IntroductionThe Model-View-Controller (MVC) Design Pattern is much heralded as the "Right Way" to build web applications. Although MVC is undoubtedly a valuable and useful way to architect such systems, I believe it goes far deeper than MVC alone. In this article, based on a post originally sent to the Template Toolkit mailing list, I suggest that a clear separation of concerns is what is really important, and while MVC is one way of achieving it, it is not the only way. By concentrating too closely on an MVC architecture, it is possible to overlook other important aspects of the system that warrant clear separation. |
I suspect that some people who talk about MVC in regard to web application design don't properly understand what it is, how it should be used, what it's good for and more importantly, what it's not good for. In this article I hope to share some thoughts on how I think it fits in.
Traditional MVC is ideally suited to time invariant applications like your typical window-based desktop application. Your application might have 3 dozen different buttons, sliders, entry fields, window controls, and so on. Any of these "controls" can be pressed at any one particular time, should signal the application "model" to Do The Right Thing, and then cause one or more display "views" to be updated to reflect the new state of the model.
MVC is designed to solve the problem of simultaneously having multiple control entry points, and multiple display outputs, and it acheives that very elegantly. But web applications only ever have one entry point and one output point - the request and the response. You don't have multiple simultaneous controls or views to worry about, so there's little point applying traditional MVC to solve this non-existant problem. Your application, be it a CGI script, mod_perl handler, or even an all-in-one embedded Perl template, receives one and only one request for any one invocation, and it must generate one and only one response. Flow of control is linear and predicatable.
Desktop MVC applications are typically single-user and the in-memory model persists for a session (e.g. while the application is running). In contrast, web applications are multi-user, and in most cases, the per-user model is regenerated on each request (i.e. by restoring a user's session data from a database on each request). There are other differences: controllers are inputs, not chunks of application code as they are portrayed in many web application frameworks; presentation elements can safely contain "programming" code, as long as it's presentation programming, not application programming; the model is the application state, not the application architecture, and so on.
What the MVC-for-the-web crowd are really trying to achieve is a clear separation of concerns. Put your database code in one place, your application code in another, your presentation code in a third place. That way, you can chop and change different elements at will, hopefully without affecting the other parts (depending on how well your concerns are separated, of course). This is common sense and good practice. MVC achieves this separation of concerns as a by-product of clearly separating inputs (controls) and outputs (views).
So in my opinion, it is the separation of concerns that is important rather than the MVC design pattern in particular. The two are different things, albeit working in a similar manner. MVC is (mostly) designed to solve problems that web applications generally don't have. Clearly separating inputs and outputs from the core parts of an application is clearly beneficial, but MVC is by no means the be-all and end-all of design patterns for web programming. Far from it.
In fact, there are plenty of other design patterns that are equally, or more relevant to web applications and to writing good, solid code that clearly separates concerns. For example, the Chain of Responsibility (to implement a pipeline processing model), Mediator/Facade (to abstract internals behind clean interfaces to ease SOC), Strategy (to define a general strategy for all web applications that can be specialised for different requests), Abstract Factory and Factory Methods (to allow different implementations to be switched in/out) and so on.
By concentrating too closely on applying the MVC design pattern and nothing else, many other important aspects may be overlooked. This can lead to a fragmented and fragile solution that fails to clearly separate the important parts of the system and as a result, is hard to develop and subsequently maintain.
So remember to fit each solution to the problem at hand, rather than forcing each problem to fit the same pre-ordained solution. Design patterns are there to help you design, but they are no substitute for thinking about a problem and crafting the appropriate solution.
In his famous essay of 1987, Frederick P. Brooks talked about the silver bullet of software development. A silver bullet, as legend has it, is the only thing that can kill a werewolf. The monster that Brooks had in mind was the software productivity monster that so many programming languages, environments, and methodologies had promised, but ultimately failed to slay.
It should be obvious by now that MVC or any other design pattern is no more a silver bullet by itself than object-oriented programming is. It's just one part of a much bigger machine. The harsh reality is that there is, and probably never will be a silver bullet. And even if there was, there would still be plenty of ways to shoot yourself in the foot with it.