Monday, November 26, 2012

View Models and Yet Another Layer

Imagine that we could just transfer the data model our application uses, straight to the client. The client user interface can use this model, the same model the server-side components are using. What's the point? The shared data model, in theory, is a big win because you get at least some level of consistency. The view model is the representation of the application model I'm talking about here - it gets transferred to the client. A replica, as it were, of the reference model. The canonical model that any application components, client or server, should reference.
This is the representational state transfer idea — REST. You might even call a view model a tool that aids in the RESTful principle. The view model is just a representation of the application model. How it aids the client in using this application data model isn't clear-cut. At least not for myself when I first started exploring the concept. I had this notion that you have this data model, probably in a database, and the client just takes what it needs, when it needs it. You need to display just a handful of fields, belonging to some object on a detail page? The client fetches that data through the API, populates the user interface. Done. This is the RESTful approach — we're grabbing the state of some object of some model and transferring it to the client.

The view model is a proxy for the model that resides on the server. It is a representational model. It is different in that it represents the entire model, not just bits and pieces of it as the user interfaces layer requires. What's really interesting about the tools that implement the view model approach, like Knockout and Backbone, is that they behave as though they're an observer for the database. You can bind user interface components, like DOM elements and values, directly to the view model. So, unlike the approach where I write some code that queries the API, and then in a callback, I have to figure out where the resulting data goes, I just need to populate the view model, and it knows what to do. From an API perspective, this works really well. I don't need to think about my user interface code querying the API. I have a nice separation of concerns. My code is either dumping data from the API into the view model, or it's manipulating DOM elements as a result of bindings to the view model. A direct mapping to the view model from the user interface components means that the programmer doesn't usually have to implement event handlers. The logic is in the bindings.

When you think about web application architecture in terms of layers, the view model is yet another layer. That is, the view model tool employed, be it Knockout, Backbone, or something else, is just an encapsulated translation layer. You put data in, and get updated DOM elements out. But as we all know, layers are a dependency. A dependency is sensitive to change. Take the application model for instance. These change, that is an expectation we should expect and prepare for. So too then, does the view model. We have to reflect model changes in two places — the server model and the view model. Which is to be expected, the client needs to understand what data it has to work with, and the view model is just one way of communicating that data structure.

Here is the problem. How do we separate the data model from the user interface? How do we go about manipulating the structure of the data model independently? Well, you can't really. You still have to bind your user interface components to the view model. These components are affected by change. Again, this is not unexpected. View models aren't completely isolated from their environments. When we do have changes to think about in the data model, view models aren't difficult to update. We have to change the way the view model is populated, and the way the bindings to that model work due to the new or changed data available.

View models work best as a thin layer between the API and the user interface. The DOM elements. Where they don't work so well is with widget toolkits — like jQuery UI. The problem is that the widget toolkits have their own data model for each given widget. It's best to have a programmer translate between the application data model, and what we can feed into the widget. A view model cannot really help us there. Just keep in mind that with a view model directly to DOM, and some minimal Javascript and CSS — we have more freedom in what we do in the view model. How we interact with it. On the other hand, adding yet another layer between the API and the widget components of a Javascript toolkit is often more constraining than beneficial.