|MVC - it's the routing stupid!|
|Monday, 27 December 2010|
Page 2 of 2
If you think about what actually happens in an application you can start to see that MVC is a gross over simplification. It has to be in order to fit so many proposed situations,
Adopting MVC is a mainly a way to avoid analysis and building a more refined and appropriate model.
Still any architectural model is better than none at all - which is the way web applications have been built until quite recently. Sun calls such unstructured applications Model 1 web apps and the newer variety with a separate up-front controller web 2 apps and this is an interesting distinction that we will have to return to if we are to follow what is really on offer with an MVC approach.
In practice the MVC model doesn't fit well with most situations unless is is used as the starting point for a more complete model.
If you simply embrace the MVC model as a way of avoiding analysis and building a more specific model then in many cases the result is something that seems awkward. Beginners in particular often find it hard to stick to the MVC plan and the result is usually incomplete or half hearted MVC implementations. In many cases the resulting mess would have been better served by not adopting the MVC model at all.
Let's take a look at how MVC fits with reality.
Consider the job of the Model - it has to access the data and manipulate the data. Notice that in this very simple statement we already have two tasks for the model and this means that we can separate the concerns even more by splitting the model into a data access layer and a manipulation layer.
Indeed most MVC frameworks don't impose on their users a choice of data access method. This is good but it also means that this issue isn't addressed and beginners think that they have to build data access within the Model framework. In nearly all cases a much better plan is to implement a data access module - using ADO, XML, JSON or Object Relational methods - and interface this with the Model which performs whatever data manipulation is required. If the interface can be kept small and general then creating a new data access layer should be just a matter of plugging one in.
So much for the three components of MVC.
Next turning our attention to the View, which should be dumb, we have to consider its relationship to the UI.
The View accepts prepackaged data and displays it - and this is all it should do. There is already a problem with this simple idea when you come to implement it which many beginners find puzzling and worrying.
The Model serves up the data and the View accepts it - but in many cases this is a lot of data and the connection between the two is a very thick pipe. The beginner has to manually wire up the data that the Model outputs into the UI that the View creates - and this is often after having to wire up the connection between the data access layer and the Model. It all seems like a lot of duplication and a lot of typing.
Of course modeling the domain using suitable objects - e.g. an Order object, Customer object and so on - makes this task a lot easier and more logical - but now we have another module - the domain object model which is passed around the MVC architecture to wire the basic components together.
Now consider the UI that the View creates. This will have display only data fields which emphasises the passive nature of the View but... there will be modifiable fields and action components such as buttons.
The big problem is what to do when a button or some other action component it clicked?
In even more direct terms - who handles the event?
In principle it should be the controller which is supposed to always be the acceptor of the user's commands.
However this doesn't always fit. Consider a button that submits a form after checking the validity of the data. The button belongs to the View, the click event belongs to the Controller but the validation belongs to the Model. Seems logical but wiring this together is a lot of work.
In addition most web programmers would opt to do the validation in the client side using a script. Client side scripts and client side state in general is not something that naturally appears in the MVC architecture.
That is the MVC model is not by its nature a client/server model.
Efforts to remove client side dependencies are cruelly logical but result in crazy architectures such as the ASP .NET round trip triggered for every event and every minor update.
In this architectural approach there is no client side!
Of course we all know what happened next - we waited years for someone to point out the obvious and Ajax was born. It is simply ludicrous to ignore client side processing and it is therefore ludicrous to insist that the Model is the repository of all data processing and validation and that the Controller handles all user interaction with the system.
It is very hard to decouple the presentation of data from the user's interactions with that data and the idea that a View is a dumb component is one that can only be maintained if the data is immutable and the interface has no input controls.
So it looks as if the MVC architecture is at best a starting point and at worst a complication that forces the programmer to convey data and events across module boundaries in a way that is unnatural.
However there is one thing about the MVC approach that fits right in with a modern web app and this is routing.
Some user interactions are not with data but with system state.
It's all a matter of what will happen next.
It is usually said that the web is stateless in that you move from page to page without altering the state of the server - it simply serves the page. But... moving from one page to another is a state change for the client. When the user clicks a button that causes an action that confirms an order or requests information or just some other part of the application this is a state change and the big difference between Web 1 and Web 2 applications is that this state change may be on both the client and the server side.
In the early days such state changes were handled using primitive mechanisms such as CGI and scripting. Today we have a much better paradigm - routing. The idea is that the URL should be used to carry the verb that initiates the next task/state change. Routing carries the client and server state in the URL and it links the two states together.
The main purpose of the Controller is to implement and/or oversee routing. As in the case of the other MVC components it is common for the Controller to be split and to have the help of a Routing engine but in many cases the Controller is the Router and is does little else than connect object and method calls to particular URLs.
If this sounds to you a lot like REST - Representational State Transfer - then it is worth pointing out how it differs.
The REST dogma states that it isn't simply a mechanism for RPC - Remote Procedure Call. The only "verbs" allowed in REST are the standard HTTP actions such as PUT, GET and so on. As a result a URL used for routing fails to be REST because it specifies a task that goes well beyond the HTTP actions.
Routing is the most general and hence most powerful use of the URL to specify a state change. It can say what should happen and supply the parameters that specify the action exactly.For example:
can translate directly into a method call on a particular object passing it the parameter id=400.
Notice that in this case parameters don't have to be simply part of the query string. You can use URL routing templates such as:
The arguments for using REST's approach to restricting verbs to HTTP actions is on the face of it reasonable but it attempts to make web apps look more like web pages than apps.
It is the passive approach to creating applications that is also found in the functional approach to programming. You can't simply dismiss it but if used as a blanket technique it misses what is powerful about programming - doing something!
We write programs and programs do things that are active - we need the freedom to implement rich and sophisticated verbs and because of this the strict interpretation of REST is a nonsense.
If you look carefully at what parts of a typical MVC framework actually make the implementation of a web application easier you will find that it is the use of routing as supplied by the controller rather than the Model or the View. The immediate payoff in adopting most MVC frameworks is that you have a ready-made routing system that you can use to build the application.
This doesn't mean that a good architecture for the data presentation, manipulation and access isn't desirable, only that the MVC model doesn't supply it out of the box. It does however supply routing off the shelf, leaving the user to basically implement some routing templates to govern how URLs map to method calls.
So it is arguable that it's not the MV part of MVC but the C part that is responsible for the adoption of the model by so many - and only because it adopts the most flexible and powerful interpretation of routing.
Perhaps it should be called MVR - Model View Router.
If you would like to be informed about new articles on I Programmer you can either follow us on Twitter, on Facebook , on Digg or you can subscribe to our weekly newsletter.
|Last Updated ( Monday, 27 December 2010 )|