From Theory to iPhone, Part 2: Separation of Concerns
Model-Editor / Domain-View : On This We Can Agree
For 20 years now, it’s been widely agreed that one of the best ideas for writing a maintainable system is to separate the domain stuff from the interface stuff. This makes especially good sense in a world where you want to make your software available on multiple devices (say, a desktop and a smartphone).
In the world of Smalltalk, the domain stuff was called the Model and the interface stuff was called the Editor. The idea was that you had a single Model and you had one or more Editors for manipulating it. In the Windows world, years later, there was a similar model called “Document-View,” and, indeed, it’s an essentially universal concept when working with GUIs.
From Editor To View-Controller: The Gathering Storm Clouds
Smalltalk went a step further. “Interface stuff” consists of input and output, which are really quite different beasts. So Smalltalk split the Editor concern into two parts: the View concerned with how things are … let’s say … drawn on the screen and the Controller, which is concerned about how … let’s say … mouse clicks and keyboard strokes are interpreted as commands to the domain-stuff and screen-stuff.
This leads to the classic Model-View-Controller (MVC) communication model:
The View requests data from the Model (“What is the city name?” “What is the postal code?”) and outputs it. The Controller routes mouse clicks and keyboard strokes to either the Model (“calculate shipping costs”) or to the View (“Scroll to the next page”). When the Model changes, either in response to a command sent to it view the Controller or by, say, a timer going off, it sends out a notification to any objects that have registered interest in hearing about it.
This model is simple enough, but it does contain some structural assumptions that are not logically demanded by the idea of separating the concerns of Model, View, and Controller. The most obvious is the notification model. Instead of having a Observer pattern, objects interested in the Model could be independent actors that just poll the Model regularly. That’d work: it’s actually closer to the structure of the Web (think about an RSS feed – the server does not maintain a list of subscribers, the subscribers just hit it every once in awhile saying “Anything new?”).
Another assumption (one directly relevant to OS X / iPhone programming) is that the Model maintains the list of its Observers. Another option is a separate notification “hub” that maintains the lists of “objects publishing updates” and “objects subscribing.” (This is how I think one “should” do it in Cocoa.)
Finally, this tidy little diagram begs the question of organizing complete screens. I’ve heard people adamant that one should create an MVC triad for each interface element. They say a BarChart View reflects a NumericRange Model and has Keyboard and Mouse Controllers and that these elements ought to be gathered together into larger units (panels and forms). Each component completely encapsulates its own responsibilities. This is a structure that fits well with most interface painting tools. I argue that such a structure is not MVC at all, but is Presentation-Abstraction-Control. (And I argue that most people get PAC wrong and that this is a cause of much suffering in the world. But that’s a post for another day.)
In my opinion, one ought to think of MVC triads in the coarsest granularity that maintains coherence. Sure, if you’re designing a framework, you have fine-grained MVC triads. But if you’re developing an application, your MVC triads ought to be quite coarse – that if you have a domain / Model object of type, say, Address, you ought to be thinking along the lines of an AddressController and an AddressView (or, in many cases, multiple View-Controllers that view and control the same domain object in different contexts – for instance, a read-only view that occurs after shipping occurs).
Warning: This description of mine does not describe any MVC framework – it’s a discussion of the MVC pattern. Modern MVC frameworks implement things based on an underlying platform and implementation language. I think it’s valid for Rails, ASP.NET MVC, and Cocoa to call themselves MVC frameworks, but even if you scratch under their surfaces, you won’t (quite) see the diagram I’ve presented here. Indeed, that’s the major reason I’m writing this series of posts.