There’s a lot of recent buzz about the Model-View-ViewModel or MVVM. (I pronounce it like it rhymes with Auntie Em.) Rather timely for me as a lot of my thinking about implementing UI patterns in WPF has begun to coalesce.
There’s has been a lot of thought given to UI patterns prior to the advent of WPF. Martin Fowler has a relatively succinct historical overview of GUI architectures. I’d like to start here by discussing how these established patterns are mapped to WPF. After that, I’d like to explore how WPF allows us to improve on these patterns. We’re probably in for a series of posts here.
Why Patterns?
One guiding principle, both for testability’s sake as well as for myriad other reasons, is Separated Presentation. This is a just a special case of the general principle Separation of Concerns. We separate the concerns because they are easier to test, maintain, and extend.
Let’s assume that you buy into the value of testability. The next problem is that UI code is notoriously difficult to test. This is a product of the way UI frameworks generally work. The common solution is to push as much behavior as possible into Plain Old CLR Objects (POCO). In other words, if a class is tied to the UI framework, and thus is difficult to test, it should have as little logic in it as possible; instead that logic should be delegated to classes that are easier to test.
The Patterns
There are number of standard approaches, er, patterns, that have been recognized. My influences for interpreting these patterns are Martin Fowler, Jeremy Miller, John Gossman, and Dan Crevier.
I want to show you have these patterns look in code, so let’s establish a quick (and highly contrived) scenario. We have a registration form that accepts an email address, a password, and a confirmation of the password. There’s a button to initiate the registration, but the form has to be in a valid state in order for the button to be enabled. The rules are:
- The email address cannot be blank.
- The password cannot be blank.
- The confirmation must match the password.
Now for the patterns…
The Autonomous View
This is what we don’t want to do, but usually do. All of the logic is in the code-behind. Very little is delegated out to other classes, and when it is, it is typically delegated to concrete types so that hard dependencies exist. It’s impossible to test with this pattern because it is impossible to isolate the behavior that need to be tested. Here’s the xaml and the code-behind.
Model-View-Presenter
I’ve used the term MVP a lot. (Hey, I am one now!) Fowler has suggested that MVP subsumes two more specific patterns (and that the term MVP should be retired in favor of them). Both of the child patterns have the same elements: a model, a view, and a presenter. Generally, the model is data that you are interested in, the view renders the data on screen, and the presenter handles all the “presentation concerns”. What constitutes “presentation concerns” though is part of what distinguishes the two child patterns.
Supervising Controller
The first of the MVP patterns is the supervising controller, or supervising presenter. (The terms controller and presenter are somewhat ambiguous themselves and are frequently interchanged.) The presenter in the supervising presenter pattern has properties that interact with the view through data binding. Frequently, you’ll have simple event handlers (e.g., the click event for a button) that merely call methods on the presenter. (There is an alternative to the event handlers, but I’ll get to that later.)
This pattern is easy to test because the presenter has most of the behavior for the UI and it is POCO. The deficit is that the view still contains some logic in the form of bindings.
Notice here that we’ve introduced bindings into the xaml and that there is almost nothing in the code-behind. The real behavior is here in the presenter.
Passive View
This flavor of MVP squeezes out the remaining behavior out of the view. With this pattern you define an interface for the view that the presenter operates against. The implementation of the view interface has to be very simple, you want the absolute bare minimum in the view. The view is passive because it doesn’t know or do anything. The presenter handles all of the logic and manipulates the view. In WPF, you’ll end up with more code in the code-behind (because you are implementing the interface), but you can avoid bindings. Why do you want to avoid bindings? Because they are harder to tests… or are they? More on that later.
Here’s the view’s interface. Note that the code-behind is more involved, but the xaml no longer has bindings. Also, notice how the presenter has to know a lot more about the view.
A Warning
We all want patterns to be distinct and specific, but the reality is that they are blurry. Often you will be combining elements from various patterns in order to accomplish what you need to do. Don’t get hung up on implementing a pure pattern.
Presentation Model vs MVVM
Actually, I will pick up here next time. I need to give you a reason to come back, right? :-)
If you are interested in the playing with the code examples, I’m posting it on CodePlex.
Posted
01-19-2009 10:19 PM
by
Christopher Bennage