2009-12-11 1 views
2

나는이 일반적인 디자인, 리팩토링에 문제 또는 "선별"이 있습니다멀티 스레드 프로그램의 두 "깊은"부분을 서로 대화하는 패턴은 무엇입니까?

을 나는이 플러그인 라이브러리의 번호를 사용하여 데이터를 검색하는 기존 다중 스레드 C++ 응용 프로그램입니다. 현재 검색 인터페이스에서 주어진 플러그인은 검색 문자열과 QList 객체에 대한 포인터를받습니다. 다른 스레드에서 실행되는 플러그인은 나가서 다양한 데이터 원본 (로컬 및 웹)을 검색하고 해당 개체를 목록에 추가합니다. 플러그인이 돌아 오면 메인 프로그램은 여전히 ​​별도의 스레드에 있으며이 데이터를 로컬 데이터 저장소에 추가 처리하여 뮤텍스를 사용하여이 삽입 포인터를 보호합니다. 따라서 각 플러그인은 비동기 적으로 데이터를 리턴 할 수 있습니다.

QT 기반 플러그인 라이브러리는 메시지 전달을 기반으로합니다. 상당수의 플러그인이 이미 응용 프로그램 용으로 작성되고 테스트되었으며 상당히 잘 작동합니다.

더 많은 플러그인을 작성하고 기존 응용 프로그램을 활용하고 싶습니다.

문제는 새로운 플러그인이 애플리케이션에서 더 많은 정보를 필요로한다는 것입니다. 검색 할 때 로컬 데이터 저장소 자체에 대한 간헐적 인 액세스가 필요합니다. 그래서 이것을 얻으려면 데이터를 저장하는 해시 배열과 저장소에 대한 다중 액세스를 보호하는 뮤텍스에 직접 또는 간접적으로 액세스해야합니다. "카탈로그"개체에 추가 메서드를 추가하여 액세스를 캡슐화한다고 가정합니다.

나는이 새로운 플러그인을 쓰는 세 가지 방법을 볼 수 있습니다. 플러그인을로드 할 때

  1. 는 시작 그들 내 "카탈로그"에 대한 포인터를 전달합니다. 새 플러그인에 대한 추가 정보, "보이지 않는"인터페이스가됩니다. 이것은 쉽고 빠르며, OO에 따르면 은 완전히 잘못되었지만 나는 미래의 문제가 무엇인지 알 수 없습니다. 나는 새로운 플러그인 라이브러리에 대한 를 호출 할 수있는 두 번째 기능을 가지고 있으므로
  2. 가 기존의 인터페이스 방법/메시지를 추가, 메시지가 에 플러그인에 대한 카탈로그를 포인터를 전달한다. 이 은 플러그인에 대해 쉽게 될 수 있지만 은 내 주 코드를 복잡하게 만들고 은 일반적으로 나쁨으로 보입니다.

  3. 플러그인 인터페이스를 다시 디자인하십시오. OO에 따르면 ""은 다른 부가적인 이점을 가질 수 있지만 은 " "의 모든 종류를 다시 작성해야합니다.

그래서, 내 질문은

A. 사람이 콘크리트 위험 내게 옵션 1의를 말할 수 있습니까?

B. 이러한 종류의 문제에 적합한 알려진 패턴이 있습니까?

EDIT1 : 그것은 반복을 통해 아웃 코드의

elsewhere(spec){ 
    QList<CatItem> results; 
    plugins->getResult(spec, &results); 
    use_list(results); 
} 

... 
void PluginHandler::getResults(QString* spec, QList<CatItem>* results) 
{ 
    if (id->count() == 0) return; 
    foreach(PluginInfo info, plugins) { 
     if (info.loaded) 
      info.obj->msg(MSG_GET_RESULTS, (void*) spec, (void*) results); 
    } 
} 

: 같은

플러그인 루틴을 호출하기위한 일반적인 기능이 보인다. 나는 그것을 깰 때보 다 오히려 연장 할 것입니다.

답변

4

"OO에 따르면 완전히 잘못 되었습니까?"플러그인이 해당 객체에 액세스해야하고 보존하려는 추상화를 위반하지 않으면 올바른 해결책입니다.

내게는 플러그인 자체가 목록 자체에 액세스해야한다고 결정한 순간 추상화 된 것처럼 보였습니다. 전체 응용 프로그램의 아키텍처를 폭발 시켰습니다. 실제 목록 자체에 액세스해야합니까? 왜 그렇습니까? 너 뭐야? 그것으로부터의 필요성? 그 정보를보다 합리적인 방법으로 제공 할 수 있습니까? 하나는 공유 리소스에 대한 경합을 증가시키지 않고 (경합 및 교착 상태와 같은 미묘한 멀티 스레딩 버그의 위험을 증가시키지 않음) 2) 앱의 나머지 아키텍처를 손상시키지 않습니다. 목록과 클라이언트 사이에서 비동기 허용)

당신이 근본적으로 (사용자 응용 프로그램의 기본 아키텍처를 위반하는) 수행하려고 시도하는 것이기 때문에 그것이 080이라고 생각하면 이 아닙니다. 다시하고있어.

+0

단어는 강하지 만 정확합니다. –

1

글쎄, 옵션 1은 결국 옵션 3입니다. 메인 앱에서 추가 데이터를 받기 위해 플러그인 API를 다시 디자인하고 있습니다.

'카탈로그'가 잘 구현되고 해시 및 뮤텍스 백업 저장소의 모든 구현 세부 사항을 숨기고있는 한 나쁘지는 않으며 IMO 목적을 충분히 충족시킬 수있는 간단한 재 설계입니다.

이제 카탈로그에 구현 세부 사항이 누설되면 메시지를 사용하여 저장소를 쿼리하고 필요한 데이터로 응답을받는 것이 좋습니다.

+0

글쎄, 카탈로그는 플러그인의 글로벌 변수이며 플러그인 인터페이스는 카탈로그에 액세스 할 것이라는 것을 분명히하지는 않지만 그 외에 ... –

+0

하지만 카탈로그의 인터페이스는 어떻게 생겼습니까? 벡터 응답 = catalog.query (params); 여기서 쿼리는 모든 것을 처리합니다 (그래서 플러그인은 해시와 뮤텍스가 있는지를 모릅니다). 아니면 (catalog.mutex) 획득합니다. 응답 = catalog.hash [key]; 릴리스 (catalog.mutex); ? 후자라면,하지 마십시오. 전자의 경우에는 아무런 문제가 없습니다. 글로벌 변수가 되더라도 약간의 냄새가납니다. 왜 저장소를 쿼리하고 일치하는 데이터를 반환하는 메시지를 구현하는 것이 어렵습니까? 플러그인이 전역 상태를 엉망으로 만드는 옵션이 없기 때문에 가장 깨끗한 옵션입니다. –

+0

아직 외부 카탈로그 인터페이스를 작성하지 않았습니다. 그래도 쓰는 것은 그리 어렵지 않을 것입니다. 첫 번째 옵션은 그냥 두 번째 옵션을 호출 할 수있는 것처럼 보이므로 항상 첫 번째 옵션을 수행 할 수 있습니다. –

1

죄송합니다. 귀하의 질문을 3 번 다시 읽었을 때 제 대답이 너무 단순했을 수도 있습니다.

"카탈로그"는 독립된 개체입니까? 그렇지 않은 경우 자체 객체로 포장 할 수 있습니다. 카탈로그는 완전히 안전해야합니다 (threadsafe 포함).

이 작업을 수행하면 카탈로그를 새 플러그인에 전달하는 것이 완벽하게 유효합니다. 여러 레이어를 통과 시킬지 염려하면 카탈로그 팩토리를 만들 수 있습니다.

내가 아직도 뭔가를 오해하고있는 경우 미안하지만이 방법에 문제가있는 것은 아닙니다. 카탈로그가 데이터베이스 객체 나 컬렉션과 같이 컨트롤 밖에있는 객체 인 경우에는 멋진 인터페이스로 제어 할 수있는 무언가에 캡슐화해야합니다.

카탈로그가 프로그램 전체에서 여러 부분에서 사용되는 경우 공장을 살펴볼 수도 있습니다 (가장 단순한 것이 싱글 톤으로 저하됨). 팩토리를 사용하면 카탈로그를 Catalog.getType ("Clothes")으로 소환 할 수 있습니다. 또는 무엇이든. 그런 식으로 당신은 그것을 지나치지 않고 하나를 원하는 모든 사람들에게 같은 대상을내어주고 있습니다.

(이것은 싱글 톤과 매우 비슷하지만 팩토리로 코딩하면 거의 둘 이상이 될 것임을 상기시켜줍니다. Catalog.setType ("Clothes",. ..); 테스트 용

+0

좀 더 자세한 정보를 주시겠습니까? 내 컨텍스트에서 어떻게 보일까요? (기능을 붙여 넣었습니다) –