There’s a lot of fuzz around MVVM and its appliance in Silverlight and WPF. Almost everyone who has done something with Silverlight has tried it and is using the pattern to some degree. Some people are puristic about the use of MVVM, while others are more of the pragmatic kind.
In this article I’m not going to give you a full guide on everything that is MVVM. Instead I’m going to give you some insight into how I think MVVM can be used. Also I’m going to give you a bit of insight into my own brain, to show you what factors play a role in designing a user interface with or without the MVVM pattern.
The MVVM pattern explained
Before I start explaining how you can use MVVM, I’d like to take a few (or maybe a lot) words to explain how I see MVVM when building frontends in Silverlight. I will not talk about WPF here, but you could easily substitute Silverlight for WPF here.
One way to think about MVVM is to look at it as a design-pattern. MVVM defines a structure where there’s a separate model that is an abstraction of the view. This ViewModel aggregates various parts of the domain model. It does so in a way that it is easy to show the data on screen. The view itself is pretty much dead in this pattern. I use the term “dead” on purpose here, because most of the time you will not need any code in the view to get the data on screen. The idea is that every bit of logic needed for the presentation of data is contained within the ViewModel.
Not everyone will agree with me that MVVM is a design-pattern, because experts in the field of design patterns (Martin Fowler and others) will not call it a design-pattern persé. And with good reason. When you take a close look at MVVM, you will notice it’s a combination of design patterns:
- Presentation model
- Passive view
- Observer synchronization
Each of the patterns presents a very small part of MVVM as a whole. To give you an idea of where each of the patterns fits in, I’ve created a schematic that you can find below.
Note: I put PresentationModel in the schematic because the ViewModel has some striking similarities with the PresentationModel. MVVM is partially derived from the PresentationModel and can be viewed as an evolution of that model.
The combination of design-patterns makes MVVM less of a design-pattern. Instead could call it a software pattern. I’m however not one of those people that likes to make more complicated than they really should be, so for me it’s still a design-pattern. And why wouldn’t it be, you can build design-patterns out of other patterns, right?
So there you have it, MVVM explained. Admittedly that I’ve bend the rules a bit here and there, but that’s all part of being pragmatic about it.
Using MVVM as a way to design your frontend
Applying MVVM to the design of your Silverlight frontend isn’t really hard. For each screen in the application there will be a View and a ViewModel which will contain logic to work with the domain model. Every property that you add to the ViewModel can be databound to the view, either by entering the infamous {Binding Path=…} expressions or by using the designers offered by Expression Blend and Visual Studio. So far so good.
The domain model itself can either be something local to the application or a set of web services that expose business data to the frontend.
As simple as it may look, there’s still a lot more to MVVM than people might think. There are situations that make it harder to apply the MVVM pattern correctly. In the following sections I will show some of the distinct features of the MVVM pattern and what situations that you may come across when designing a user interface using the pattern.
Abstraction of the view
The best way to approach the design of a frontend using MVVM is by building a view model as the model of a view. Building the ViewModel as a model of the view helps you to disconnect the view from the business logic. You can unit-test the ViewModel and verify if the behavior of the user interface is the way it was meant to be. Also by having a strong separation, you allow designers to build the views of the application without having to worry about any logic.
This abstraction of the view does have a downside. I’ve found that there are interaction styles that force you to break the separation of the View and ViewModel. For example, drag-and-drop functionality cannot be done without redirecting events raised on the view to the ViewModel. You will need to write a bit of logic for this to work. Almost anything that you can only do by handling events, breaks this separation.
Is breaking the separation of View and ViewModel a bad thing? It depends on how you break it. Everything that you can do through databinding keeps the separation intact and you really should try to use databinding as much as you can. However if the amount of work required to keep the separation is getting to a point where it becomes hard to maintain, I suggest you break it. The key here is to document the cases where you allow for breakage of the separation between the View and the ViewModel. This will keep everyone on the team informed and it helps to keep a uniform (and more maintainable) code base.
What comes first, the view or the model?
In the previous section I talked about the fact that the View and ViewModel are two separate things. Because the View and the ViewModel are separated, they will each need to be instantiated and linked together at runtime. There are various ways to do this, each with its own ups and downs. Here’s a list to give you an idea of the possible variations:
- The View and the ViewModel are created separately and are linked together afterwards.
- The View creates the ViewModel in the codebehind of the View.
- The ViewModel is created and the View is applied later, by using DataTemplates.
- The View declares the ViewModel in XAML.
It’s important to note here that none of the variations is wrong on its own. There are however situations where you might choose one method over the other. It all depends on your personal preference and the technical or design requirements of the application.
There are basically three approaches to constructing a View-ViewModel pair. First there’s the View-first approach, where you create a View and the View creates the ViewModel. Second there’s the Model-first approach, where you create the ViewModel and the application will find the right view to display for you. And lastly there’s the simultaneous approach, where you create the View and ViewModel and link them together after they are created.
Depending on the development team you’re working on, you might choose a different method to create and initialize the View with its ViewModel. If you do have a designer on the team I suggest you choose a method that keeps the design interface of Expression Blend intact. In the case that you don’t have a designer on the team, you can choose to use a method that’s more code oriented.
All techniques except one technique allow for designer-developer interaction. If you choose the model-first approach, you will break the design capability. It can be done, but the designer has a hell of a job designing the user interface. Using this approach also makes the magic-factor in the frontend higher. People who need to work on the user interface need to know exactly where to find the DataTemplates or they may have a hard time figuring out where to go next when they open the VisualStudio solution containing the frontend. Last but not least, because of the fact that you sometimes need to break the border between the View and ViewModel, using the model-first approach might not be such a good idea, since you completely block that road.
So when do you use a view-first approach for constructing the View-ViewModel pair? This depends on the interaction style needed for the specific scenario you are implementing. The view-first approach works best when the component creating the view, doesn’t need to know about the View and the ViewModel. Even if the component creating the view, needs to know about the view, you can still use this approach. The view-first approach is the most commonly used method of constructing a View-ViewModel pair and certainly the one that is the easiest to use.
However, sometimes it’s easier to create a separate View and ViewModel and link them together afterwards. This is especially true when you work with dialogs. But it also works in other cases where you need control over both the View and the ViewModel.
If you open a dialog in Silverlight, you most likely want to see if the user closed it and act accordingly. In that case the controller would monitor the Closed event on the ChildWindow derived view and get the data from the ViewModel when the event is raised.
Should you be using MVVM for everything?
The last View-ViewModel pair creation technique described in the previous section, introduces another pattern into the mix, namely Supervising Controller. This is where it gets interesting for me.
MVVM has some clear advantages, but the fact that I need a lot of other patterns to make things complete, made me wonder if you should be using MVVM in all cases.
Build for testability
Unit-testing has become immensely popular among developers and with good reason. It helps you greatly reduce the number of bugs that remain in a system when it’s being tested by the tester (Yes, you still introduce them, but you fix them early on by changing code around when the unit-test fails).
MVVM helps you by defining components that can be tested separately. You can create a mockup for the screen and use that in your unit-tests if you need to. Most of the time however, you will not use any view at all in the unit-tests.
So if you’re serious about your frontend, I suggest you invest some time into designing the frontend in such a way that you can easily test it. If you do this early on, you will that it doesn’t take much time.
Should this be a rule that everyone needs to follow? I think not. As I talked about before, there are cases where it’s impossible to keep the boundary between the View and the ViewModel, due to conflicting interaction styles. This may or may not break your unit-testing strategy. In the case that it does happen to break your unit-testing strategy, I suggest you follow a classic 80-20 rule. Test the stuff that you can using unit-tests and test that last bit by hand.
Other patterns that work too
MVVM certainly isn’t the only pattern that allows you to build maintainable and testable user interfaces. It’s predecessors work too. So if you feel that MVVM doesn’t work for the specific scenario you’re in, choose another pattern that does work. The cases that this happens are few, but it might still occur.
There’s no rule that developers must be using MVVM. Instead it’s better to go with common sense here and take a careful look at the technical requirements and design constraints before choosing a pattern for a specific part of the application. I’m deliberately saying a part of the application, because I think it’s perfectly fine to mix MVVM with other patterns where necessary.
No patterns at all
I can here you think now, what the … is he thinking! Well yeah, that’s exactly what I was thinking when I opened the first ever RIA services sample posted by Microsoft. They told me that MVVM was important to them and they would work on supporting it more in their tools. But instead of posting samples that use the MVVM pattern, they decided to build samples that use none of the patterns that I talked about.
Instead of using patterns they demonstrated that you could build an application with just a few screens that have DomainDataSource objects attached to them by declaring them in XAML. Every bit of logic that you needed to write to support such a scenario is now contained within that single object that you can declare. It’s that sort of “Look ma, no code” moment.
This got me thinking, what if you use such a framework. Should you be making it harder by throwing out the cool stuff and introduce MVVM instead? Sometimes, yes, but there are plenty of places in applications where it’s more than enough to go with the basic features offered by a framework like WCF RIA services. There are also cases where you have so much complexity, that the standard components are no longer working the why you intended them to work. In that case it’s smarter to take some time to design that part of the application using MVVM or any other pattern.
Conclusion
In my mind, you really shouldn’t be making it harder for yourself when designing a frontend. Instead take time to take a good look at what’s there and what should be there. This will make it easier to decide where to invest the money of the customer into building the right stuff.
Keep in mind that everything we do as IT-guys costs a lot of money and that making decisions whether or not to use MVVM or other patterns affects the time you need to build that particular feature. So sometimes, it’s better to build a user interface that may not be 100% unit-testable, but is cheaper to setup. This is true in the case of screens that are used less and screens that are not too complex as to what is displayed on them.
So there it is, my opinion on MVVM and frontend design. Feel free to discuss or e-mail me if you feel that there are things that I’ve missed here. At least I hope you’ve got a sense of what goes into designing a frontend using the MVVM pattern.
2 comments
Impressive Coverage.
Thx for the writeup.
Simple and easy on the head to read.
Raghuraman
Simple and easy to understand. Awesome explanation compared to many articles in the web.
Murali Vemulapalli