The Case for ViewModel

I've been blogging about the ViewModel, aka MVVM pattern. So has everyone else, who has been using it! This post talks about the why, and some ideas about the possibilities that view models may open up down the road...

One of the comments I got on my last post on view/view model hookup options was the following:

I've been a mvvm fan but actually when I see all the hoops to jump through I wonder at times how effective this is

So I wanted to take a moment to list what I thought compelled me to adopt the ViewModel pattern of client application development (so much so, that I now feel odd writing Silverlight and sometimes even Ajax apps in any other way). Some will be obvious benefits, especially to those already using MVVM in their everyday development, but I want to throw in a couple that are farther out exploratory ideas that I am thinking about. I'd also love to pursue what it means to make view model more mainstream, so if you've got ideas on this topic of "Why ViewModel", I'd love to hear.

ViewModel Pattern

The often cited benefit is increased testability of additional code within the application, and I'll get to that, but I think there are some other benefits that are more applicable, considering not everyone practices the rigor of the level of testing we're talking about here. Essentially, testability is not a justification for the ViewModel pattern on its own.


Making the Conceptual Model of the Application Concrete

The core of the application is comprised of the data it presents, the operations it enables, and the logic/behavior that cause it to move from one state to another.

The ViewModel pattern (as well as the complementary MVC pattern) help encapsulate that core of the application into a concrete form, separated from the user interface and user experience parts of the application, which aids in understanding and maintainability of the code over the long term. In the absense of such separation, all of the state and behavior take on the form of spaghetti, distributed into UI controls, event handlers and code-behind members.

This was the primary reason why view model generally defines the structure and approach I like to take with my application development.

My last post discussed how the view and view model are associated with one another. And in the diagram above, I tried to convey how the key XAML constructs: bindings, actions and triggers allow hooking in a late-bound, decoupled manner, to data, operations and notifications implemented as properties, methods and events on the view model.

The separation leads to a number of second order benefits, one of which is testability. The core of the application can be tested through a unit test, which effectively simulates a view.


Facilitating Designer/Developer Workflow

The view model class serves as a nice contract between the designer and developer roles within a project. As long as the designer and developer have a general agreement on what is the shape of the data, the operations and notifications, the designer can focus on polishing and iterating, as well as evolving/changing the UI design and UX, and the developer can focus on implementing and optimizing the underlying behavior, how data is fetched, stored and managed on the client, the services that are to be requested, when, and how often etc. etc. Furthermore, these design and development can happen in parallel.


Jumpstarting Development

OK, this is a very developer centric view. I often find I get bogged down designing the UI, and focusing on little details too early. Instead, with the view model pattern, I can focus on wring the logic of the app and simply not care about the UI. Throw in RIA Services, and I can build the server portion of my app as well, and have the view model call into it, and get a generally working end-to-end app before writing any XAML.


Updated: A Pattern that Scales, and Lets You Scale

Do read the first comment below, from Darren Oster. It captures an essential element of why, which I'll summarize - as a pattern it applies to small projects and works well with complementary patterns like dependency injection, etc. when working on larger projects. And even more importantly, it lets you scale better, by allowing you to focus on one portion of your application at a time.


As mentioned, I also want to briefly mention some early ideas I have in the back of mind, for how view models help address some more fundamental problems, or can improve the application development workflow, should the ViewModel pattern indeed become mainstream over time.


Making Async Simpler

Async programming is hard, and the natural desire is to simply avoid asynchronous work and instead do things synchronously. This has the problem of getting in the way of responsive UI. What if all application-specific work could be done on a background thread where it was free to block, while freeing up the UI to process input, animate, and paint?

To add to that, there is an increasing desire to do more work concurrently to leverage many-core hardware. But that just made the async problem even harder. What if multiple bits of interesting application work can be moved to multiple background threads.

Essentially, what I'm getting at is what if view models were run in the background? They're already decoupled from the view, and so they shouldn't need to touch any UI objects. The interface between the view and view model (as shown in the diagram above) - the bindings, actions and triggers could take care of marshalling across threads. The nice thing is they're all system/platform code and so most app developers don't need to care about the details. Instead they get to focus on their application logic housed within view models.


Integrating Prototyping into Application Development

Sketchflow is a great tool to quickly prototype the screens of the application. It facilitates iteration, experimentation, and collecting feedback by designers, developers in conjunction with actual customers/users of the application.

The output of the sketchflow and prototyping effort is a blue print for the application's user interface. But it can be more. What if it is also effectively constructing the contract exposed by the view model? What if the output is an interface that the developer of the view model must implement, and that the designer can assume and design the actual view around?


[ Tags: | | ]
Posted on Monday, 3/1/2010 @ 1:56 AM | #Silverlight


Comments

14 comments have been posted.

Darren Oster

Posted on 3/1/2010 @ 2:45 AM
I appreciate the comment about testability not being enough to justify MVVM. While this is certainly a nice aspect of MVVM, the thing I find most appealing is the separation of concerns offered by the pattern. Even without going to the extent of Dependency Injection and Async services, the ability to concentrate on one thing (either, how do I treat my data, or, how do I display this data) is a great benefit. For small projects, MVVM still holds its own for these reasons alone. As the scale of the project increases, adding in DI and testability just increases its worth.
Thanks for the article!

John Waters

Posted on 3/1/2010 @ 6:45 AM
What would be really helpful in the context of RIA is patterns for how to map between the various representations of data, and codegen/tooling support all the way through.
Also, having some customizable codegen templates for different scenarios would create a great jump start.
Keep up the good work!
John

Nikhil Kothari

Posted on 3/1/2010 @ 8:21 AM
@Darren
Good point - I think what you said should be explicitly called, out, and I updated the blog post to include it.

Michael Washington

Posted on 3/1/2010 @ 10:06 AM
I also appreciate the comment about testability not being enough to justify MVVM. "Facilitating Designer/Developer Workflow" is the primary advantage to me. Even if I am "wearing both hats".

David K.

Posted on 3/1/2010 @ 1:00 PM
Great article; There IS much more to the MVVM pattern than unit testability. My comment is in regards to your section on making async simpler. In my experience a view model needs to invoke the dispatcher to ensure an operation that will affect the view is done on the UI thread (for instance, an update to an ObservableCollection). This seems like something the view model author shouldn't need to be concerned about. Is there a better (cleaner) way to ensure updates that affect the view are done on the UI thread? Thanks.

Nikhil Kothari

Posted on 3/1/2010 @ 1:12 PM
@David
On the possibility of simplifying async, its still an early thought, and not necessarily even accomplishable end-to-end given the platform today, but I'm thinking of a) whether its something useful to think through, and b) what would the platform need in order to enable it. I have some ideas of what might be needed, and where to start, but those are even more raw and early!

For instance on propagating change notifications, in WPF they can happen on a background thread, and bindings will post to the UI thread to actually update the UI. In Silverlight, that is not the case today. However in Silverlight.FX, which contains a Model base class, the base class is responsible for posting to the UI thread. As you see, the idea is for infrastructure to handle the threading aspects, and not app developer code, that should be both simple, and ideally oblivious of the threading.

Orrin

Posted on 3/1/2010 @ 3:27 PM
Could you explain the part of your diagram where the ViewModel sends notifications to the View by invoking Triggers? How is this done? Thanks.

Nikhil Kothari

Posted on 3/1/2010 @ 3:54 PM
@Orrin,
The interaction between view and view model could be a post of its own, as a followup to the hookup post. But I'll summarize here until I get to authoring that one...

Imagine my view model with events:

public class MyViewModel {
public event EventHandler StartingProcess;
public event EventHandler CompletedProcess;
}

Now in the view, using Triggers listening to the events, I could write the following:

<UserControl>
<fxui:Interaction.Triggers>
<fxui:ModelEventTrigger EventName="StartingProcess">
<fxaction:GotoVisualState StateName="Active" />
</fxui:ModelEventTrigger>
</fxui:Interaction.Triggers>
</UserControl>

Basically the there is a trigger that listens to the model's events (just like triggers can listen to events from UI elements) and in response invokes some actions that perform some work in the UI layer.

Clement

Posted on 3/1/2010 @ 5:09 PM
Thank Nikhil.
I'm all for the MVVM pattern and I think I understand its benefits.

Once thing I do not understand though, is why MVVM developers are (religiously?) trying to get rid of any code at all in the code behind.
What's wrong with a click handler in the code behind for example ?
Even if most of the code behind is just forwarding to the view model, the advantage of this is that everything is strongly typed. That is, things would not compile if you were to rename a member/event/method of the view model.
Also I allow myself to add minimal ui specific logic in the code behind, such as displaying a confirmation dialog before forwarding (or not) to the view model.

Nikhil Kothari

Posted on 3/1/2010 @ 5:29 PM
@Clement
I am personally not arguing for zero-code in code-behind. Notice in the diagram above ... I have UI-Logic. Some logic may be declarative (the more there is the more designable it is generally), but it allows for code-behind. Also notice the diagram I have in my original view model post at http://www.nikhilk.net/Silverlight-ViewModel-Pattern.aspx - it has an explicit box for code-behind, just happens to be smaller than the normal code-behind box in the non-viewmodel scenario.

I do like to use the zero-code-behind as a guiding goal, as it helps highlight what are the interesting set of building blocks (eg. behaviors, triggers, actions) that should exist, as they promote both designability and reuse.

Taiwo Ojo

Posted on 3/1/2010 @ 11:44 PM
Thanks Nikhil,Let take for instance that someone is not using your framework.Is it possible for ViewModel to send notifications to the View by invoking Triggers.Thanks.

Nikhil Kothari

Posted on 3/2/2010 @ 12:54 AM
@Taiwo

The view model doesn't invoke triggers. The view model raises events - vanilla events like any .net class. Triggers listen to events. If you're not using triggers, you can write normal event wireup code, for example in code-behind. Triggers are simply the declarative equivalent.

daniels

Posted on 3/2/2010 @ 4:41 PM
I discovered Silverlight early and by the time 3.0 came out, I had written enough async code to really have a mess on my hands. Since discovering MVVM I can write the same amount of code, doing about the same thing, and the overall application does not even begin to get all that complex, and I can handle it easily, where-as the stuff I wrote prior to this is so difficult and complex now to follow that it is very difficult to modify. I am refactoring it to MVVM.

I am aware I am not fully implementing the pattern, or else the pattern is not quite right, but it is ten times better than not using it.

Adrian

Posted on 4/1/2010 @ 8:13 AM
Hi Nikhil,

Firstly I've only been looking at your SilverlightFX framework for one week and already I am busy integrating it into a new project alongside WCF RIA services and I must say it is making so much of my life a lot easier.

I read with interest your thoughts regarding putting the ViewModel layer on background threads primarily because I have a non-threaded queuing implementation that allows RIA service operations to be queued and dispatched one-by-one. It works well and saves me having to track the state of the RIA proxy (because it doesn't like concurrent operations).
(if anyone is interested I'll pop the source on sky-drive/codeplex)

However what would really allow view-models to fly would be to build the View-Model layer (and controller/services too) on top of a Silverlight version of the CCR (Concurrency Coordination Runtime from the MS robotics team) - apparently they have an internal version of the CCR core that runs on Silverlight - it really would be the perfect match. If you haven't taken a look at it then check it out - if you ever have such a thing as free time ;-)

Oh just a quick question - auto-complete - I read somewhere that I need an ASHX service but can't find an example - if you would be so kind as to point me in the direction of anything appropriate!

Many many thanks for the framework and the blogs - you're singlehandedly helping a lot of developers out here!

Regards,
Ade
Post your comment and continue the discussion.