Tuesday, October 20, 2009

What granularity for MVC?

Web developers often try to use an MVC architecture. This means that the business end of a website is divided into models, views, and controllers. Models encapsulate your data, and this is where you are supposed to put business rules like, "You can't take more money out of your account than you have in it." Views are about how to present the data. Ideally the model shouldn't know or care about whether the user is going to look at an edit page or a display page, or look at a page in English or Chinese, those things are presentation logic which belongs in the view. And finally the controller is responsible for the necessary glue between them, for instance to figure out what model and view to use for a given URL for a given person.

There is widespread agreement that this is a good thing in the principle, but things get messy when you go to the details. Why? Well in part because people often break the rules they agree to. Business logic creeps into views, models format text that is just passed through the view, and the controller gets into everyone else's business. After a while you're doing MVC in name only. But also there are honest disagreements about a myriad of issues including where exactly to draw the lines between classes, whether to add in helper classes and if so which ones, how complex views should be, and so on.

I'd like to draw people's attention to a design question that few in the web world think about, namely how granularly we should do MVC.

Traditionally in web development people assume that the right level of granularity is the web page. You get a URL, that goes into a controller, sometimes there can be a cascade of routing decisions, and eventually you get to the code that fetches an appropriate model and view, then puts them together to get a web page. Sounds pretty straightforward and flexible.

But what if we have a complex web page? What happens if we add independent sections on a web page that have little to do with each other but need different dynamic information? Alternately how do we handle displaying many related objects for editing? In my experience the natural tendency is for the controller to become a mess. And the view has to be synchronized with the controller, resulting in fragile dependencies.

For an alternative, let's look back at the history of MVC. Originally MVC arose in the Smalltalk world. And the appropriate granularity for MVC wasn't a whole page, it was a component. You'd write Smalltalk applications and every little dropdown could have its own model, view and controller. Which could all talk to each other, and permitted good decomposition of very complex behavior. This idea has continued in the world of GUI programming. For instance an object-oriented Flash program is likely to be developed on a similar paradigm.

What happens if we take this idea back to serving a web page? Well obviously you need a lot more models, views and controllers. However it isn't as bad as it seems because they also become much simpler. Plus it becomes easier to reuse components on multiple pages through a site. The whole page can still become complex, but MVC is a good way to manage it. After all our design is now closer to the original versions where MVC first proved itself useful.

And as a final thought, ever more complex and dynamic client side interfaces make web pages into something more like any other GUI. Which means that at some point there are likely to be real advantages to using component based MVC within the client interface. But this idea is more natural to try when there is no impedance mismatch between your server-side design and your client-side design. Which suggests that you should start with component-level MVC on the server side, and then "lift" components to dynamic AJAXified components one by one as appropriate. Therefore starting with a component-level MVC gives you more flexibility to later evolve a complex, dynamic client-side interface.

Obviously I wouldn't recommend that every developer rewrite their current websites based on this idea. However I think that the benefits are interesting enough that I'd recommend that developers play with this idea, so that they can make an informed decision about whether to try this approach on future websites.

No comments: