开发者

Always use MVVM in a WPF app, or are alternative patterns still practical/useful?

开发者 https://www.devze.com 2023-02-14 14:50 出处:网络
On page 374 in the book Microsoft .NET Architecting Applications for the Enterprise, there is a chart regarding the evolution of patterns for the presentation layer and their impact on platforms (figu

On page 374 in the book Microsoft .NET Architecting Applications for the Enterprise, there is a chart regarding the evolution of patterns for the presentation layer and their impact on platforms (figure 7-14).

In addition to showing the evolution from the original MVC pattern, to the more modern variants, that chart also shows that the following modern patterns can be applied across the following technologies:

  1. Model2 (MVC)
    • Web Only
  2. Passive View (MVP)
    • Web
    • WinForms
    • WPF
  3. Supervising Controller (MVP)
    • Web
    • WinForms
    • WPF
  4. MVVM (Presentation Model)
    • WPF Only

Note: One other recent pattern of interest lately not in that chart is Presenter First (MVP) which was envisioned to be more accommodating of TDD.


From what I understand if one develops with WPF, then the MVVM pattern is the de facto choice (kind of like Model2 is for web development). That said, it appears nothing prevents one from using Passive View, Supervising Controller, or Presenter First in a WPF app. Such an approach would result in an application that doesn't really care if the front end is WPF, WinForms, or the Web. It appears that these MVP variants allow more flexibility.

However, does aiming for UI-platform-agnostic flexibility (that might not be needed) come at the cost of making WPF development much more difficult and lose out on a portion of the features/power that WPF offers?开发者_JAVA百科 So much so that the costs outweigh the benefits?

In other words, is MVVM so great that one shouldn't consider other alternatives in WPF applications?


According to the included documentation in MVVM for WPF (page 2 of the general introduction)

The origins of this pattern are obscure, but it probably derives from the Smalltalk ApplicationModel pattern, as does the PresentationModel pattern described by Martin Fowler. It was adapted for WPF use by the Expression team as they developed version 1 of Blend. Without the WPF-specific aspects, the Model-View-ViewModel pattern is identical with PresentationModel.

Going to Martin's Fowler's website and looking up Presentation Model we have this

Compared to Passive View and Supervising Controller, Presentation Model allows you to write logic that is completely independent of the views used for display. You also do not need to rely on the view to store state. The downside is that you need a synchronization mechanism between the presentation model and the view. This synchronization can be very simple, but it is required. Separated Presentation requires much less synchronization and Passive View doesn't need any at all.

For my own metal cutting CAD-CAM application I use Passive View. The reasons for this are

  1. To making testing easier by having mock objects implementing the view thus allow the vast majority of my software's functionality to be automatically tested
  2. To reuse not only the core model but the different views for related types of metal cutting software.
  3. To clearly document the interaction between the views and the model.
  4. To destroy any dependency on the GUI toolkit as this software has been continuous development since 1985 and seen several major changes in the underlying tools, APIs, and even the language itself.

The the concerns of first three can be handled by the MVVM, Presentation Model, Supervising Controller pattern. But only the Passive View addressed #4.

As stated by Martin Fowler only the Passive View doesn't require any synchronization method. MVVM is a implementation of Presentation Model for WPF. You are dependent on the XAML interface to tie the view state located in the View Model with the View itself. So if at a later time you change the UI or it's APIs then your View Model will be changed as well.

In contrast Passive View only requires that the new UI elements implement the View Interface. It doesn't matter what they are actually connected to also as the form or controls implementing responds correctly.

But the price is that you have an extra step when implementing new elements of a view. You have to decide how they are to be presented to the presenter and at what level of abstraction. It is enough that it over kill on some projects or for some types of UI like dialog boxes.

The short answer to your question about MVVM being THE way for WPF, the answer is no it is not. It is a tool that need to be considered in light of the other issues surrounding the development of your application.


@RS Conley's answer is giving a very broad into to the subject, and I agree with most. The only thing I think differently is in the bottom line.

MVVM is THE architecture for 95% of applications in WPF.

Choosing any other architectures is means settling for something that is less than the best you can get. In RS Conley's situation Passive View might be the best way to go, but that is far from being the normal case.

As a way to understand how MVVM is better, let's see what's he's losing when he's going the PassiveView approach.

Maintainability

In Passive View, the ViewModel knows about the IView, which means that SRP (Single Responsibility Principle) is not kept. The Controller in PassiveView interacts directly with both the Model and the View, and therefor is doing two completely different things!.

Under MVVM, the ViewModel, which is the heart of the application only have one concern, which is to contain the state&logic of the application. The Maintainability of such code is really superior to PassiveView, MVP or MVC treamendously.

It is true that PassiveView is better when it comes to Automated Tests Coverege, but IMHO, good maintainability of code is far more important. Testability helps u make sure you don't break your code, while Maintainability helps you not to build problematic code to begin with.

When it comes to Maintainability, MVVM and PresentationModel are an evolotion of previous UI architectures, and that's because the SRP principle is kept very strictly. Write enough code in MVVM and you'll see what I mean.

Blendability

Another Feature where MVVM is really strong is Blendability. Since all of the application state is preserved within the ViewModel, it is easy to fake data for design time, which allows enourmous boost to productivity. This is impossible to create in PassiveView, MVP or MVC, because in all of those architectures the controller has to actively put data inside the view. In MVVM the data just "jumps" to the View and therefore can be mocked.

Testability

This is indeed a place where PassiveView is superior to MVVM. If 100% Unit Tests coverage of UI is crucial to you then it's a big deal. In most situations however, the coverage that MVVM allows you is more than enough, and you'll usually add another tier of testing using regular UI Testing (which you'd end up doing in PassiveView also btw).

I think that Testability is the less important of the three features. Sorted by importance, it's Maintainability, Blendablilty, and Testability.

Where is MVVM not the right choice?

I've participated in ~ 15 WPF & Silverlight Projects the last year, all of which MVVM fit perfectly. I think that in places where the presentation logic is extremely big, such as in games, MVVM might not be the right choice. Other than games, I can't really think of an application category that wouldn't go best with MVVM, other than special situations like RS Conley mentioned.


I've been working on implementing MVP with a WP7 (Silverlight) MVVM app for the past couple months. I believe I've managed to come up with a good working solution that leverages the best of both worlds. The downside is that there is a fair bit of "scaffolding" code. The upside is an MVP framework where the Model & Presenter tiers should be reusable between WP7, WM, and Android (given MonoDroid).

I used MVP-VM as described here - http://aviadezra.blogspot.com/2009/08/mvp-mvvm-winforms-data-binding.html - as a basis for my design.

The Model is the model and shouldn't need any clarification. It contains the data classes, business logic, and services, and doesn't reference anything UI-specific.

The Presenters and View interfaces follow the Passive View pattern.

View interfaces are comprised mostly of events, some properties, and a few methods. Everything that passes between the Presenter and View is non-UI specific.

View implementations are a triad of PhoneApplicationPage (or WPF form), PageViewModel, and a ViewFacade.

The ViewFacade is what actually implements the View interface. It is responsible for coordinating the Page and ViewModel. It bubbles up events from the Page, makes most of them fire asynchronously, which the Presenter catches. It also transforms any UI-specific event parameters into non-UI parameters. Anything coming from the Presenter to the ViewFacade is checked for UI thread safety and invoked properly. The properties are usually data and are passed on to the ViewModel.

Keeping the View interface implementation (ViewFacade) separate from the actual UI class (Page, Form, etc) helps to keep the responsibilities distinct between the View triad classes. For instance, one of the ViewFacade's primary purposes is to be the layer where thread synchronization happens.

The Page / ViewModel are done mostly as you would normally do, however, the commands are events which bubble up via the ViewFacade to the Presenter.

Advantages

MVP design & reusability between platforms.

Easy databinding with MVVM.

IMO, MVP is more logical and easier to conceptualize.

Disadvantages

Duplication of code between Page events and ViewFacade events, ViewModel properties and ViewFacade properties.

Simple cases can have a lot more code than is really necessary.

In the end you have to ask yourself if MVP is worth the extra effort. Is a quicker development cycle more important than reusability across platforms and enhanced testability?

0

精彩评论

暂无评论...
验证码 换一张
取 消