MVVM은 무의미합니까? [닫은]


91

정통 MVVM 구현은 무의미합니까? 새 응용 프로그램을 만들고 있으며 Windows Forms 및 WPF를 고려했습니다. WPF는 미래에 대비하고 많은 유연성을 제공하기 때문에 선택했습니다. 코드가 적고 XAML을 사용하여 UI를 크게 변경할 수 있습니다.

WPF에 대한 선택은 분명하기 때문에 MVVM을 응용 프로그램 아키텍처로 사용하여 혼합 가능성, 분리 문제 및 단위 테스트 가능성을 제공하므로 끝까지 진행할 수 있다고 생각했습니다. 이론적으로는 UI 프로그래밍의 성배처럼 아름답게 보입니다. 이 짧은 모험; 그러나 실제로 두통이되었습니다. 실제로 예상했던대로, 저는 한 문제를 다른 문제와 교환했습니다. 나는 올바른 결과를 얻고 더 나은 프로그래머가 될 수 있도록 올바른 방식으로 일을하고 싶다는 점에서 강박적인 프로그래머 인 경향이 있습니다. MVVM 패턴은 생산성에 대한 내 테스트를 막았고 방금 큰 엉뚱한 해킹으로 변했습니다!

명확한 사례는 모달 대화 상자에 대한 지원을 추가하는 것입니다. 올바른 방법은 대화 상자를 표시하고이를 뷰 모델에 연결하는 것입니다. 이것을 작동시키는 것은 어렵습니다. MVVM 패턴의 이점을 얻으려면 애플리케이션 계층 전체에 걸쳐 여러 위치에 코드를 배포해야합니다. 또한 템플릿 및 람바 식과 같은 난해한 프로그래밍 구조를 사용해야합니다. 머리를 긁적 거리며 화면을 응시하게 만드는 것. 이로 인해 유지 관리 및 디버깅은 내가 최근에 발견 한대로 일어나기를 기다리는 악몽이됩니다. 두 번째로 호출했을 때 예외가 발생할 때까지 about box가 잘 작동하여 닫히면 대화 상자를 다시 표시 할 수 없다고 말했습니다. 대화 창에 닫기 기능을위한 이벤트 핸들러를 추가해야했습니다. 다른 하나는 IDialogView 구현에 있고 마지막으로 다른 하나는 IDialogViewModel에 있습니다. 나는 MVVM이 그런 사치스러운 해커로부터 우리를 구할 것이라고 생각했습니다!

이 문제에 대한 경쟁 솔루션을 가진 여러 사람들이 있으며 모두 해킹이며 깨끗하고 쉽게 재사용 가능하며 우아한 솔루션을 제공하지 않습니다. 대부분의 MVVM 툴킷은 대화 상자를 무시하고 처리 할 때 사용자 지정 인터페이스 나 뷰 모델이 필요하지 않은 경고 상자 일뿐입니다.

나는 MVVM 뷰 패턴, 적어도 그것의 정통 구현을 포기할 계획입니다. 어떻게 생각해? 문제가 있다면 그만한 가치가 있었습니까? 나는 단지 무능한 프로그래머입니까, 아니면 MVVM이 과장된 것이 아닌가?


6
나는 항상 MVVM이 과잉 엔지니어링인지 여부에 대해 의문을 제기했습니다. 흥미로운 질문입니다.
Taylor Leese

11
MVVM 및 MVC와 같은 패턴은 일부 수정을 수행하거나 구성 요소를 변경해야 할 때까지 과도한 엔지니어링처럼 보입니다. 처음으로 그렇게해야 할 때, 모든 의식 은 그 자체로 가치가 있습니다.
Robert Harvey

41
람다는 난해한가요? 나에게 뉴스.
Ray Booysen 2010 년

5
@Ray-하하, 그 댓글에 +1! : D
Venemo 2010-06-11

7
Alan Cooper가 10 년 전에 About Face 에서 지적했듯이 UI를 디자인하고 모달 대화 상자가 엣지 케이스가 아니라면 뭔가 잘못하고있을 것입니다.
Robert Rossney

답변:


61

내 대답이 조금 길어지면 미안하지만 나를 비난하지 마십시오! 귀하의 질문도 길다.

요약하면 MVVM은 무의미하지 않습니다.

명확한 사례는 모달 대화 상자에 대한 지원을 추가하는 것입니다. 올바른 방법은 대화 상자를 표시하고이를 뷰 모델에 연결하는 것입니다. 이것을 작동시키는 것은 어렵습니다.

네, 정말 그렇습니다.
그러나 MVVM은 UI의 모양과 논리를 구분하는 방법을 제공합니다. 아무도 당신이 모든 곳에서 그것을 사용하도록 강요하지 않으며 아무도 당신이 모든 것에 대해 별도의 ViewModel을 만들도록 이마에 총을 들고 있지 않습니다.

이 특정 예제에 대한 솔루션은 다음과 같습니다
. UI가 특정 입력을 처리하는 방법은 ViewModel의 업무가 아닙니다. View의 .xaml.cs 파일에 코드를 추가하여 대화 상자를 인스턴스화하고 DataContext와 동일한 ViewModel 인스턴스 (또는 필요한 경우 다른 항목)를 설정합니다.

MVVM 패턴의 이점을 얻으려면 애플리케이션 계층 전체에 걸쳐 여러 위치에 코드를 배포해야합니다. 또한 템플릿 및 람바 식과 같은 난해한 프로그래밍 구조를 사용해야합니다.

글쎄, 여러 곳에서 사용할 필요가 없습니다. 이것이 내가 그것을 해결하는 방법입니다.

  • 보기에 XAML을 추가하고 .xaml.cs에는 아무것도 추가하지 않습니다.
  • ViewModel 내부에 모든 앱 로직 (UI 요소로 직접 작동하는 항목 제외) 작성
  • UI에서 수행해야하지만 비즈니스 로직과 관련이없는 모든 코드는 .xaml.cs 파일로 이동합니다.

MVVM의 목적은 주로 응용 프로그램의 논리와 구체적인 UI를 분리하여 UI를 쉽게 수정 (또는 전체 교체) 할 수 있도록하는 것이라고 생각합니다.
다음 원칙을 사용합니다. View는 ViewModel에서 원하는 것을 알고 가정 할 수 있지만 ViewModel은 View에 대해 아무것도 알 수 없습니다.
WPF는이를 정확하게 달성하는 데 사용할 수있는 멋진 바인딩 모델을 제공합니다.

(BTW, 템플릿 및 람다 식은 올바르게 사용하면 난해하지 않습니다. 그러나 원하지 않으면 사용하지 마십시오.)

머리를 긁적 거리며 화면을 응시하게 만드는 것.

네, 느낌을 알아요. MVVM을 처음 보았을 때 제가 느꼈던 바로 그 느낌입니다. 그러나 일단 익숙해지면 더 이상 기분이 나쁘지 않을 것입니다.

나는 약 상자가 잘 작동했습니다 ...

약 상자 뒤에 ViewModel을 배치하는 이유는 무엇입니까? 그게 중요하지 않습니다.

대부분의 MVVM 툴킷은 대화 상자를 무시하고 처리 할 때 사용자 지정 인터페이스 나 뷰 모델이 필요하지 않은 경고 상자 일뿐입니다.

예, UI 요소가 같은 창이나 다른 창에 있거나 현재 화성을 공전하고 있다는 사실은 ViewModels의 관심사가 아니기 때문입니다.
우려 사항 분리

편집하다:

제목이 Build your own MVVM framework 인 매우 멋진 비디오가 있습니다 . 볼만한 가치가 있습니다.


2
마지막 세 단어는 +1입니다. 그러나 나머지 답변도 좋습니다. :)
Robert Harvey

12
코드 숨김 사용에 대한 조언은 +1. MVVM에서 코드 숨김을 사용하는 것이 "나쁘다"는 것은 일반적인 오해입니다.하지만 순전히 UI 관련 항목에 대해서는 그렇게하는 것이 좋습니다.
Thomas Levesque

@Thomas : 네, 더 이상 동의 할 수 없었습니다. 나는 사람들이 모든 코드 (심지어 UI 관련)를 ViewModel에 넣는 여러 구현을 보았다. 왜냐하면 (그들에 따르면) "코드가있는 곳"이기 때문이다. 꽤 해키했습니다.
Venemo

3
@Venemo, 사용자 정의 Behaviors와 같은 기술을 사용하여 코드 숨김에 넣고 싶은 많은 항목을 캡슐화 할 수 있다고 생각합니다. 이는 글루 코드를 반복적으로 작성하는 경우에 유용합니다. 그러나 일반적으로 어색한 XAML을 함께 해킹하는 것보다 접착제에 코드 숨김을 사용하는 것이 더 낫다고 생각합니다. 내 생각에 주요 관심사는 코드 숨김에 단위 테스트를 보증 할 수있을만큼 정교한 코드가 없는지 확인하는 것입니다. 충분히 복잡한 것은 ViewModel 또는 Behavior 또는 MarkupExtension과 같은 확장 클래스에 캡슐화하는 것이 좋습니다.
Dan Bryant

7
@ Thomas : 맞습니다. MVVM에 대한 가장 큰 신화는 MVVM의 목적이 코드 숨김을 제거하는 것입니다. 목적은 비 UI ocde를 코드 뒤에서 제거하는 것입니다. ViewModel에 UI 전용 코드를 넣는 것은 문제 도메인 코드를 코드 숨김에 넣는 것만큼이나 나쁩니다.
Jim Reineri 2011-08-24

8

이것을 작동시키는 것은 어렵습니다. MVVM 패턴의 이점을 얻으려면 애플리케이션 계층 전체에 걸쳐 여러 위치에 코드를 배포해야합니다. 또한 템플릿 및 람바 식과 같은 난해한 프로그래밍 구조를 사용해야합니다.

일반적인 모달 대화 상자의 경우? 확실히 여기서 뭔가 잘못하고 있습니다. MVVM 구현이 그렇게 복잡 할 필요는 없습니다.

MVVM과 WPF에 익숙하지 않다는 점을 감안할 때 모든 곳에서 최적이 아닌 솔루션을 사용하고있을 가능성이 높으며 일이 불필요하게 복잡해집니다. 적어도 처음 WPF를 사용할 때 그렇게했습니다. 포기하기 전에 문제가 실제로 MVVM이고 구현이 아닌지 확인하십시오.

MVVM, MVC, Document-View 등은 오래된 패턴 계열입니다. 단점이 있지만 설명하는 종류의 치명적인 결함은 없습니다.


5

저는 PRISM을 사용하는 매우 복잡한 MVVM 개발 중이므로 이미 이러한 종류의 문제에 대처해야했습니다.

내 개인적인 결론 :

MVVM 대 MVC / PopUps & Co

  • MVVM은 정말 훌륭한 패턴이며 대부분의 경우 WPF의 강력한 데이터 바인딩 덕분에 MVC를 완전히 대체합니다.
  • 발표자로부터 직접 서비스 계층을 호출하는 것은 대부분의 경우 합법적 인 구현입니다.
  • {Binding Path = /} 구문 덕분에 매우 복잡한 List / Detail 시나리오도 순수한 MVVM으로 구현할 수 있습니다.
  • 그럼에도 불구하고 여러 뷰 간의 복잡한 조정을 구현해야 할 때 컨트롤러는 필수
  • 이벤트를 사용할 수 있습니다. 컨트롤러에 IView (또는 AbstractObserver) 인스턴스를 저장하는 것을 의미하는 이전 패턴은 더 이상 사용되지 않습니다.
  • 컨트롤러는 IOC 컨테이너를 통해 각 Presenter에 주입 할 수 있습니다.
  • Prism의 IEventAggregator 서비스는 컨트롤러의 유일한 용도가 이벤트 디스패치 인 경우에 가능한 또 다른 솔루션입니다 (이 경우 컨트롤러를 완전히 대체 할 수 있음).
  • 뷰가 동적으로 생성되는 경우 이것은 컨트롤러에 매우 적합한 작업입니다 (프리즘에서 컨트롤러는 IRegionManager에 주입 (IOC)됩니다).
  • 모달 대화 상자는 필수 확인과 같은 작업을 실제로 차단하는 것을 제외하고는 현대 복합 응용 프로그램에서 거의 사용되지 않습니다. 이러한 경우 모달 활성화는 컨트롤러 내부에서 호출되는 서비스로 추상화 될 수 있으며 고급 프레젠테이션 수준 단위 테스트를 허용하는 특수 클래스에 의해 구현 될 수 있습니다. 예를 들어 컨트롤러는 IConfirmationService.RequestConfirmation ( "are you sure")을 호출하여 런타임에 모달 대화 상자 표시를 트리거하고 단위 테스트 중에 쉽게 조롱 할 수 있습니다.

5

나는 속임수로 대화 문제를 다룬다. My MainWindow는 모든 응용 프로그램 별 대화 상자를 노출하는 IWindowServices 인터페이스를 구현합니다. 내 다른 ViewModel은 서비스 인터페이스를 가져 와서 (MEF를 사용하지만 생성자를 통해 인터페이스를 수동으로 쉽게 전달할 수 있습니다) 필요한 작업을 수행하는 데 사용할 수 있습니다. 예를 들어, 다음은 저의 작은 유틸리티 응용 프로그램에 대한 인터페이스의 모습입니다.

//Wrapper interface for dialog functionality to allow for mocking during tests
public interface IWindowServices
{
    bool ExecuteNewProject(NewProjectViewModel model);

    bool ExecuteImportSymbols(ImportSymbolsViewModel model);

    bool ExecuteOpenDialog(OpenFileDialog dialog);

    bool ExecuteSaveDialog(SaveFileDialog dialog);

    bool ExecuteWarningConfirmation(string text, string caption);

    void ExitApplication();
}

이렇게하면 모든 Dialog 실행이 한곳에 배치되고 단위 테스트를 위해 쉽게 스텁 할 수 있습니다. 대화 상자의 클라이언트가 적절한 ViewModel을 생성해야하는 패턴을 따른 다음 필요에 따라 구성 할 수 있습니다. Execute 호출 블록 및 이후 클라이언트는 Dialog 결과를보기 위해 ViewModel의 내용을 볼 수 있습니다.

보다 '순수한'MVVM 디자인은 더 깨끗한 단열과 더 복잡한 구성이 필요한 대규모 응용 프로그램에 중요 할 수 있지만 중소 규모 응용 프로그램의 경우 필요한 후크를 노출하는 적절한 서비스와 함께 실용적인 접근 방식으로 충분하다고 생각합니다. .


그러나 그것을 어디라고 부릅니까? 전달되는 것보다 IWindowServices 클래스의 함수 내에서 대화를 구성하는 것이 더 낫지 않을 것입니다. 이렇게하면 호출하는 모델 뷰가 특정 대화 구현에 대해 알 필요가 없습니다.
Joel Rodgers

인터페이스는 응용 프로그램 대화 상자에 액세스해야하는 ViewModel 인스턴스에 삽입됩니다. 대부분의 경우 대화 상자에 대한 ViewModel을 전달하고 있지만 약간 게으르고 파일 대화 상자 호출에 WPF OpenFileDialog 및 SaveFileDialog를 사용했습니다. 내 주된 목표는 단위 테스트를위한 격리 였으므로이 정도면 충분합니다. 더 나은 격리를 원하면 대화 상자에 필요한 속성을 복제하는 OpenFileViewModel 및 SaveFileViewModel을 만들 수 있습니다.
Dan Bryant

대화 상자를 사용하는 ViewModel이 열려고하는 각 대화 상자의 특정 ViewModel에 대해 알고 있다는 점에서 이것은 확실히 순수한 접근 방식이 아닙니다. 나는 이것이 상당히 깨끗하다고 ​​생각하지만 대화 사용에 필요한 매개 변수를 순수하게 노출하는 클래스를 사용하여 항상 추가 절연 레이어를 추가하여 바인딩 중에 사용되는 ViewModel 속성의 불필요한 가시성을 숨길 수 있습니다. 작은 응용 프로그램의 경우이 추가 절연이 과도하다고 생각합니다.
Dan Bryant

5

디자인 패턴은 방해가 아니라 도움을주기위한 것입니다. 좋은 개발자가되기위한 작은 부분은 "규칙을 어길 때"를 아는 것입니다. MVVM이 작업에 번거롭고 미래 가치가 노력할 가치가 없다고 판단한 경우 패턴을 사용하지 마십시오. 예를 들어, 다른 포스터가 언급했듯이 간단한 about box를 구현하기 위해 모든 오버 헤드를 거치는 이유는 무엇입니까?

디자인 패턴은 독단적으로 따르도록 의도되지 않았습니다.


2
옳은. 간단한 about box는 간단해야하지만 버전, 라이선스, 실행중인 프로세스, 회사 이름 등과 같은 정보를 표시해야한다면 어딘가에있는 모든 정보입니다. 표준 양식에서는 모든 정보를 바인딩하고 처리 할 수 ​​있습니다. MVVM은 중복되는 뷰 모델을 만들어야한다고 말합니다.
ATL_DEV

1

패턴 자체로 MVVM은 훌륭합니다. 그러나 NET 4.0 데이터 바인딩 지원과 함께 제공되는 WPF의 제어 라이브러리는 매우 제한적이며 WinForm보다 훨씬 낫지 만 여전히 바인딩 가능한 MVVM에는 충분하지 않습니다.
Bindable MVVM : ViewModel이 데이터 바인딩을 통해서만 View와 연결되는 UI입니다.
MVVM 패턴은 ViewState의 개체 표현에 관한 것으로, View와 ViewModel 간의 동기화를 유지하는 방법을 설명하지 않습니다. WPF에서는 데이터 바인딩이지만 무엇이든 될 수 있습니다. 그리고 실제로 이벤트 / 콜백을 지원하는 모든 UI 툴킷에서 MVVM 패턴을 사용할 수 있으며, WinForms의 순수 WinAPI에서 사용할 수 있습니다 (내가 했으므로 이벤트 / 콜백에 대해 더 이상 작업하지 않음). Text에서도 사용할 수 있습니다. MVVM 패턴을 사용하여 DoS의 Norton Commander를 다시 작성하는 것과 같은 콘솔.

요약하자면 MVVM은 무의미한 것이 아니라 훌륭합니다. NET 4.0 WPF의 제어 라이브러리는 휴지통입니다.

다음은 WPF를 사용하여 순수한 MVVM 방식으로 데이터 바인딩 할 수없는 ViewModel 개념의 간단한 증명입니다.

public class PersonsViewModel
{
    public IList<Person> PersonList;
    public IList<ColumnDescription> TableColumns;
    public IList<Person> SelectedPersons;
    public Person ActivePerson;
    public ColumnDescription SortedColumn;
}

WPF의 DataGrid 열 머리글을 데이터 바인딩 할 수없고, 선택한 행을 데이터 바인딩 할 수없는 등의 작업을 수행 할 수 있습니다. 간단한 코드 방식으로 수행하거나 가장 간단한 ViewModel 5 줄에 대해 200 줄의 XAML 해킹 코드를 작성합니다. 복잡한 ViewModel로 상황이 어떻게 악화되는지 상상할 수 있습니다.
따라서 Hello World 응용 프로그램을 작성하지 않는 한 대답은 간단합니다. WPF에서 바인딩 가능한 MVVM을 사용하는 것은 무의미합니다. ViewModel을 바인딩하기 위해 해킹에 대부분의 시간을 보냈습니다. 데이터 바인딩은 좋지만 이벤트 시간의 70 %로 대체 할 준비가되어 있어야합니다.


변환기를 사용하여이를 DataGrid에 바인딩 할 수 있습니다.
Cameron MacFarland

@CameronMacFarland : 전부는 아닙니다. 일부 속성은 읽기 전용이고 바인딩 할 수 없습니다. 일부 속성은 단순히 존재하지 않으며 상태 변경을보고하는 이벤트 만 있습니다.
Alex Burtsev

WPF DataGrid를 사용한 경험이 많지 않다는 것을 인정하겠습니다. 추악하고 더 이상 WPF에 맞지 않기 때문에 피하는 경향이 있습니다. 이벤트를 처리하기 위해 변환기와 AttachedProperties를 조합하면 필요한 것을 얻을 수 있습니다.
Cameron MacFarland

1
Alex, 당신이 겪고있는 문제는 MVVM이 아니라 DataGrid의 디자인에 있습니다. "데이터 바인딩은 좋지만 이벤트의 70 % 시간으로 대체 할 준비가되어 있어야합니다."라고 말하는 것은 잘못된 것입니다. (Telerik) 데이터 그리드가 초기화에 필요한 이벤트 핸들러를 제외하고는 UI에 이벤트 핸들러가 전혀없는 객관적으로 거대한 WPF 애플리케이션을 작성했습니다.
Robert Rossney

3
"이건 잘못 설계되어 작동하지 않는다"는 태도를 취하는 대신 "왜 다른 사람에게는 효과가 있지만 나에게는 그렇지 않은가?"라는 태도를 취하면 더 많은 성공을 거둘 수 있다고 생각합니다. 일을하기 어려운 이유는 아직 그 방법을 모르기 때문이라는 것을 알게 될 것입니다.
Robert Rossney

0

아니요, 무의미하지는 않지만 패턴 자체가 말도 안되게 단순하더라도 머리를 감싸는 것은 어렵습니다. 수많은 잘못된 정보와 적절한 방법을 놓고 싸우는 다양한 그룹이 있습니다. WPF 및 Silverlight에서는 MVVM을 사용해야한다고 생각합니다. 그렇지 않으면 문제를 일으킬 수있는 "오래된"승리 양식 방법론에서 새 모델의 문제를 지나치게 코딩하고 해결하려고 할 것입니다. Silverlight에서는 모든 것이 비동기식이어야하기 때문에 더 많은 경우입니다 (이를 둘러싼 해킹이 가능하지만 다른 플랫폼을 선택해야합니다).

이 기사를 읽고 ViewModel 패턴을 사용하여 WPF TreeView를 단순화하여 MVVM이 어떻게 잘 구현 될 수 있는지 확인하고 MVVM의 새로운 사고 방식으로 승리 양식 사고 방식을 변경할 수 있도록하는 것이 좋습니다. 간단히 말해서, 무언가를 원할 때 View가 아닌 ​​ViewModel에 로직을 먼저 적용하십시오. 항목을 선택 하시겠습니까? 아이콘을 변경 하시겠습니까? UI 요소를 반복하지 말고 모델 속성을 업데이트하고 데이터 바인딩이 핵심적인 작업을 수행하도록합니다.


-1

(모달) 대화 상자와 관련하여 많은 MVVM 구현에서 동일한 문제를 보았습니다. MVVM 패턴의 참가자를 살펴보면 일관된 응용 프로그램을 구축하기 위해 뭔가 빠졌다는 느낌이 듭니다.

  • 보기 는 특정 GUI 컨트롤을 포함하고 사용자 인터페이스의 모양을 정의합니다.
  • ViewModel 은 프레젠테이션의 상태와 동작을 나타냅니다.
  • 모델 은 도메인 계층의 비즈니스 객체이거나 필요한 데이터를 제공하는 서비스 일 수 있습니다.

그러나 누락은 다음과 같습니다.

  • 누가 ViewModel을 생성합니까?
  • 애플리케이션 워크 플로를 담당하는 사람은 누구입니까?
  • ViewModel이 서로 통신해야 할 때 누가 중재합니까?

내 접근 방식은 누락 된 포인트를 담당 하는 (Use-Case) 컨트롤러 를 도입하는 것 입니다. 작동 방식은 WPF WAF (Application Framework) 샘플 애플리케이션 에서 확인할 수 있습니다 .


Josh Smith가 구현 한 Mediator 패턴은 모든 View Model 커뮤니케이션 문제를 해결했습니다. Messenger.NotifyColleagues는 두 개의 뷰 모델이 서로에 대해 알지 못하도록 글로벌 이벤트에 응답하는 방법을 알고있는 완전히 독립적 인 뷰 모델을 제공하는 방법을 제공했습니다. 이미 베이컨이 몇 번이나 저장되었습니다.
JasonD
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.