MVC: not a good architecture for web sites
Before you even mention it, yes I’m writing in english in my spanish blog.
Have you ever tried finding a matching nut for a given screw in a box full of nuts of different kinds, well, that’s how usually looking for the right software architecture feels. Sometimes you’re only given a few nuts, and even if they look about the right size, you’ll have to force the screw to fit in, that’s how it feels to do use the MVC pattern for a web site.
Why is MVC such a crappy fit for web development? Let’s look at MVC history.
MVC was proposed as a very good solution for windowed GUI development in Smalltalk. Every windows was composed as an MVC triad. The view did all the bitmap drawing, the controller handled mouse and keyboard, and the model stored the state of the window and information displayed on it. Each view was bound to a controller and a model on creation. Any given model could be loosely coupled to any view, but every controller/view pair were always bound together to their respective partner. Actually the controller was not expected in any way to have any business logic, it had to handle mouse and keyboard interaction and update the view accordingly, which was not trivial. The model could be shared among displays so it had to be loosely coupled, as much as it’s needed today, but the model/view binding had a specific purpose: having the model notify the bounded views about changes.
Also, views were meant to be nested, i.e. hierarchical (so MVC is by definition hierarchical, there’s no such thing as a Hierarchical MVC, or rather there’s no difference). A window view had child views for the buttons, textfields, comboboxes, and so on, and each of the subviews was part of an MVC triad.
So far, so good. Today all the tasks done by an MVC architecture are covered by GUI APIs, and we have different models to generate interaction with GUIs. Event handling is mostly used to add logic which was before added to a concrete controller, that had been replaced by a generic controller that dispatches events where foreign logic could be applied. Dataflow binding allows to bound a data source to a data display, and handle both request and update, so that the data display can request the data when generating the view and receive updates when the data is changed, also a lazy model could be applied so that the data can be retrieved on demand, rather than preemptively caching the data to be used.
In a few words, MVC is no longer a concern for today’s GUI developer (unless he’s working in a GUI API).
So, let’s see how well the MVC can be exported to a different environment. Web sites (let’s not talk about the diffuse concept of “Webapps”, web development is still mostly doing web sites) are much different that windowing GUIs. Let’s see what the most important differences are:
The web is not a windowing environment. Yes you can have many windows running a web browser, but a web site is window-agnostic and the web doesn’t provide a priori interaction between windowed web pages, i.e. you’re not supposed to know that another web page is running in another window, or having this windows interact with each other. As of now, that’s entirely up to the browser to implement, and you may use javascript to do so, but that’s not what the web is meant for, just someone thinking out of the box.
The web is passive. Although some sites provide an illusion of activity, the web is supposed to be passive, i.e. you request a web page and you don’t receive further updates until your next request. Web sites development mostly consist on dynamically creating web pages on request. Nothing occurs if a user doesn’t request a web page. But, again, this just the common ground for web development, it doesn’t mean you can create a web site that actively updates its contents and act like a desktop app, but that’s still someone thinking out of the box. The web is still just an hypertext repository, until the day the protocols change.
The web navigation is state-less. A windowed GUI retains state of its views even while you navigate through it, the web doesn’t provide a navigation that retains state. You can access any web page at any time and you shouldn’t expect to return to a previous page and have it remember the state it was when you previously visited. State persistence and management during navigation is one of the main concerns of web site development, and no matter how well done it’s the feature that provides this, it will still be a work-around, and probably not fool-proof. We have cookies to store state in the client side, but they are not reliable and provide very limited capabilities. Also, most attempts at providing a state-persisted navigation have/will generally broke the standard navigation features provided by all browsers (backward-forward-history).
The web is composed by many content types and in many encodings. In a web site coexist many documents of different kinds, from HTML documents, images, stylesheets, XML documents, PDF documents, Flash movies, Java applets, etc. Some can be embedded, some cannot. Some need to be properly encoded to be displayed inside another, and even different encodings are used inside the same document, e.g. inside a HTML document, a plain text has to be encoded differently if it’s in the content or inside a tag’s attribute or in an URL.
So how does these differences make MVC a bad architectural choice in web site development?
MVC was designed for window GUIs. A web page is not a window neither functionally nor esthetically. A windowing system generally tries to avoid cluttering too much data in one window, if there’s more to show, better do it in a new child window. A web page has no other choice but to clutter information in one web page, a web user wouldn’t expect to navigate too far to obtain the information he’s looking. Also you wouldn’t have your logo, header, navigation menu, footer, legal notices in every window, but in a web page… Also web pages are rather difficult to decompose to a hierarchical tree, were the basic elements can be handled by nested MVC. It’s either you control all that happens in a web page or you control all that happens in a web page.
MVC can handle passive displays but it was meant for active displays. The model/view pair is at its best when they handle events that occur without the user interaction. Without this, it becomes just a poor template system. MVC would be a good choice for an ajaxy GUI API in client javascript, but for the HTTP server side, mmmm… no.
MVC assumes that the model (view state) is persistent. Usually, web MVC implementations provides models for entities in a database of some sort, but there’s not an actual model for a concrete view, particularly, there is no storing the view state in a model. Because of the way navigation occurs in the web, it’s rather pointless to have the view state stored, it would be reseted anyway at each call. You can have some states stored in a session persistence, but that’s not reliable. Also, due to the nature of the web, having a corresponding model for a view would just translate the cluttering of information in the web page to the model.
MVC was designed for a common graphical environment without special encodings. The content types displayed by an MVC are just bitmaps, the web handles many more content types. Also there are no special encodings that need to be context-aware. Display has a different complexity that needs to be handled by probably more than one subsystem.
Bottom line: MVC is not the best choice for web development. What could be used instead that’s not the quick-and-dirty php script?