What is MVC?

by Curtis Poe

If you read up on the Model-View-Controller (MVC) design pattern, you might find yourself a bit confused. In fact, I found myself confused by it when I first started reading about it, because there are plenty of resources out there to describe it, but so many of them seem to have different flavors of MVC and different diagrams explaining how data flows that it's no wonder that programmers are bewildered about it. Fully believing that I don't want perfect to be the enemy of the good, I'll show a few practical implementation details of one way of looking at MVC, primarily focused on the Web needs.


7 Comments

George Jempty
2007-06-21 08:52:18
"I didn't really explain MVC itself. That's because there are several flavors of it"


But there shouldn't be. MVC's even simpler in a web context because there is no "listener" to code: the web server does the listening for you. This actually simplifies "MVC2" (for the web) down to pretty much a concrete instance of the Mediator pattern: the Controller mediates between the Model and the View.


Anybody who tells you anything different is a liar and a fatmouth ;)


But seriously, in the past 9 or 10 months I've written code in THREE languages which is meant strictly to properly separate the 3 concerns that comprise MVC (rather than being a "full stack" framework replete with ORM layer, etc.) The crux of my code in pretty much any language being


A) the notion of a "ModelTransferObject" (or MTO: Spring WebMVC's "ModelAndView" is actually what I would call a "ModelTransfer Object"),


and B) a "template method" leaving the user to implement the intuitively named methods: applyInputToModel() & applyModelToView(). Here's that template method in PHP:


static function sendResponse(IBareBonesController $controller) {
$controller->setMto($controller->applyInputToModel());
$controller->mto->applyModelToView();
}


And in Python:


class AbstractController(IController):
def sendResponse(self):
self.applyInputToModel().applyModelToView()



Other than that the core framework in either of these languages weighs in at about 50 lines of code!! After successfully that THIS is the very abstraction that ALL more fully-featured web frameworks (with Dispatch and/or Flow controllers) should be built upon

Youdaman
2007-06-26 19:55:53
I must be "a liar and a fatmouth", but there is indeed more than one flavour of MVC. With TT you don't need to "applyModelToView" or push stuff from the Model to the View, but instead the the View can pull stuff out of the Model (via the Controller). So there's at least 2 flavours ;)
David Stanek
2007-06-27 04:11:09
I do see the value of many flavors of MVC, but I'll call them implementations. The crux of MVC is to try to isolate the domain model (business rules) from its use. The use being not only the presentation, but also the application specific logic that glues the rules together in some order.


There are many implementations of MVC for good reason. Each has a trade off with regard to reuse and coupling. Also language design plays a hand in the implementation.


Stepping back to the basic GoF design patterns shows that a pattern is designed to show a conceptual solution and not the exact implementation. For example, a singleton is often implemented as a class without a public constructor. In Python I usually implement it as a module level attribute. They are completely different implementations, yet the both allow for only one instance of a particular class.

Jorge Gomez
2007-06-27 14:31:24
The code you highlighted (with the mixed responsabilities) looks like it was taken straight from my server.


I've been in the proceess of cleaning as much as I can (since reading the excellent Perl Best Practices), but I hadn't thought to take the separation as far as you showed.


Could you please go into some detail about separating control from model? In other words, where would the $dbh finally go?


For instance, what about a subroutine when all I need is to display a list of (say..) invoices. Should I make an Invoice class and then an InvoiceList class?

Ovid
2007-06-28 00:28:07

Jorge: as a general rule, the $dbh should never be seen in your controller code (for those not familiar with Perl, $dbh is the traditional name for a database handle). That belongs in your model or even further down. In fact, if you use an ORM (object relational mapper), that's where the $dbh should generally be with the model layered on top, potentially delegating out to various ORM classes. The reasons for this strategy are probably the subject of another blog entry, though.


As for an Invoice class, that can be handy, but it's generally much better to have a generic Collection class -- or something conceptually similar -- to put them in, rather than an InvoiceList class. That's because a Collection can be reused with other classes and your code will know how to deal with a Collection.


In fact, the only reason I could think of to create an InvoiceList class would be if, for some reason, you had more specific needs than a collection. In that case, you might do something like this:


package Collection::Invoice;


use strict;
use warnings;


use base 'Collection';


sub next {
... invoice specific code goes here
}


If you do something like that, you can ensure the same interface as with a collection, but override methods for your invoice-specific behavior. The important thing to remember is that you must be able to use Collection and Collection::Invoice the same way!. The latter might offer additional behavior, but it shouldn't offer less. See the Liskov Substitution Principle for more information.


So, in short, make sure your controller only contains control flow code -- something harder in practice than many would think -- and try to write generic classes which are easy to reuse.


Also, if you're migrating a codebase to an MVC style architecture, trying to do it one piece at a time can help. Do everything at once can be fatal.


2007-08-22 10:27:38
I like the way Curtis has defined Model, View, and Controller. Now that if people try to learn the 'usually unnoticed' difference among them.


Good article!

Roy Vincent
2008-07-30 03:50:55
nice article.... ^___^