Wednesday, September 26, 2007

A Review of the MVC pattern

Tight coupling among software components is one of the common problems in large enterprise applications. This is due to the large amount of data and the way in which this data is represented to users of the application. In practice, it's very easy to fall into the problem of writing unorganized code that, although it delivers a product, it does not maintain any known convention or standard. This only contributes to the problem of extending application functionality (scalability) which is almost certain to happen. Many design patterns are used in the industry to solve different business problems. Among these, the Model-View-Controller (MVC) pattern is one that if often misquoted and misused. In using the Struts Framework for building web-based applications, it is crucial that every developer understand this pattern.

In the MVC patterns, a clear distinction is made between three different components. These are the Controller, the View and the Model. Each of this components help segregate and centralize certain functionality of our code away from each other (loose coupling), thus scalability and re-usability is feasible. The following figure provides a small representation of how this components are meant to interact:

Figure 1 - Diagram of the Model-View-Controller Pattern

In this pattern, the Model component is a representation of some business data. This is also known as "domain model" and is specific to a business. It can also serve as a representation of a "real-world" process that the application is identifying or hold the state of a business entity. The View component is a specific display of the model component in the user interface (UI). This is also known as the "presentation layer" of the application. Thus, if the model component is a BankAccount object, the view component may be an HTML page containing account balance and transactions, or a frame of UI widgets representing the account holder personal information. Note that for both of this examples, the model knows nothing about the view, however the view needs to know some about the model component in order to display it. This direction in dependency is an important concept in this paradigm which encourages loose coupling among components: Developers programming in the model component do not depend on the presentation layer.

Changes to the model component (information holding business data) are handled through the Controller of the application. This means that if the view component has a function (e.g a button, or a drop-down) that needs to be triggered in order to execute an update on the model component, the view communicates this event to the controller component who executes this change and updates the model component. This level of redirection ensures the controller to handle the proper action per view according to business needs. For example, a bank account number may need to be "read-only" to customers but to staff members, this may be an editable field. In this case, it is up to the controller to decide whether the action of updating the account number should trigger an update operation on the model component and is up to the view component to determine if this functionality is even displayed to the user.

In the context of the Struts Framework, the MVC pattern can be represented using the following diagram. Note that the three components of this pattern appear in the same order as in Figure 1:

Figure 2 - Struts implementation of the MVC pattern.


Struts is focused on web-based Enterprise Applications and is heavily based on Servlet Technology. At the core of the controller component is the ActionServlet object. In general, this servlet forwards control to Action objects (to perform CRUD operations on the model component) or to another view component. This ActionServlet knows how to associate view components with specific Action objects through one or more XML files loaded during the servlet initialization process - init() method. Thus changes to this XML file typically represent a reload of this ActionServlet. In this approach, developers are left to insert code in the Action objects of their choice in order to perform changes in the component. When objects need to be placed in the presentation layer, the controller also uses this Action objects to place this model in proper scope (page, request, session, etc).

Struts also provides different tag libraries to help in the rendering of the model components in the presentation layer (view), however, it is left to the developers to decide how to display the data by virtue of the MVC pattern. This means that JSP, velocity or any other rendering engine can be used as part of the presentation layer. As for the model this can be any representation of the domain model of the application such as an entity bean EJB, a Java Bean using Hibernate (Session in View) or Data transfer objects to partially represent a domain model object. Other components can also be plugged to controller component such as resource bundle configuration, menu capabilities, tiles, etc. This pluggable architecture mixed with other configurable features (e.g. validation) has made Struts a preferable option when choosing to use the MVC pattern as part of the architecture of a Java Enterprise Application.

Loose coupling between components is the key concept. Different frameworks are available in the open source community, among which some offer an MVC architecture for Java Enterprise applications, however keep in mind that, as quoted in Martin Fowler's "Patterns of Enterprise Application Architecture":

"The value of MVC lies in its two separation. Of these the separation of
presentation and model is one of the most important design principles in
software, and the only time you shouldn't follow it is in very simple
systems..."
(page 332)

So, keep these in mind when using Struts. Additional features offered by the framework should not be confused with the objective for which Struts was designed. Overuse and/or additional design without careful planning can prove to reduce scalability thus reducing the value of the product in the long run.

No comments: