Winforms 솔루션을 위해 MVP를 어떻게 설정합니까?


14

나는 과거에 MVP와 MVC를 사용해 왔으며, MVP가 그것이 실행 흐름을 훨씬 더 잘 제어한다는 점에서 MVP를 선호합니다.

인프라 (데이터 저장소 / 리포지토리 클래스)를 만들어 샘플 데이터를 하드 코딩 할 때 문제없이 사용하므로 이제 GUI로 이동하여 MVP를 준비하고 있습니다.

섹션 A

  1. MVP가 뷰를 시작점으로 사용하는 것을 보았습니다. 즉, 뷰 생성자 메소드에서 프리젠터를 작성합니다. 그러면 프리젠터가 모델을 작성하고 필요에 따라 이벤트를 연결합니다.

  2. 또한 발표자를 뷰 포인트, 모델, 발표자가 생성되는 진입 점으로 보았습니다.이 발표자는 이벤트를 연결하기 위해 생성자에 뷰 및 모델 객체가 제공됩니다.

  3. 2에서와 같이 모델은 발표자에게 전달되지 않습니다. 대신 모델은 메소드가 호출되고 응답이 직접 리턴되는 정적 클래스입니다.

섹션 B

뷰와 모델을 동기화 상태로 유지하는 측면에서 보았습니다.

  1. 보기의 값이 변경 될 때마다 (예 : TextChanged.Net / C #의 이벤트) 이것은 DataChangedEvent모델에 전달 된를 실행하여 항상 동기화 상태를 유지합니다. 그리고 모델이 변경되는 경우 (예 : 청취하는 백그라운드 이벤트) 뷰를 올리는 것과 동일한 아이디어를 통해 뷰가 업데이트됩니다 DataChangedEvent. 사용자가 변경 사항을 커밋하려고하면 변경 사항이 적용 SaveEvent되어 모델로 전달되어 저장됩니다. 이 경우 모델은 뷰의 데이터를 모방하고 동작을 처리합니다.

  2. # b1과 유사하지만 뷰는 항상 모델과 동기화되지 않습니다. 대신 사용자가 변경 사항을 커밋하려고하면 SaveEvent해고되고 발표자는 최신 세부 정보를 가져 와서 모델에 전달합니다. 이 경우 모델은 뷰 데이터에 대한 조치가 필요할 때까지 뷰 데이터에 대해 알지 못하며,이 경우 필요한 모든 세부 사항이 전달됩니다.

섹션 C

뷰에 비즈니스 오브젝트 표시, 즉 기본 데이터가 아닌 오브젝트 (MyClass) (int, double)

  1. 보기에는 도메인 / 비즈니스 오브젝트로 표시 할 모든 데이터에 대한 특성 필드가 있습니다. 보기는 TreeView의 노드로 속성을 처리하더라도 속성 을 view.Animals노출합니다 IEnumerable<IAnimal>. 그런 다음 선택한 동물의 경우 속성으로 노출 SelectedAnimal됩니다 IAnimal.

  2. 뷰에는 도메인 객체에 대한 지식이 없으며 기본 / 프레임 워크 (.Net / Java) 포함 객체 유형에 대한 속성 만 노출됩니다. 이 경우 발표자는 어댑터 오브젝트에 도메인 오브젝트를 전달한 다음 지정된 비즈니스 오브젝트를보기에 표시된 제어로 변환합니다. 이 경우 어댑터는 뷰뿐만 아니라 뷰의 실제 컨트롤에도 액세스 할 수 있어야하므로보다 밀접하게 연결됩니다.

섹션 D

단일 컨트롤을 만드는 데 사용되는 다중 뷰 즉, 다른 유형의 객체를 저장하는 것과 같은 간단한 모델로 복잡한 뷰를 가질 수 있습니다. 적절한 컨트롤이 표시된 항목을 클릭 할 때마다 측면에 메뉴 시스템이있을 수 있습니다.

  1. 뷰 인터페이스를 통해 노출되는 모든 개별 컨트롤을 포함하는 하나의 거대한 뷰를 만듭니다.

  2. 몇 가지 견해가 있습니다. 메뉴에 대한 하나의보기와 빈 패널이 있습니다. 이보기는 필요한 다른보기를 작성하지만 표시하지 않습니다 (visible = false).이보기는 포함 된 각보기 (예 : 하위보기)의 인터페이스도 구현하므로 한 발표자에게 노출 될 수 있습니다. 빈 패널은 다른보기 ( Controls.Add(myview)) 및 ( (myview.visible = true) 로 채워집니다 . 이러한 "자식"보기에서 발생한 이벤트는 부모보기에 의해 처리되며,이보기는 이벤트를 발표자에게 전달하고, 그 반대로 자식 요소에 이벤트를 다시 공급하기 위해 비자를 전달합니다.

  3. 각 상위 뷰 또는 작은 하위 뷰는 각각 자체 발표자와 모델에 연결됩니다. 문자 그대로 뷰 컨트롤을 기존 양식에 드롭 할 수 있으며 기능이 준비되어 있으므로 장면 뒤의 발표자에 배선하면됩니다.

섹션 E

위의 예에서 MVP가 수행 된 방식을 기반으로 모든 인터페이스가 제공되는 경우 상호 호환되지 않을 수 있으므로이 답변에 영향을 미칩니다.

  1. 모든 것에는 인터페이스,보기, 발표자 및 모델이 있습니다. 그러면 이들 각각은 분명히 구체적인 구현을 갖습니다. 구체적인 견해, 모델 및 발표자가 하나 뿐인 경우에도 마찬가지입니다.

  2. 뷰와 모델에는 인터페이스가 있습니다. 뷰와 모델이 다를 수 있습니다. 발표자는 뷰 및 모델 객체를 생성 / 제공하며 객체간에 메시지를 전달하는 역할 만합니다.

  3. 뷰에만 인터페이스가 있습니다. 모델에는 정적 메소드가 있으며 작성되지 않으므로 인터페이스가 필요하지 않습니다. 다른 모델을 원하면 발표자는 다른 정적 클래스 메서드 집합을 호출합니다. 정적 인 모델은 발표자와 연결되지 않습니다.

개인적인 생각

내가 제시 한 모든 다른 변형 (대부분 나는 어떤 형태로 사용했을 것입니다)에서 더 많은 것이 있다고 확신합니다. 나는 데이터 복제 및 이벤트 발생을 줄이기 위해 비즈니스 로직을 MVP, B2 외부에서 재사용 할 수 있도록 A3을 선호합니다. 다른 클래스에 추가하지 않는 C1은 소량의 테스트 불가능한 논리를 뷰에 넣었는지 (도메인 객체가 시각화되는 방법) 코드 검토 또는 애플리케이션에서 간단히 볼 수 있습니다. 논리가 복잡한 경우 어댑터 클래스에 동의하지만 모든 경우에 동의하지는 않습니다. 섹션 D의 경우 D1이 메뉴 예에 비해 너무 큰 뷰를 생성한다고 생각합니다. 나는 전에 D2와 D3을 사용했다. D2의 문제는 이벤트를 발표자에서 올바른 자식보기로 라우팅하기 위해 많은 코드를 작성해야하며 드래그 앤 드롭 호환이 불가능하다는 것입니다. 각각의 새로운 제어는 단일 발표자를 지원하기 위해 더 많은 배선이 필요합니다. D3은 내가 선호하는 선택이지만 뷰가 매우 간단하거나 재사용 할 필요가없는 경우에도 뷰를 처리하기 위해 발표자와 모델로 더 많은 클래스를 추가합니다. 나는 상황에 따라 D2와 D3의 혼합이 가장 좋다고 생각합니다. 섹션 E와 관련하여 인터페이스가있는 모든 것이 과도 할 수 있다고 생각합니다. 도메인 / 비즈니스 오브젝트에 대해 이미 수행하고 있으며 "디자인"에서 이점을 얻지 못하는 경우가 많지만 테스트에서 오브젝트를 조롱하는 데 도움이됩니다. 개인적으로 나는 이전에 작업 한 2 개의 프로젝트에서 E3가 사용되는 것을 보았지만 E2를 고전적인 솔루션으로 볼 것입니다. 나는 상황에 따라 D2와 D3의 혼합이 가장 좋다고 생각합니다. 섹션 E와 관련하여 인터페이스가있는 모든 것이 과도 할 수 있다고 생각합니다. 도메인 / 비즈니스 오브젝트에 대해 이미 수행하고 있으며 "디자인"에서 이점을 얻지 못하는 경우가 많지만 테스트에서 오브젝트를 조롱하는 데 도움이됩니다. 개인적으로 나는 이전에 작업 한 2 개의 프로젝트에서 E3가 사용되는 것을 보았지만 E2를 고전적인 솔루션으로 볼 것입니다. 나는 상황에 따라 D2와 D3의 혼합이 가장 좋다고 생각합니다. 섹션 E와 관련하여 인터페이스가있는 모든 것이 과도 할 수 있다고 생각합니다. 도메인 / 비즈니스 오브젝트에 대해 이미 수행하고 있으며 "디자인"에서 이점을 얻지 못하는 경우가 많지만 테스트에서 오브젝트를 조롱하는 데 도움이됩니다. 개인적으로 나는 이전에 작업 한 2 개의 프로젝트에서 E3가 사용되는 것을 보았지만 E2를 고전적인 솔루션으로 볼 것입니다.

질문

MVP를 올바르게 구현하고 있습니까? 그것에 대한 올바른 방법이 있습니까?

나는 변형이있는 Martin Fowler의 작품을 읽었으며 MVC를 처음 시작했을 때를 기억했지만 개념을 이해했지만 처음에는 진입 점이 어디 있는지 알아낼 수 없었습니다. 모든 것이 자체 기능이 있지만 원래는 제어하고 만드는 것 MVC 객체 세트


2
이 질문을하는 이유는 거의 첫 번째 시도에서 올바르게하고 싶습니다. 동일한 패턴에 대해 다른 변형을 사용하여 6 개의 응용 프로그램을 만드는 것이 아니라 표준 MVP를 따르는 것이 좋습니다.
JonWillis

완벽합니다 ... 오랫동안 묻고 싶었습니다
The King

답변:


4

여기에 제시 한 많은 것들이 매우 합리적이고 건전합니다. 선택 사항 중 일부는 응용 프로그램의 세부 사항과 어떤 것이 "느낌"인지에 달려 있습니다. 대부분의 경우와 마찬가지로 하나의 정답은 없습니다. 일부 선택은 여기에서 의미가 있으며 다음 선택과 상황에 따라 선택이 완전히 잘못 될 수 있습니다. 앱의 세부 사항을 알지 못하면 올바른 방향으로 가고 있으며 신중하고 신중한 결정을 내렸다고 생각합니다.

저는 발표자가 거의 항상 진입 점이어야한다고 생각합니다. UI를 진입 점으로 사용하면 UI에 너무 많은 논리가 적용되고 큰 코딩 변경없이 새 UI를 대체 할 수있는 기능이 사라집니다. 그리고 그것이 바로 발표자의 역할입니다.


어쩌면 내가 물어봐야 할 질문은 MVP를 잘못 사용하는 방법 중 하나 일 것입니다. 다양한 시나리오에 적합한 변형에 동의하지만 일반적으로 허용되는 접근 방식이 있어야한다고 생각합니다. MVP의 예는 도메인 개체를 편집하고 변경 사항을 저장하기위한 간단한 예이며 거의 모두 동일한 요구 사항입니다. 그러나 동일한 목적을 가진 예에서 위의 변형이 생성되었습니다. 방금 발표자에서 처리하기 위해 뷰에서 발생하는 이벤트를 사용하여 앱의 일부를 코딩했지만 뷰가 발표자에 대한 참조를 보유하고 메소드를 직접 호출하도록 할 수있었습니다.
JonWillis

단위 테스트를 거치지 않은 것을 정당화하기 위해 뷰를 단순화하려는 모든 노력에 동의 할 것입니다. 그러면 발표자가 제어해야합니다. 이것에 대한 나의 유일한 관심은 (내 머리를 생각하면 잘못 될 수 있음) winforms / usercontrols가 부모 요소에 연결되어 있어야하며 발표자에게 추가 논리가 필요한지 궁금해한다는 것입니다.
JonWillis

@Jon-MVP가 틀린 방법? 내 책에서 그 견해가 발표자에 대해 알 때입니다. 그것이 작동한다는 의미에서 "잘못"되지 않을 수도 있지만 MVP 일뿐 만 아니라 그 시점에서 다른 것으로 변형됩니다. 디자인 패턴의 문제점은 예제가 항상 깨끗하고 단순하다는 것입니다. 그런 다음 처음으로 구현하려고 할 때 현실 세계가 뛰어 올라 '이봐 야 실제 앱은 그 엉뚱한 예보다 훨씬 복잡합니다.' 그것이 당신의 성장이 시작되는 곳입니다. 당신과 앱의 ​​상황에 맞는 것을 찾으십시오.
Walter

충고 감사합니다. 대학에서 MVC를 배우는 것을 기억합니다. 훌륭하게 들리지만 빈 캔버스로 시작 위치와 작동 방식이 궁금합니다. MVP가 잘못되었다는 점에서, 내가 MVC의 아이디어 / 변형이 잘못된 방식으로 게시했음을 의미합니다. 즉, 발표자가 발표자가 어떻게 작동하는지 알 때입니다. 또는보기에 발표자 또는 콘크리트 유형 등의 인터페이스에 대한 참조가 있어야합니다. 모두 동일한 목적으로 작동 할 수있는 다양한 변형이 있습니다.
JonWillis

1
@Jon-MVP의 정신에 따라 다양한 변형이 가능합니다. 인터페이스 또는 구체적인 유형으로 작업하는 한 앱의 상황에 따라 다릅니다. 앱이 상당히 작고 복잡하지 않은 경우 인터페이스를 추가 할 필요가 없습니다. 앱이 X 아키텍처를 구현해야한다는 것이 분명해질 때까지 가능한 한 간단하게 유지하고 싶습니다. 자세한 내용은 다음 답변을 참조하십시오. programmers.stackexchange.com/questions/34547/…
Walter

4

.NET 2.0 Winforms 앱에서 수정 된 MVP 형식을 사용합니다. 우리가 놓친 두 부분은 WPF ViewModel의 수정 된 어댑터와 데이터 바인딩을 추가하는 것입니다. 우리의 구체적인 패턴은 MVPVM입니다.

우리는 디자이너 친화적 인보기 우선으로 연결되는 사용자 정의 사용자 컨트롤을 제외하고 거의 모든 경우에 발표자 우선으로 연결합니다. 의존성 주입, 코드 생성 ViewModels, 발표자를위한 BDD, 모델을위한 TDD / TED를 사용합니다.

VM은 변경 될 때 PropertyChanged를 발생시키는 방대하고 평평하며 방대한 속성입니다. 코드 (및 관련 운동 단위 테스트)를 통해이를 쉽게 생성 할 수있었습니다. 사용자 상호 작용 가능한 컨트롤을 읽고 쓰고, 활성화 된 상태를 제어하는 ​​데 사용합니다. ViewModel은 View와 결합되어 있습니다. 왜냐하면 우리는 다른 모든 것 근처에서 데이터 바인딩을 사용하기 때문입니다.

View는 때때로 VM이 할 수없는 일을 수행하기위한 방법을 제공합니다. 이것은 일반적으로 항목의 가시성 (WinForms가 까다로울 수 있음)과 데이터 바인딩을 거부하는 것을 제어합니다. 보기는 항상 "로그인"또는 "다시 시작"과 같은 이벤트를 사용자 행동에 따라 적절한 EventArgs와 함께 노출합니다. "View.ShowLoginBox"와 같은 핵을 사용하지 않았다면, 일반적인 설계 요구 사항을 충족하는 한 View는 완전히 호환됩니다.

이 패턴을 없애려면 약 6-8 개월이 걸렸습니다. 그것은 많은 조각을 가지고 있지만 매우 유연하고 매우 강력합니다. 우리의 특정 구현은 매우 비동기식이며 이벤트 중심이며, 이는 설계 동작의 부작용이 아닌 다른 요구 사항의 인공물 일 수 있습니다. 예를 들어 VM이 상속하는 기본 클래스에 스레드 동기화를 추가했습니다 (이벤트를 발생시키기 위해 단순히 OnPropertyChanged 메서드를 노출했습니다). 그러면 이제 다중 스레드 발표자와 모델을 가질 수 있습니다.


MVPVM에 상업적 관심이있을 수 있지만 괜찮다면 샘플 코드를 제공 할 수 있습니까? 참고로, 모델에서 수행하는 작업과 발표자에게 전달되는 작업에 대한 선을 어디에 그리십니까? 나는 발표자가 뷰 이벤트를 처리하고 모델을 호출하여 데이터 계층에 액세스하여 발표자가 비즈니스 모델을 발표자로 대체하는 모델까지 비즈니스 객체를 모델에 전달하는 발표자에게 매우 기본적임을 보았습니다.
JonWillis

예, 예를 마무리하겠습니다. 사내 교육 도구로 사용하기 때문에 비즈니스에 맞게 조정됩니다.
Bryan Boettcher

감사합니다. 주말에 살펴보고 이해할 수 있는지 확인할 것입니다.
JonWillis

@insta-링크가 다운되었습니다. 어딘가에 다시 업로드 할 수 있습니까?
Yves Schelpe

1
크랩 나는 방금 일주일 전에 그것을 삭제했습니다. 수치 :(
Bryan Boettcher

2

.Net 용으로 수정 된 후 스스로 확장 한 PureMvc 버전을 사용하고 있습니다.

Flex 애플리케이션에서 PureMvc를 사용하는 데 익숙했습니다. 베어 본 유형의 프레임 워크이므로 사용자 정의하려는 경우 상당히 쉽게 적용 할 수 있습니다.

나는 다음과 같은 자유를 얻었습니다.

  • 리플렉션을 사용하여 view-mediator에서 개인 속성을 가져 와서 폼 클래스로 나가서 중재하는 각 컨트롤에 대한 (비공개) 참조를 가져올 수있었습니다.
  • 리플렉션을 사용하여 컨트롤을 일반 중재자의 이벤트 서명에 자동으로 연결할 수 있으므로 sender 매개 변수를 켜기 만하면됩니다.
  • 일반적으로 PureMvc는 파생 된 중개자가 문자열 배열을 리턴하는 함수에서 알림 관심사를 정의하기를 원합니다. 내 관심사는 대부분 정적이고, 중재자 관심사를보다 쉽게 ​​볼 수 있기를 원했기 때문에 중재자가 특정 서명을 사용하여 멤버 변수 세트로 관심사를 선언 할 수 있도록 수정했습니다. _ _ _ <classname> _ <알림 이름>. 이 방법으로 함수 내부를 보지 않고 IDE 멤버 트리를 사용하여 진행되는 작업을 볼 수 있습니다.

PureMvc에서는 Command를 사용하여 진입 점으로 사용할 수 있습니다. 일반적인 시작 명령은 모델을 가능한 범위까지 설정 한 다음 MainForm을 작성하고 해당 양식에 대해 중재자를 작성 및 등록한 다음 Application을 실행합니다. 양식에.

양식의 중재자는 모든 하위 중재자를 설정해야하며 일부는 다시 반사 트릭을 사용하여 자동화 할 수 있습니다.

내가 사용하는 시스템은 당신의 의미를 이해하면 드래그 앤 드롭 호환됩니다. 실제 양식은 모두 VS로 작성되었지만 제 경험은 정적으로 작성된 제어 기능이있는 양식에만 있습니다. 동적으로 생성 된 메뉴 항목과 같은 것은 해당 메뉴 또는 하위 메뉴에 대한 조정자를 약간 조정하여 실현 가능해 보입니다. 털이 많은 곳은 중재자가 고정 된 루트 요소가없고 동적 '인스턴스'중재자를 만들었을 때입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.