Build your own Dynamic Web Applications

Using Model-View-Controller (MVC)

By Richard Mischook

It’s easy to fall into a trap and treat designing dynamic web sites in the same way one treats developing static web sites. In this article we will be looking at how the MVC design pattern works and why we should use it.

This article is part of a series on server side development exlusive to Killersites.com.

Introduction

There are lots of technologies and tools available for building dynamic web applications. These include ASP and .Net from Microsoft, J2EE from Sun Microsystems, PHP, Cold Fusion – the list goes on. Regardless of which of these technologies/frameworks one selects, there are certain common patterns that one finds show up over and over again. One of the most talked about is the MVC or Model-View-Controller Pattern and yet for those who might be used to a page-centric style of design, understanding how the MVC pattern works or the need for it can be difficult.

This article hopes to explain the MVC pattern as simply as possible. In subsequent articles we will look at a simple framework I have evolved to enable MVC development in Java without relying on outside frameworks such as Struts.

The Page-Centric Design Pattern

Before discussing the Page-Centric Pattern we need to distinguish between a dynamic web application and a static web site – although for many readers this will probably be obvious. Essentially a static web site is composed of HTML pages that never change, or only change when the author/web-master manually changes them. Contrasted to this, a dynamic web site features content that changes in response to user input. The simplest example is a search engine like Google where what you see depends on what you asked for. More complex examples include shopping and banking sites. Because of their interactive nature these sites can be thought of as applications or programs – that is, tools that can be used to do work.

Some of the easiest technologies for adding dynamic features to web sites include Active Server Pages (ASP), Java Server Pages (JSP), PHP and Cold Fusion. Each of these technologies shares a common attribute: the ability to embed tags on the page that are parsed by the server before being delivered to the client web browser. For example the following bit of JSP:

<%out.println(new java.util.Date())%>

will print the the current date and time when the JSP page is loaded. Hitting reload in your browser will cause the value that is displayed to change each time. Voila – a simple dynamic page.

The ability to embed tags in a page coupled with some simple programming logic opened doors previously been to many web developers. The only real option for dynamic web site creation prior to that was CGI scripting using programming languages like C which, for many HTML developers, made dynamic web scripting un-achievable. The flip side of the accessibility introduced by tag-based development though, is that some bad habits were introduced. For HTML developers used to the web page as the center of their universe, it made sense to put everything in the page. This might be OK for a simple web site wanting to display a counter or the current date and time, for example. But when you start building applications with complex business logic and many functions, this approach can turn into a nightmare.

Anatomy of an Application Request

It might help to look at what generally happens when a user makes a request from a web application. Take a look at the diagram in figure

The first thing a user does is make a request. Let’s use the search-engine example: a user types in what they are looking for and hits the search button (User Makes Request). The web application server receives the request and evaluates it (Evaluate Request). The next step for the application is to assemble the data that the user is looking for, i.e. matching web sites (Retrieve Data). And finally the user needs to be shown the results of the search (Show Response).

Many applications (web or otherwise) will tend to follow this pattern, at least in outline. The meat of the application lies in the work that is done in steps 2, 3 and 4. The Page-Centric model puts all of the code to manage these steps in one place – the page. A smarter approach breaks the code up into components, each of which handles a particular step in the process. Some reasons for doing this are:

  • debugging pages can be difficult and time consuming, whereas debugging components is often far easier
  • using components promotes code-reuse, e.g. a login component can be used from different pages
  • refactoring operations in response to changing requirements are hard to do on pages
  • moving all the tricky stuff out of pages means that non-programmers can work on the pages while those with programming skills can focus on the components

We could discuss this in greater detail but it is beyond the scope of this article. Those of you who have had to deal with complex and hard to understand (and debug) ASP/PHP/JSP pages may already have some idea of what I am talking about though.

MVC Understood as Data-Presentation-Logic

When I first read about the Model-View-Controller pattern I was confused by the terminology. I have always preferred to think of it as Data-Presentation-Logic. Here’s why:

Model = the information that will presented to the user (Data)

View = the component(s) that handles the way that the data will be shown to the user (Presentation)

Controller = the component(s) that evaluate and handle the user request (Logic)

So the model is the data that the user asked for; the view is how the data will be formatted for presentation to the user; and the controller is the component that evaluates the user request. We can map these components to our process in figure 2:

Earlier I mentioned that the MVC pattern really starts to shine when the application get complicated. Our search engine example is useful but perhaps a little simplistic. I want to look at a slightly more complicated scenario to illustrate one way it could be implemented using MVC. In this scenario the user wishes to load a dashboard-style page like My Yahoo, for example.

The first thing we need to do is identify some of the things that can happen in response to a user request to load his or her dashboard (note that the scenario below is still far too simple for a real-world application).

We start with the request by the user to show the dashboard and follow through some of the things that can happen:

If the user is not logged-in then we need to log them in.

After logging in (or if already logged in) we need to check their access rights (for simplicity I have omitted dealing with a fail here).

If the user has not specified their preferences (e.g. they have not chosen what content they want on their dashboard) then we forward to an appropriate module/component to handle that.

Otherwise we fetch the data and show them their personalized dashboard.

Notice that in this scenario there are a few decisions that need to be made in response to the user’s initial request. It is the Controller’s job to make those decisions and invoke the appropriate path in the process. Note also that the Controller can use other components to get things done: a Login component to handle logging the user in, a Data Access Component to get the data from a database and so on. Each of these can be thought of as helpers or business objects because they provide services that can be re-used in other contexts. Note also that as each sub-component is invoked (e.g. login), we probably need a mechanish to send processing back to a Controller so that the user’s original request (to see the dashboard) gets executed.

At the end of this process is a View component that expects to be supplied with some data – in this case the contents of the user’s dashboard. I’ll talk about how we do this in concrete terms in a subsequent article. The thing to note is that the View component (which could be an ASP, JSP or PHP page) does not care how the data gets to it. All that is required is that when the page is invoked, it is supplied with the data it needs to show the dashboard. The View is and should be a relatively ‘dumb’ component with as little logic as possible.