daveBlog

Sitting in relative obscurity since 2007…

View My GitHub Profile

Follow me on Twitter

Come work with me!

Site feed

Bindings and the Model-View-Controller Pattern

There has been a lot of talk lately about the usefulness (or lack thereof) of design patterns in software, but the Model-View-Controller pattern is, without a doubt, one of my favorites. For any who are unfamiliar with it, Model-View-Controller separates the code of an application into three tiers: code that presents an interface to the user (View), code that actually does useful stuff (Model), and code that glues it all together (Controller). On many platforms, such as Apple's Cocoa or Microsoft's WPF, the view may be partially (or completely) implemented without explicitly writing any code, which can greatly speed the development process.

One under-utilized implication of the Model-View-Controller Pattern is that very careful application of the pattern allows models to be reused in multiple contexts; for example, a model might be used as the backbone of both a Windows application and a web application (or theoretically, for a Windows application and a Macintosh application; this is currently rather difficult, although I am working to make it a practical reality). However, even when the models are reused, the views and controllers must be rewritten from scratch. In the case of the view, this is often not a terrible burden, especially when there are good tools for creating views on your platform of choice. On the other hand, rewriting a controller is tedious, boring work. Most of the time, a controller does little more than shuttle data between the view and the model and occasionally disable a control or two. You'd think that there'd be an easier way to hook everything up that didn't involve so much pain and suffering.

As it turns out, you'd be right.

A number of modern MVC frameworks provide a relatively new facility known as "bindings". The UI widgets in such frameworks provide you with the opportunity to specify data sources for various properties (for example, the text in a text field or the enabled state of a button). At runtime, the widgets sign up to receive notifications when the applicable properties on their data sources change (generally using something akin to the Observer pattern). If the data source changes its value for a property, the view will automagically catch this update and change its display accordingly. Likewise, when the user changes a value in the UI, the view propagates this change down to the model.

While this ability to bind directly to a model is incredibly useful and can greatly reduce the amount of code required for many applications, it also leaves us with a question: where do we put all that code that doesn't exactly fit in a model but that also cannot be adequately represented in the view (for example, the enabled state of a button)? One answer that has been proposed is Dan Crevier's DataModel-View-ViewModel pattern. In this pattern, the model (which is renamed to the "data model") and the view remain essentially unchanged, but the controller morphs into being just another model. However, rather than modeling the underlying data, a view model keeps track of application state.

When properly designed, a view model is much more unit testable than a controller, and it seems to me that it ought to be more portable between MVC frameworks, as well. Unfortunately, this pattern comes with a practical hurdle that must be overcome: sometimes, a desired behavior cannot be adequately modeled in a way that is usable by the view. It's often tempting to use this as an excuse to bake platform specific code into a view model, but I find this to be inelegant. In such cases, a developer has two options: either new UI widgets can be created (or extended) to understand the new behaviors, or a controller may be reintroduced in order to serve as a bridge between the view model and the view.

I'm fairly certain that each of these approaches has situations in which it is the best solution, but I strongly suspect that a new controller is the best choice in the majority of cases. While this method does add a fourth tier to the system, which will increase complexity, I believe that in most cases, it will ultimately be less work than baking new functionality right into a view toolkit.

I really wish I could come up with a snappy ending for this post, but it just isn't coming, tonight. In closing, if you're not using MVC in your designs right now (or if you're using it in an undisciplined fashion), I strongly recommend that you study up on it and see if it's right for you. If you're already using MVC, but you aren't using bindings, I'd suggest that you look into whether or not your framework supports them, as they can save you from quite a bit of tedious code.

Technorati Tags: ,
comments powered by Disqus