As a follow-up to my last post on MVVM, I want to further investigate the ViewModel as a concept. In commenting on my blog, one reader describes a ViewModel as “a UI oriented abstraction of the model.” In that sense, he is saying that a ViewModel (VM) is simply a contextual “View of the Model” and that it is confusing to think of it in any other way. However, when we construct a VM, we do so with the explicit intent of creating a public surface area that is easily bindable and supportive of the UI itself. Therefore, the public properties and methods/commands exposed by the VM tend to form a “Model of the View.” How do we justify these two views? Are they really at odds with one another or are they merely two sides of the same coin?
One reason VM is confusing stems from its frequent use as an Adapter, where it enables the incompatible interfaces of the UI and domain model to talk to one another. However, using a VM for this purpose is mixing concerns. A better solution would be to have an explicit Facade/Adapter/Bridge handle communication between layers, freeing the VM to vary independently from the domain model. When I’ve failed to make this distinction in the past, I’ve been burned…bad. Nevertheless, even if your VMs do operate like an extremely intricate adapter, it’s often quite unhelpful to think of the problem in this way. Doing so can lead you to miss the realization that a VM has its own set of concerns, which primarily center around supporting the UI, not abstracting the domain. That is to say, we don’t build a VM for the purpose of abstracting the domain model, we build it to power the UI.
How I Think
When I’m constructing a system, I prefer to think of the VM as a state machine with the View being a visualization of the current state. The user interacts with the View, causing “messages” (actions/commands/bindings) to be sent to the VM. The VM receives and delegates or interprets these messages, which may or may not result in state changes and may or may not result in domain model interaction. (I’ll discuss what these state machines look like more in future posts.) The important thing to remember is that the VM is in control; the view makes “suggestions,” but the VM decides what happens when.
The Flip Side
So, for me, the most helpful way of thinking of a VM is as a “Model of the View.” But, is there value to the notion of “View of a Model?” I had to go back and look at concrete code samples from past projects, consider what we did, why and what did or did not work before I could settle on an answer I feel confident about. I saw code that I wrote two years ago in which I mixed adapter qualities with the view model rather than carefully thinking about modeling the view’s behavior. It was hideous. I’m not sure what I was thinking, but I wasn’t creating a “Model of the View.” Then I looked at NHProf’s code which has an explicit bridge (IBackendBridge) and a structural VM, whose implementation was easy to adapt and extend over the coarse of major architectural change. It’s code has remained relatively simple and concise while delivering a rich feature set. Here’s what I have determined. If your view model happens to look like an abstraction of the domain or “View of the Model,” that shouldn’t surprise you. It is a natural consequence of that fact that the entire presentation layer of your application is at a higher level of abstraction than the domain model. From time to time you should think of your VM in this light. It’s likely that doing so will reveal some implicit concepts in your domain which need to be made explicit. This happens because the VM closely models exactly what the users are doing. So, there is value in thinking in this way, but this value is completely different than what is gained from trying to model a view.
When building your VM, try to think of it as a “Model of the View,” but when building your domain model revisit your VM, trying to see it as a “View of the Model” and ask yourself if the VMs implementation has any implications for your domain. Naturally, this really only works when utilizing an iterative design methodology…
08-02-2009 5:38 PM