Wednesday, August 29, 2007

Model View Controller

The Model View Controller pattern is popular for organizing Web applications. Yet, there is quite a bit of confusion surrounding MVC. What exactly is it? Whatever it is, it must be good. Like object orientation, MVC seems to have earned a halo. It has a reputation for being a good design practice. Therefore, in a strange twist of logic, anyone who creates a good design must be using MVC, right? Much like good practices that have nothing to do with objects are lumped under that general term, good practices that have little to do with MVC are lumped under that term. A precise definition of MVC is probably impossible.

That said, we do have an historical record to fall back on. MVC was introduced as a graphical user interface organizational principle in Smalltalk in the mid-70s. A later paper, “Applications Programming in Smalltalk-80: How to use Model-View-Controller MVC,” describes the Smalltalk implementation. From this and other papers dating from the early Smalltalk years, we can gain insight into the original intent of the MVC pattern.
The original intent of the MVC pattern was to structure an application with a user interface in order to make certain kinds of changes easier. As I discussed in my first column, “Organizing for Change”, it can be a good idea to segregate different kinds of code in an application, based on the changes that one is likely to make for programs with user interfaces, it is generally considered a good idea to separate the user interface related code from the domain-related code. This is because those kinds of code tend to change for different reasons and at different times. Separating the two allows the programmer to make a change in one without having to touch the other.

Separating the user interface from the domain logic also allows one implementation to be swapped with another. Different views and controllers can be substituted to provide alternate user interfaces for the same model. For example, the same model data can be displayed as a bar graph, or a pie chart, or a spreadsheet. But wait! The Model View Controller pattern has three segments. To separate the user interface from the do-main logic, it would seem that only two would be needed. Why three? This goes back to the original metaphor upon which MVC is based. Conceptually, MVC is intended to replicate an abstract data processing model. In that model, data is fed into a computer as input. A processor uses that data to perform some task. Then some kind of output is produced. Notice that there are three stages in that process. These three stages correspond to the model, view, and controller segmentation of the MVC pattern. Perhaps the most obvious correspondence is the view. This is obviously the output portion of the program. Working back from the end of the process, the model segment of the program corresponds to the processing component. Unfortunately, when may people think of the word ’model’, they think of data, nouns and structure. In MVC, ’model’ corresponds to ’processor’. You should also think in terms of verbs when you think of the model. The model is where the stuff gets done that the program is designed to do. The remaining segment, and the one that seems most confusing, is the controller. The controller corresponds to the input phase of our data processing abstraction. It receives input and translates that input to requests on the model or the view. Why is the controller so confusing? Well, if your model is verb shy, you have to put the behavioral aspect of your domain logic somewhere. Often people will separate out the view or output logic, separate out the data storage logic, and then consider that anything else left must be the controller, right? Well, no. You see, while MVC is a way of separating the user interface from the domain logic, not every way of achieving this separation is MVC. Not every method of structuring a user interface is MVC. In Smalltalk MVC, the idea of having a separate controller layer for input allows an input method to be changed without changing either the view or the model. For example, in a spreadsheet program, a different controller would handle mouse input or handle keyboard input, but the model and view objects would be the same. Fair enough, but how many times in a Web application do you want to swap out input methods without also changing the corresponding output? There is a strong coupling between the input and output methods of a program. It can be hard to change one without changing the other. Another common UI organization pattern is called Document/View. Document/View collapses the input and output layers of MVC into a single view layer. Document/View is a good way of separating your user interface from domain logic, but it is not MVC. We pay a price for dividing our applications into three Parts.

The Model

The model encapsulates the functional core of an application, its domain logic. The goal of MVC is to make the model independent of the view and controller, which together form the user interface of the application. A model could conceivably be used with multiple different view-controller interface pairings. Since the model must be independent, it cannot refer to either the view or controller portions of the application. The model may not hold direct instance variables that refer to the view or the controller. It passively supplies its services and data to the other layers of the application. In fact, there is a variation on the model layer typically used with Web applications, called a passive model. With a passive model, the objects used in the model are completely unaware of being used in the MVC triad. The controller notifies the view when it executes an operation on the model that will require the view to be updated. In another version more traditional to MVC, the active model, model classes define a change notification mechanism, typically using the Observer pattern. This allows unrelated view and controller components to be notified when the model has changed. Since these components register themselves with the model, and the model has no knowledge of any specific view or controller, this does not break the independence of the model. This notification mechanism is behind the immediate updating that is the hallmark of a MVC GUI application. The passive model is commonly used in Web MVC. The strict request/response cycle of HTTP does not require the immediacy of an active model. The view is always rendered anew on every cycle, regardless of changes. This may be especially true in PHP, where no state is retained between requests.

The View

The view obtains data from the model and presents it to the user. It represents the output of the application. The view can be implemented using a variety of techniques, including templates, or a transformative method like XSL. One major misconception I see in beginner questions about MVC is that the view must somehow remain separate from the model. This line of thinking causes frustration with MVC. Programmers end up creating controllers that shuffle data from the model into the view. This is unnecessary. The view usually has a direct dependency on the model. If you change the model, you must also change the view. Because the view depends on the model, the view can generally have free access to the model. Well, almost free access. Views are read-only representations of the state of the model. They should not attempt to modify the model; this would be a violation of the MVC separation. Attempting to modify the model in the view would indicate a mixing of controller code into the view layer. A far more common and insidious violation of separations occurs when domain model code leaks into the view. For example, consider the requirement “Show negative balances in red.” At first glance, this appears to be strictly an output requirement and a test might be placed into the view in roughly this form: if balance <>

Can you spot the violation of separations? Upon further analysis, it turns out that the real requirement is “show overdrawn balances in red.” The definition of overdrawn, here balance <>, belongs in the domain model, not in the view. In this way, changes to the definition of ’overdrawn’ can be made independently of decisions about how to display the status of being overdrawn.

The Controller

The controller receives and translates input to requests on the model or view. Controllers are typically responsible for calling methods on the model that change the state of the model. In an active model, this state change is then reflected in the view via the change propagation mechanism. A passive model shifts more responsibility into the controller, as the controller must notify the views when they should update. In traditional Smalltalk MVC, views and controllers are tightly coupled. Each view instance is associated with a single unique controller instance, and vice versa. The controller is considered a strategy that the view uses for input. The view is also responsible for creating new views and controllers. Modern Web usage of MVC shifts even more of the traditional responsibilities of the view to the controller. The controller becomes responsible for creating and selecting views, and the view tends to lose responsibility for its controller. Sometimes, responsibility for creating and selecting views is delegated to a specific object; this is known as the Application Controller pattern for Web MVC, or the View Handler pattern for GUI MVC. You can see that, as with the view, the controller also has a direct dependency on the model. Changes to the model layer will often trigger corresponding changes in the controller layer. Of course, the reverse should not be true. Unfortunately, as with the view, it is easy for domain logic to leak out of the domain layer and into the controller. This is especially true when the domain model is considered to be passive, verb-deprived data. This is a big challenge for modern MVC frameworks for the Web. The controller can be an inviting place for quick and dirty unstructured code.

No comments: