For centuries people have sought ways to separate style from
substance, good manners from good science, and user interface from
application logic. The Model View Controller (MVC) design pattern is a
way of separating the user-interface from the substance of the
application.
In recent years, MVC has become a popular strategy for building
websites. There are now web-MVC frameworks available
for many programming languages, for instance Struts
for Java, Maypole for Perl and Rails for Ruby.
This article introduces the MVC pattern and its use in web
development. I will mention some Perl modules, but most
of it will be applicable to any language supporting object-oriented
programming.
MVC is an object-oriented design pattern, so I'll mention objects,
classes and other patterns here. This text will probably not make
very much sense without some experience in OO programming and web
development. Information about all the patterns mentioned here
can be found at the C2 Wiki: http://c2.com/cgi/wiki
Since MVC was originally invented for traditional GUI applications,
certain details in original MVC pattern don't map well to web
applications. (Note 1)
Since I'm describing MVC for the web, I will simplify, change,
misrepresent and ignore those details here.
The idea of the MVC pattern is to divide an application into 3 parts:
the Model, View and Controller.
Let's take a look at each of them.
The Model handles the state of the application. The state is what
your application is about.
If your application is a forum, your Model might contain Class::DBI
objects
representing threads, users and postings. The Model does not know
anything about
HTML, or web servers or anything like that. It just supplies ways to
query the state, and ways to change that state.
The View is the representation of the user interface. Usually there are
many (possibly nested) Views in a single application. A view can query the
model, but it is not supposed to change the state. In web based MVC
systems, a view can be implemented using a template that renders
an HTML page. In our hypothetical forum application, the Views would be the
templates for rendering a full thread, the login page, the posting page
etc.
User actions on the View are send to the Controller. In a web environment,
this is usually done by having the Controller handle the incoming HTTP
requests.
The Controller receives user requests, and translates them
into actions that the Model should take. Then it selects
the appropriate View to handle the response.
It is possible to have more than one Controller, but most web application
frameworks I've used assume you only have one.
Figure 1. A sequence diagram of a single request/response
pair.
Browser View Controller Model
. . . .
. HTTP Request . . .
+---------------------------------->+ .
| . | update model .
| . +-------------->+
| . | |
| . | return status |
| . +<--------------+
| . select view | .
| +<----------------+ .
| | . .
| | query state . .
| +-------------------------------->+
| | . |
| | . return state |
| +<--------------------------------+
| HTTP Response | . .
+<----------------+ . .
. . . .
Notice that the Controller does not handle the communication
between the View and the Model: the Views make direct requests
to the Model.
- Separation of requests and pages
-
Since the Controller is in charge of handling the requests and
selecting an appropriate page (View), there is no immediate coupling
between the request made by the user and the resulting page.
-
This turns out to be very useful if the page-flow in the application is
complex, but even for simple applications the Controller is a good
place to handle common actions - authentication and session management
can be handled in the Controller, for instance.
- Views are dumb
-
Since all code that does anything except building a nice page for the
user is outside the View objects, changing the layout does not involve
touching the logic of the application. Since the part of the application
that changes the most during and after development is the layout,
this means much less chance of adding bugs.
- Shielding of the Model implementation
-
Since all actions on the application state are handled by the Model,
it is possible to change the Model's implementation without touching
the user interface, as long as the Model's public API doesn't change.
(but see Coupling between View and Model).
- What goes where
-
Sometimes is just hard to figure out where a specific piece of the
application is supposed to go. Especially dividing the
Model from the Controller can be hard. As a rule of thumb, the Controller
should be as minimal as possible - it is only responsible for translating
HTTP requests into Model actions and selecting the right View - the
Model should provide all the behavior
it can without handling the HTTP requests or output formatting details.
- Coupling between View and Model
-
One problem with having the View and Controller querying the Model
is that changing the Model's public API means you also have to adapt
the Controller and Views that act on it (Note 2). Adapting the Controller is
usually not too much work, but changing a large number of Views
will be annoying.
-
The Model Model View Controller pattern tries to minimize the impact
of these changes by using two Models: a Domain Model and an Application
Model - the View only queries the Application Model, and the Application
model can query the Domain Model. The Application Model usually
partly generated by the GUI design tools. I haven't used this pattern at
all, so I don't know how useful it is for web applications
- Lots of objects
-
Creating an MVC application can result in more classes and objects than
a ``page-based'' system. That means more design up front. On the
other hand, a well designed MVC system will be easier to adapt and expand,
because the code will be separated better.
Possibly :-) I think that any web-based application that uses more than
a handful of templates, or has a complex interaction between pages would
be a good candidate for the MVC pattern. There are alternatives, of course.
See Resources - Alternatives.
- CGI::Application
-
CGI::Application, by Jesse Erlbaum is a relatively simple module
that provides a good base-class for a Controller.
It's easy to understand and it has some convenient HTML::Template support
(though it doesn't force you to use HTML::Template if you like another
templating system better).
-
You derive your Controller from the CGI::Application
class, handling user requests via the run_modes system
and you can use a templating system to implement the Views.
-
How you implement your Model is entirely up to you. IMO this is a Good
Thing; the model is the most specific thing in an application, and a
framework should not make unnecessary restrictions on it.
- Maypole
-
Maypole, a fairly new project by Simon Cozens is a complete MVC
framework that uses lots
of other CPAN modules: CGI::Untaint, Class::DBI and extensions,
Template::Toolkit etc.
It ``aims to be the most generic and extensible ( ... ) MVC-based web
application framework'', and comes bundled with templates
for building CRUD (Create Update Delete) applications. Maypole runs best
on mod_perl (mod_perl 2 now supported).
-
While CGI::Application's approach is to set up a minimal base for
your Controller, giving the programmer as much
choice as possible, Maypole's focus is on rapid development: the
example BeerDB application requires about 20 lines of Perl and
a database schema. If you're building a CRUD application on mod_perl,
Maypole might be just what you're looking for.
-
All this convenience comes at a price, of course - Maypole is big,
slow to load (can be a problem in CGI environment), and if you
don't want it to auto-generate a whole CRUD application based on your
database schema, it takes a lot more time to figure out than
CGI::Application.
Update
borisz mentioned that Apache AxKit is also an MVC framework. I apologize for missing it. I've never used it, so I can't really tell much about it, though. From the website:
Apache AxKit is an XML Application Server for Apache. It provides on-the-fly conversion from XML to any format, such as HTML, WAP or text using either W3C standard techniques, or flexible custom code. AxKit also uses a built-in Perl interpreter to provide some amazingly powerful techniques for XML transformation.
http://axkit.org/
Update - but wait, there's more!
Yes, I left out more MVC - based systems. perrin points to a list containing server web application frameworks.
Of that list, at least Apache::PageKit, and OpenInteract follow the MVC pattern. Check it out:
http://perl.apache.org/products/app-server.html
- Note 1
-
In ``traditional'' MVC applications, Views and Controllers register
their interest in parts of the Model and will then be notified when
those parts change. (Via the Observer pattern).
This assumes a permanent, single model and persistent views,
which is fine if your application
is a single process on a single machine, but becomes
cumbersome when you spread an application over
multiple processes or machines. Most web based MVC frameworks
use a passive Model instead, where the Controller and View request
information from the Model when they need it.
- Note 2
-
If your Model's API closely
matches its implementation (say, Class::DBI objects where each class
corresponds to a database table), rearranging your implementation
can result in Model API changes.
-
You could argue that having Class::DBI objects in the public API is
not very good encapsulation anyway, but models can change for other
reasons too.
- Maypole
-
Maypole's homepage
-
http://maypole.perl.org/
- CGI::Application
-
CGI::Application - Best Practices Wiki
-
http://twiki.med.yale.edu/twiki2/bin/view/CGIapp/WebHome
- mod_perl - Choosing a Templating System
-
A discussion of many Perl templating systems.
-
http://perl.apache.org/docs/tutorials/tmpl/comparison/comparison.html
- POOP
-
Discussion of several Perl Object-Oriented Persistence systems.
-
http://poop.sourceforge.net/
- Building Graphical User Interfaces with the MVC Pattern
-
An explanation of the MVC pattern in traditional GUI applications.
-
http://csis.pace.edu/~bergin/mvc/mvcgui.html
- C2 wiki - Model View Controller
-
With discussion and links to related topics. Many other design patterns
are also discussed here.
-
http://c2.com/cgi/wiki?ModelViewController
- Web Application Toolkit - MVC
-
A clear explanation of the MVC pattern as used by the PHP based
Web Application Toolkit.
-
http://wact.sourceforge.net/index.php/ModelViewController
- Java BluePrints - MVC
-
Sun's explanation of the MVC architecture.
-
http://java.sun.com/blueprints/patterns/MVC-detailed.html
- C2 wiki - Four Layer Architecture
-
An alternative pattern that directly addresses the problems
in designing a client-server application.
-
http://c2.com/cgi/wiki?FourLayerArchitecture
- JavaWorld - Building user interfaces for object-oriented systems
-
A series of articles describing an alternative to MVC, arguing
that MVC is not object-oriented.
-
http://www.javaworld.com/javaworld/jw-07-1999/jw-07-toolbox.html
Joost.
Re: The Model View Controller pattern in web applications
by perrin (Chancellor) on Oct 24, 2004 at 22:05 UTC
|
There are more toolkits for MVC listed here. Also, although it is not the norm, systems like Apache::ASP and Mason can be used to build MVC systems if you are careful about it. | [reply] |
Re: The Model View Controller pattern in web applications
by pg (Canon) on Oct 24, 2004 at 21:51 UTC
|
"MVC is an object-oriented design pattern"
This is a good introduction, but I definitely disagree with this assertion. MVC is a popular design pattern for web applications, those components, whatever M or V or C, can be realized in an OO way, or a non-OO way, that's simply irrelevant, although it is very normal for one to implement MVC in a OO way nowadays.
Design pattern is higher in level of abstraction than things like OO.
| [reply] |
|
| [reply] |
|
The same simple idea is behind all those concepts: to modulize things. Start from wrapping code in functions, to OO, to MVC, this is all about modulization.
When the web application is no longer just a bunch of static pages, or something relatively static like shipping cart or a forum like this, it becomes too complex for things like CGI etc. Once again, people need to simplify what they are dealing with and the way they looking at the applicatin. MVC comes in.
Model can be simply understood as the data (could be database, a flat file, a set of XML's), or activities against the data (for example a query, or an upadte, an OO method against a dataset object, a SOAP call, a Java Enterprise Bean...)
View is the window for you to see the data and its transition.
You need something to glue your model and view together, or I would rather say to seperate them, but yet attached. Now here comes the controller. As you said, for a web application, this is where your requests got handled.
There are lots of challenges when you do web application in MVC way. My experience tells me that one of the biggest challenge is the cost. If you want to do everything right (everything MVC), with the tools you have now, the effort is hugh. No free lunch!
| [reply] |
|
|
•Re: The Model View Controller pattern in web applications
by merlyn (Sage) on Oct 25, 2004 at 12:09 UTC
|
There's also CGI::Prototype, which I've referenced recently here and in a column. It'll be released soon, I promise. I'm finishing building two different client apps using it, and found a great way to use WWW::Mechanize to test the app without actually involving a web server (joy!), so I'll be bundling this all up soon.
| [reply] |
Re: The Model View Controller pattern in web applications
by metaperl (Curate) on Oct 26, 2004 at 17:36 UTC
|
I would like to mention that HTML::Seamstress was designed from the bottom up to control the view in a completely non-invasive fashion.
| [reply] |
Re: The Model View Controller pattern in web applications
by BUU (Prior) on Oct 24, 2004 at 23:39 UTC
|
This is ridiculously off topic, but it's been bugging me for a while now. I'm using Firefox 1.0pr, why the hell are all of the "headers" in the parent node rendered in big white text that highlights yellowish when I mouse over them? They aren't links because my cursor doesn't transform and clicking does nothing. | [reply] |
|
If you view the source of this page, you'll notice that those headers have anchor tags around them, but these a-tags don't have hrefs. Firefox's behaviour makes sense if there's an a:hover specified in the CSS somewhere.
| [reply] |
|
Your wisdom is enlightening.
| [reply] |
|
|