“Those who do not remember their past are condemned to repeat their mistakes.”
- George Santayana
If we hope to grasp the foundation of architectural patterns we have to understand MVC. Every pattern today hinges on this understanding since they, for the most part, have evolved from it. MVC knowledge is an important part of becoming an architect as it teaches us the lessons learned from our past great architects, the issues they encountered, and why they evolved to the next pattern as a solution to those issues.
It is also important to know that for ASP.NET MVC, the (C)ontroller in MVC is an overloaded term and has nothing to do with traditional MVC as outlined in this article; the controller in ASP.NET MVC actually behaves more like a Presenter from the Model View Presenter (MVP) pattern.
Figure 1 – Learn from our past architects, lest history repeats itself…
Martin Fowler tells us in his GUI Architecture article 6 that MVC is the most misquoted pattern, and this was among those architects that understood the Smalltalk environment. To complicate matters, we (todays developers) lack a common core of experience with our great architects (and their articles), e.g., we don’t know what a “controller” is because we’ve never had to work with one, so it is understandable how MVC can be hard to grasp.
Understanding the Controller
“Another irritating feature of MVC, at least with respect to Dolphin, was that the idea of a controller did not fit neatly into the Windows environment. Microsoft Windows, like most modern graphical operating systems, provides a set of native widgets from which user interfaces can be constructed. These "windows" already include most of the controller functionality embodied as part of the underlying operating system control.” 7
The above statement eludes to the underlying difficulty in our ability to understand MVC; it was not designed for Windows (or modern) operating systems – it was designed for systems that had to monitor user inputs and process them manually. Unlike Windows, those systems did not have controls (supported by an operating system) that did all the work for them, they had to manually manage framework features that we take for granted.
For those systems, if you created a text control (view) you had to create a way to communicate with it (update the display from data) as well as a way for the control to communicate with the application (update data from input) – this is where the MVC controller came in. There were a collection of controllers, one for each control on the screen (controller-view pair). Only one controller could have control at anytime (the one receiving the input) so a ControlManager was responsible for managing the hierarchical of controllers to ensure the proper controller was active 3.
The system had input sensors (keyboard or mouse) and as the user interacted with the controls (gestures), the active controller would broadcast the applicable message.
Figure 2: Model-View-Controller State and Message Sending 2
When the controller was initialized it was linked to both a model and a view (control), likewise the view is linked to the model. When a user selects a control (via keyboard or mouse) the controller associated with that control is made active and it broadcast the user input as a message.
This message contains a symbol (#propertyName) and the applicable value 6. The model receives this message and updates the applicable property on it. It then notifies the view that there was a property changed so that it can refresh its associated view, or views (if more than one control are linked to the model property).
So when you understand the role of the view-controller pair as follows: “The view and controller are supposed to create and maintain the user interface, track user events, and update the model when appropriate” 4. You’ll better understand that it is the model that handles all of the application business logic – not the controller or its view.
In summary, at the highest level the controllers only responsibility is to get the user inputs to the model. If we look at todays controls, i.e., a text control, we do not have to worry about this. We can either take a passive approach and grab the content from the textbox control and place it on the model, or we can use data-binding so that as the content is changed the model is automagically updated – the controller functionality is done for us under the hood of the control.
Armed with this information, you can see that with the Windows operating system there is no “C” in MVC – only MV. Some architects wrongly believe the the “C” in MVC is analogous to the “P” in MVP, because they believe the controller is where all of the business logic resides. If they understood MVC they would know that the “P” in MVP is actually analogous to the “M” in MVC because in MVC the model contains all of the business logic, later it was moved to a Presentation/Application, aka view model (more on this below) – this is explained further in the article referenced below “Twisting the Triad”.
Model View Pattern
With Windows the pattern now becomes MV because there is no controller. This does not mean that the MVC pattern conceptually does not apply to us – it still does. For all practical purposes there is no functional difference because the view-controller pair of MVC and the view of today’s control. When it comes to the principles (and issues) of MVC they apply equally to both of us because our view functioned the same function as their controller-view.
Figure 3: Windows View-Model pattern (there is no controller)
Understanding the Model
“This is the data upon which the user interface will operate. It is typically a domain object and the intention is that such objects should have no knowledge of the user interface.” 7
Domain Object (aka Entity)
A domain object is a class that has a clear separation of concerns; it represents a single entity. For example a User domain object would have Last, First, MI, Address, and Email properties. it “should be completely self contained and work without reference to presentation, they should also be able to support multiple presentations” 6.
What does “work without reference to presentation” mean? If the view has a behavior where the email content displays in red if it is invalid, you would have a EmailTextColor property on your model to trigger this behavior – since this is presentation state, you would not want the EmailTextColor property in your domain object; to be technically correct you would place this in the evolved MVC Application Model (discussed below).
A model, by today’s definition, is a class. This class will have properties and methods to handle the business rules of the application; in MVC all processing is done by the Model. The model properties could be any type, i.e., bool, string, etc. as well as entities such as the User entity discussed above.
In MVC, the user inputs are sent to the model via a controller message. The model updates the applicable property and then notifies the view that there was an update. The view is responsible for refreshing itself with the applicable data from the model.
In MV, the user inputs into a control and it automatically updates the model if using the Observer pattern (data binding). If Passive view is being used (no data binding) then the view’s code-behind would have to manually update the model.
In either case, MVC or MV, the model is changed and/or notified of a request (button click) and the model is responsible for processing the applicable business logic. Neither the view nor controller (in the case of MVC) handles business logic – only the model does.
Application Model / Presentation Model (aka MVVM)
Note: the Presentation Model is similar to the Application Model with the exception that the Presentation Model does not permit you to update the view 6.
”Smalltalk 80's MVC was very influential and had some excellent features, but also some faults. As Smalltalk developed in the 80's and 90's this led to some significant variations on the classic MVC model.” 6. One of these changes was the use of an “Application Model” (discussed below) which sits between the view and the model, this allowed for the purity of domain objects by moving presentation state to this new Application Model. Note: the Application Model can consist of your domain objects, but is typically specialized to handle UI behavior 5.
All of the business logic was moved out of the domain into the Application Model, which in today’s terms is referred to as a “view model”. A noted limitation of MVC was the complexity of code required to update the view from the model (particularly since it had no reference to the view), complex view behaviors required special coding and property objects; this was often seen as too much work so unlike the Presentation Model, the Application Model was allowed to modify the UI directly 6.
Figure 4: Functional model (view-controller pair represented only as view above to be consistent with Windows OS)
Understanding the View
“The View displays the Model on the screen. View provides a simple protocol to pass information to and from the Model. The heart of a View object presents the Model data in one particular way that is of interest to the end user. Different views may support the same data, i.e., the same Models, in completely different ways. The classic example is that one View may show data as a bar graph while another shows the same data as a pie chart.” 1
“Each view may be thought of as being closely associated with a controller, each having exactly one model, but a model may have many view/controller pairs”. 2
With the Application and Presentation Model, the view only communicates with the view model - not the domain model; this permits the domain objects to maintain their purity in terms of not having any presentation state or contain “application” business logic in them.
The evolution to the Model View Presenter (MVP) pattern was the solution to the problems inherent in the evolved MVC patterns as noted by Andy and Blair in their “Twisting the Triad” article, Mahemoff and Johnston in their “Handling Multiple Domain Objects with MVC”, and the issues I experienced myself.
My experience working on large projects based on MVVM seemed consistent; I have found that the Presentation Model (MVVM) lends itself to code bloat and the inability to reuse components. As such, I have had to refactor frameworks to MVP-VM to overcome the shortcomings which evolved into blocking issues. some of the pain points that I have encountered follow (perhaps you recognize them as well?):
- All of the business logic is placed in the Application Model (view model) which will have dependencies on domain objects that are more application centric than what a particular view requires. If another view wants to reuse a view model it has to pull in its domain objects and business logic as well, e.g., if it wants to reuse the drain it has to pull in the kitchen sink, which has to pull in the kitchen, which pulls in the house, which pulls in the yard… the architect might find it easier to add on another kitchen, with its own sink, to have the drain that can be reused for their purpose…
- A big issue I’ve seen is when the view model (for all practical purposes) becomes a view code-behind file; the view is so tightly coupled to the view model, the view model serves no other purpose than to handle that one view. The sad part is the view doesn’t even have the benefit of being able to access the view – which lends itself to the next issue.
- Another big issue is when the view’s code-behind ends up being utilized for business logic because it is inaccessible from the view model. What’s worse is when views contains child views that have their own code-behind files. It becomes difficult to locate where the actual business logic resides, particularly with data-binding in the mix - in many cases it can be almost impossible to locate business logic without the assistance of an application such as Snoop because of a deep hierarchical nesting of view/view models with code in both.
- The biggest issue - without the ability to reuse components the application becomes monolithic, hard to maintain, and is not easily extensible.
Below is an excerpt from “Twisting the Triad” – it eludes to the frustration in working with the evolved MVC pattern:
“By now we were once more becoming somewhat disheartened with our framework approach. We were left holding two possibilities that, although adequate, were flawed in several respects (and, when one is engaged on a quest to create the perfect development environment, such flaws seem all the more debilitating).
So, where were we? We liked the Observer aspect of MVC and the flexibility that came from its pluggable nature but it just didn't seem correct that the link between the application model and view was an indirect one. Also, the requirement for "controllers" in the Windows environment seemed out-moded.
To be honest, we didn't feel confident about tinkering with these aspects of MVC purely as the result of our own intuition; we’d wasted enough time already. We were on the point of giving up and resigning ourselves to using our existing interpretation of MVC when a colleague asked if we had looked at Taligent's Model View Presenter framework?” 7
REFERENCE: Mahemoff, Johnston - Handling Multiple Domain Objects with MVC 4
Note: for brevity I only mention the titles – please read the article from reference links below.
Problem 2: Each model-view-controller package should rely on as few other packages as possible
Problem 3: How can views and controllers present information relating to one model and simultaneously enable a user to change another model?
Problem 4: Some models and views have their state defined by one or more models.
Problem 5: Some models reference other models and need to know that they have changed.
REFERENCE: Andy Bower, Blair McGlashan - Twisting the Triad 7
“In MVC, it is a view's responsibility to display the data held by a model object. A controller can be used to determine how low-level user gestures are translated into actions on the model. The various components, M, V and C are all pluggable for maximum flexibility. Generally, a view and controller are directly linked together (usually by an instance variable pointing from one to the other) but a view/controller pair is only indirectly linked to the model. By “indirect”, I mean that an Observer relationship1 is set up so that the view/controller pair knows about the existence of the model but not vice versa. The advantage of this comes because it is then possible to connect multiple views/controller pairs to the same model so that several user interfaces can share the same data. Unfortunately, it is the nature of this indirect link that causes the problems with MVC.”
“In MVC, most of the application functionality must be built into a model class known as an
Application Model2 (see figure 1). It is the responsibility of the application model to be the mediator between the true domain objects and the views and their controllers. The views, of course, are responsible for displaying the domain data while the controllers handle the raw user gestures that will eventually perform actions on this data. So the application model typically has methods to perform menu command actions, push buttons actions and general validation on the data that it manages. Nearly all of the application logic will reside in the application model classes. However, because the application model’s role is that of a go-between, it is at times necessary for it to gain access to the user interface directly but, because of the Observer relationship between it and the view/controller, this sort of access is discouraged”.
“let's say one wants to explicitly change the colour of one or more views dependent on some conditions in the application model. The correct way to do this in MVC would be to trigger some sort of event, passing the colour along with it. Behaviour would then have to be coded in the view to "hang off" this event and to apply the colour change whenever the event was triggered. This is a rather circuitous route to achieving this simple functionality3 and typically it would be avoided by taking a shortcut and using #componentAt: to look up a particular named view from the application model and to apply the colour change to the view directly. However, any direct access of a view like this breaks the MVC dictum that the model should know nothing about the views to which it is connected. If nothing else, this sort of activity surely breaks the possibility of allowing multiple views onto a model, which must be the reason behind using the Observer pattern in MVC in the first place.“
- Trygve Reenskaug and James Coplien - March 20, 2009. The DCI Architecture: A New Vision of Object-Oriented Programming
- Krasner, Glenn E.; Pope, Stephen T. (Aug–Sep 1988). "A cookbook for using the model–view controller user interface paradigm in Smalltalk-80". Also published as "A Description of the Model–View–Controller User Interface Paradigm in the Smalltalk-80 System" (Report).
- Burbeck, Steve (1992) Applications Programming in Smalltalk-80:How to use Model–View–Controller (MVC)
- Mahemoff, Johnston. Handling Multiple Domain Objects with Model-View-Controller.
- Hopkins, Horan. SmallTalk an introduction to application development using VisualWorks
- Martin Fowler (2006), GUI Architectures.
- Andy Bower, Blair McGlashan. Twisting the Triad, The evolution of the Dolphin Smalltalk MVP application framework