Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Instant Update


Instant Update

Making your data and spreadsheets Web viewable through MVC

New Architect
January 2003

The Model-View-Controller (MVC) pattern is an established and well-understood software design method. It works well in the context of rich-client GUI applications that maintain persistent state. However, the Web is an entirely different medium than a rich client GUI, and porting MVC to the Web isn't straightforward.

The goal in MVC is to separate the application data (the model) from the way the data is rendered to the user (the view) and from the way in which the user controls the data (the controller). Dividing the concerns of the application in this way dramatically increases the system's modularity, and enhances the overall flexibility of the design. Such flexible design is particularly useful for e-commerce.

Modularity

Modularity is a key requirement for any type of software application. Object-oriented programming (OOP) arose out of the desire to increase code reuse and make software architectures more flexible. It was meant to promote better encapsulation of the data used by a program and of the methods that operate upon it. In principle, because objects only interact with other objects through well-defined interfaces, it should be relatively straightforward to swap out components so long as the new components implement the same interfaces as the old ones. The Web services trend takes this model to the next logical level by exposing only well-defined component interfaces to the public via the Internet. Service providers can swap out and upgrade the back-end functionality as needed.

While modularity and separation of concerns are important design issues for any software subsystem, they are particularly critical for user interface design. Consider, for example, spreadsheet programs. Even though the user is able to enter data by typing (or importing) information into the cells of the spreadsheet document, staring at pages of numbers is tedious. Although the spreadsheet cells accurately reflect the information content of the spreadsheet, this is a poor way to visualize the data contained in the document. Hidden patterns may be lying in the data, waiting to be discovered, but they are impossible to see without data representation tools that can provide users with a proper "view" of the data.

Moreover, the user might want to drill down and explore different views of the same spreadsheet document. For example, a simple pie chart might suffice for most of a user's data visualization needs, but perhaps the user also needs to plot a bar chart or scatter graph to better understand some other trend contained in the data. The user also could expect that the charts and graphs already generated would accurately reflect any changes made to the underlying data model (e.g., spreadsheet cells).

Classic Separation of Concerns

Our spreadsheet example is perhaps the most common design pattern in current use: the MVC pattern. First introduced in the Smalltalk-80 interface by Trygve Reenskaug in the late 1970s, MVC is an elegant and simple approach to user-interface programming. It allows developers to seamlessly add, remove, or change views (e.g., new graphic components in a spreadsheet application) without affecting the functionality of any other part of the system.

Another way to think about MVC is in terms of input/output program flow. Controllers define the input interface for a program, the model defines data processing functionality, and the view defines the program output.
At a high level, MVC framework components can be described as:

Model
The model object encapsulates the raw data that defines the application's central structure. A model object has no inherent notion of how it will be rendered when presented to the user, although it does contain public query methods that allow clients (e.g., view objects) to ascertain the model's current state. Model objects also contain mutator methods that allow clients (e.g., controller objects) to modify the model's current state.

Model objects must have some mechanisms to "register" view objects that are interested in communicating the current state of the application to a user. The model object must also be able to notify all registered views whenever a change has been made to the underlying data model.

In Java, the most natural way to implement an MVC architecture is to utilize the Observer/Observable infrastructure that comes as part of this system and provides much of the needed registration and notification framework necessary to make MVC happen. Objects that represent the data in an MVC system should subclass the java.util.Observable class. This allows one or more Observer objects to register themselves with the Observeable (model) object. In an MVC system, the java.util.Observer interface would ordinarily be implemented by a view object.

When the data model changes (i.e., when an accessor method is invoked), the model object should itself invoke two methods found in the parent java.util.Observable class: setChanged(), which tells the Observable parent that the state of the data model has been updated, and notifyObservers(), which signals to any interested Observer objects that a state change has occurred in the underlying data model and that the view needs to be refreshed.

View
The separation of presentation from the data model is an extremely important design principle. If there is a clean and solid separation between model and view in the design, it should be possible to develop entirely different kinds of user interfaces for the same model code. For example, you could transition between a rich GUI client, a Web browser interface, a remote API, and even a command line interface while still sticking to the same model code.

Even if an application just uses one form of user interface, it should still be able to support multiple views of the underlying data model simultaneously. For example, rich client interfaces ordinarily display several representations of the data model on screen at once (as in our spreadsheet example). If a user makes a change to the model from one of the views, that update should be propagated to all the other views simultaneously. An e-commerce Web site, on the other hand, might display different customer pages at different points in the sales process. Separation of presentation from the data model builds in the modularity that allows for this flexibility.

As I mentioned, the best way to implement MVC functionality in Java is to use the built-in Observer/Observable infrastructure. View objects should implement the java.util.Observer interface, which allows them to register themselves with any subclass of java.util.Observer and also to receive notification when state changes occur in the Observable objects they are watching. The Observer interface consists of a single method, update(Observable, Object), which is called when the Observable object invokes the notifyObservers() method. The first argument tells the Observer which one of the Objects is sending the signal, and the second argument includes any optional argument the Observer object might need to pass along.

Controller
The separation of the view from the controller is less important than that of the presentation from the data model. In fact, in many applications, the view and the controller are the same object (e.g., cells in a spreadsheet program). Whether a view also functions as a controller depends upon whether the view is meant to be editable. In our spreadsheet example, the cells in a spreadsheet program provide an editable view of the data, while the graphs and charts don't.

Controller objects should have a reference to the model objects they are controlling. This lets them invoke mutator methods to update the state of the model.

In our spreadsheet example, the different graphs (pie charts, scatter graphs, bar graphs, and so on) represent various views into the data contained in the spreadsheet. These components let the user view data, but not edit or control it. The spreadsheet cells themselves function both as views and controllers. They provide the user with the view of data contained in a specific spreadsheet cell. They also let the user update or control the data model by entering new information. Finally, the application's data model is encapsulated in a self-contained document object. Although the user has views into the document (through MVC "view" objects) and can interact with and update the data by typing information into the cells (which are MVC "controller" objects), the user doesn't usually interact directly with the document object itself. Rather, the document object exposes interfaces through which the user can view and modify it.

I've prepared some sample source code that provides an example of implementing the MVC pattern within the context of a small "thermometer" applet. This example illustrates how to use the Observer pattern to enable MVC within the context of Java. You can see the source code, and download the applet.



LISTING
<html>
<head><title>Hello World JSP</title></head>
<body bgcolor="#FFFFFF" text="#000000">

<!-- This first Java code block is a bit contrived. Ordinarily one would not
place a JSP tag in  an HTML document just to  produce more HTML markup. Rather,
the purpose would be to call on some piece of back-end server functionality that
is ordinarily not available in HTML alone. -->
<center>
<%
 out.println("<h2>Hello World!</h2>\n");
%>
</center>

<!-- This next example is less contrived. When this Java code is compiled
into a servlet on the back end, it queries the HTTP request object for various
attributes. This JSP page is then responsible for rendering the results in HTML.
-->
<b>Information about your HTTP Request:</b>
<ul>
<li>JSP Request Method: <%= request.getMethod() %>
<li>Request URI: <%= request.getRequestURI() %>
<li>Request Protocol: <%= request.getProtocol() %>
<li>Servlet Path: <%= request.getServletPath() %>
<li>Path Info: <%= request.getPathInfo() %>
<li>Path Translated: <%= request.getPathTranslated() %>
<li>Query String: <%= request.getQueryString() %>
<li>Content Length: <%= request.getContentLength() %>
<li>Content Type: <%= request.getContentType() %>
<li>Server Name: <%= request.getServerName() %>
<li>Server Port: <%= request.getServerPort() %>
<li>Remote User: <%= request.getRemoteUser() %>
<li>Remote Address: <%= request.getRemoteAddr() %>
<li>Remote Host: <%= request.getRemoteHost() %>
<li>Authorization Scheme: <%= request.getAuthType() %>
<li>Locale: <%= request.getLocale() %>
<li>Browser: <%=request.getHeader("User-Agent") %>
</ul>

</body>
</html>


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.