Tuesday, June 1, 2010

Control that view to the model

Remember that good old model, view, controller idea – simple isn't it? We need only a model, a view and a controller. Maybe we want more than one view – that would be nice. But then, what is a model – and when does one model become two models? OK, but surely the controller is simple – it must be a singleton, or not? The thing about MVC is that once you get past the M, the V and the C, you may have more questions than answers. Soon we all end up with our own definition of vanilla MVC. Then we deviate from this unattainable ideal. We have many excuses because we face real world problems, imperfect operating platforms, clunky programming languages, silver bullet UI frameworks and so on.

Maybe these realities are challenges, not excuses. Maybe throwing away the architecture is not an option and new ideals are what we need. But, before we go to that braver place, let's first find out where are we now.

My own vanilla perspective considers the MVC triad as three separate concerns. Each concern has a basic set of responsibilities. It goes without saying that I think this perspective is in fact crystal clear and entirely practical ;-)

  • The Model encapsulates the state, and exposes the functionality of the application. It notifies clients of significant changes to the state.
  • The View renders the model to the end-user. It receives notifications from and performs queries on the model.
  • The Controller defines the application behaviour. It receives a gesture event from the view, transforms this to an action and applies the action to the model. It also selects the parts of view to show as a response to an action.

From these responsibilities, it is clear that the model is the foundation, and that it should be isolated from the view and controller. This separation is a key benefit of MVC. The idea being that one can use the same model to write diverse applications that run on different technologies. Practise show that this benefit is unlike to be a key factor in most applications. However, it does help to think along these lines when putting together your application architecture.

Instead of one technology independent model, I lean towards the idea that there is some part of the model that is technology specific. I separate this part into a sub-concern called the application model. Those really non-technological model classes; that is the domain model.

This domain model exposes the functionality in terms of entities, values objects, repositories and such things. It is also responsible for validation and transactional cohesion of the information kept on long term storage. The application model is responsible for the application state - i.e. the information created during the application run cycle. This information could include session management, caching, job management, selection management and so on.

The application model for a web application might focus on remote user sessions, shared caching, cookie or server based user state (for shopping baskets and so on), while a rich client has client sessions, local cache and local user state in its application model. When writing for particular technology, the line between the two model types easily becomes blurred. The disadvantage of this blurring becomes very clear when the application is ported to a different technology or to a new framework. However, less radical changes could also be prohibited when mixing application and domain model classes. It could become difficult to fix non-functional problems (such as performance and responsiveness issues) without affecting key functional areas of the application.

The model could be a grey area, but clearly the view and the controller are technology specific. Different technologies call for different approaches on how views are to be rendered and how user gestures are captured and transformed into actions that are applied to the model.

It is good design practice to delineate a namespace for each concern. These namespaces form a layered design. Each namespace provides services only to those above it. At the bottom is the domain model – it does not consume services from any other namespace. Right above the domain you'll find the application model, and the view is the next layer on the stack. The top layer is the controller. The controller can use services from any other layer – and it provides no services to the other layers.

With these namespaces in place, the process of design starts with a decision where to place a new class, and to make sure this class does not violate the constraints imposed by its designated layer.

When the allocation of a class to a layer is not obvious, consider choosing the top layer and move down only when the need arises. For instance, if it is not used by any layer other than the controller, it belongs in the controller. You can always move it down later when things become clearer – but it is more difficult to move it up to a higher level in the stack (when things become more muddy).

Consider yourself reminded of the MVC basics – look, think ... improve!

0 comments:

Post a Comment