Saturday 17 October 2009

Exploring the Model-View-ViewModel pattern

This will be a long article, one that I intend to add on while understanding more about the MVVM pattern and patterns in general. Also, while I am sure I will add some code during the development of the post, this is intended mostly as a theoretical understanding of the said pattern.

For an easy and short explanation of the concepts, read this article: WPF Apps With The Model-View-ViewModel Design Pattern.

The start of every concept research these days seems to start with Wikipedia. The wiki article about Model View ViewModel says that MVVM is a specialization of the PresentationModel design pattern introduced by Martin Fowler specific for the Windows Presentation Foundation (WPF). Largely based on the Model-view-controller pattern (MVC).
Further reading from Martin Fowler's site on the MVC pattern, which seems to stand at the core of all this specialization, revealed this: Probably the widest quoted pattern in UI development is Model View Controller (MVC) - it's also the most misquoted. [...] In MVC, the domain element is referred to as the model. Model objects are completely ignorant of the UI. [...] The presentation part of MVC is made of the two remaining elements: view and controller. The controller's job is to take the user's input and figure out what to do with it. There is a lot more there, about how in the early MVC concept there were no events or binding of any sort. Instead the controller would get the input from the UI, update the model, then the View would change as the model changes using some sort of Observer pattern. Even from these few quotes, one can see that in this "holy trinity" there are actually two basic actors: the Model (which, to make it easier to differentiate later on from other models, I will call Data Model) and the Presentation (controller+view in MVC).
Let's see what the PresentationModel pattern is all about: Presentation Model pulls the state and behavior of the view out into a model class that is part of the presentation. The Presentation Model coordinates with the domain layer and provides an interface to the view that minimizes decision making in the view. The view either stores all its state in the Presentation Model or synchonizes its state with Presentation Model frequently. As I see it, it introduces a new model, one specific to the Presentation side but independent of the UI controls. Martin Fowler specifically says about the PresentationModel pattern: Probably the most annoying part of Presentation Model is the synchronization between Presentation Model and view. It's simple code to write, but I always like to minimize this kind of boring repetitive code. Ideally some kind of framework could handle this, which I'm hoping will happen some day with technologies like .NET's data binding. and 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.

I also find this article about different Model View Presenter patterns very informative and the diagrams easier to understand than Fowlers UML or whatever that horrible diagraming he uses is :)

This brings us to MVVM. It is basically the PresentationModel pattern, where WPF/Silverlight types of complex binding take care of the synchronization of View and ViewModel. For me, one of the most important aspects of this approach is that the complex interactions between UI components (and that don't involve the data in the DataModel) can be left in the View and completely ignored further down. That makes interchanging Views something very easy to do, as the entire "UI logic" can be separated from the more general presentation logic. In this, I see that the UI becomes a third layer by the introduction of the ViewModel/PresentationModel in between the Data Model and the Presentation.
I have imagined doing this in a Web or stricly Windows Forms environment. As Fowler said, the plumbing required for synchronization between the view and the viewmodel makes it not worth the effort. That is where the WPF Data Binding comes in.

Let's start the MVVM chapter with a simple example. There is a need to search people by using different filters, display the list of found people and give the ability to click a person and see the details in a separate detail pane. The filters can be simple (Google like textbox) or complex (specific role, age, etc searches). The complex filters of the search are hidden in a separate panel that can be shown or not.
An ASP.Net or Windows Forms application would probably create a form containing the searchbox, the additional filters in a panel with a checkbox or button to show/hide it, the details panel with textual information and a grid where the list of people would be displayed. Events would provide all the needed plumbing, with the code executed on them placed in the code behind of the form, changing what was needed. See, the code behind was already an attempt to separate the presentation from code, although the separation was mostly symbolic. One might have employed a flavour of the MVC pattern, creating a separate controller class that would have worked with the data model and the form (as a view) through interfaces. That means a lot of plumbing, anyway.
In WPF, one creates the form, as in the Windows Forms approach above, but then it binds no events (or very few, I will talk about that later). Instead, it uses data binding to link UI components to properties that it expects to find on the object that will be provided to the view as a DataContext, that is the ViewModel. It doesn't know what the format of this object is and, indeed, the properties are found using reflection, which makes this slightly slower than other methods.
What this means is that any code that reacts to a change of a UI component would be placed on an event handler of the property to which it is bound. When the property changes, stuff happens, not when someone clicks a checkbox. This makes the architecture a lot more testable from code, as all a test needs to do is change a property, not perform a click. It also means that a lot of extra plumbing must be done on those properties, for example the ViewModels could implement INotifyPropertyChanged and then notify on any property being changed. Also lists must not only inform on the get/set operations on them, but also on their items, which implies using ObservableCollection, ObservableDictionary, BindingList and other objects that observer their items and notify on change. On the Views, Dependency and Attached properties come into play , and I will link to some explanatory posts later on. They are extremely important in WPF, because they compute the value, rather than store it, but that's another story altogether.
What this also means is that events, in the way there are used in Windows Forms scenarios, are almost a hinderance. Events cannot be bound. If they are handled in bits of code that change properties in the ViewModel, then the code must either have a reference to a specific type of ViewModel, which defeats the whole purpose of MVVM, or to read/write properties using reflection, which means extra plumbing in the View code. Not that this cannot be done, and there are several solutions to that. However, it would be ugly to write a view completely in XAML, binding everything you need to properties that are to be found on the ViewModel, then starting writing code just for a few events. Here is where commands come in.
The Command pattern is an Gang of Four pattern, useful in WPF by providing objects that can be bound and that encapsulate a behaviour that will be executed. Read more about Commanding on MSDN. Many WPF controls exposes events as well as commands for common actions, for example the Button class exposes the OnClick event, but also the Command property (which will be executed on click) and the Clicked property (which will be set on click).
Commands in WPF implement the ICommand interface which exposes the Execute method as well as the CanExecute method. A default WPF button that has a command bound to its Command member will appear as disabled if the CanExecute method returns false, that because the ButtonBae class implements ICommandSource. More about commands when I present the RelayCommand class, which has become quite commonplace in the MVVM world.
A problem is that not all controls have a command for every concievable event. A solution is, of course, to inherit from the control and create your own command for a specific event. It only requires that you handle the event internally, expose a property that implements ICommand and execute that command inside the event handler. This brings the advantage that the control can be reused with minimal changes in the XAML. There are other solutions, one of them is to use Attached Properties. If you don't want an attached property for every event that you use, read this article. A very comprehensive article about the application of Commanding in WPF can be found here: WPF Command-Pattern Applied.

So far so good. Using the concepts above we can separate the UI from the data completely, as the View only uses binding on the Data Model and can be replaced with any other View that binds to existing properties. This pattern can be used on any level, be it the window or the user control level. Controls that are strictly UI, of course, don't need to implement MVVM. There are other aspects that were not covered here, more specific to WPF, like Routed Commands and Events and concepts like global messaging. But since they are not really part of the MVVM idea, I will leave them for other posts.
There is also the question of code. I will not be doing any in the post for now. However, I will be ending this with a few links that seem relevant.

Extra links:
Adventures in MVVM -- Ball of Mud vs MVVM
Hands-On Model-View-ViewModel (MVVM) for Silverlight and WPF
Exploring a Model-View-ViewModel Application; WPF Password Manager, Cipher Text

Another important thing to consider is the myriad MVVM frameworks out there, all of them implementing some helper classes and prewiring of applications. I was talking earlier about the RelayCommand. Imagine you want to create a ViewModel that exposes a Command. That command would need to implement ICommand, therefore being an object that has two methods: one to execute and the other to determine if it is possible. Creating a class for each such command would be tedious. The RelayCommand is a generic class of T (where T is the type of the command parameter) with a constructor that accepts an Action of T and a Func of T. You instantiate it with the methods in your class that are to be used and that is it.

I will update this material with more information as it becomes available and if I have enough time for it.

1 comment:

  1. Great post. But the animals on the screen are awful and bother me by reading....

    ReplyDelete