Twin Forces

Model-Facade-Controller-View

Design Pattern

(MFCV)


Main Page

Technical Docs

Design Patterns

Intent

The Model-View-Controller Pattern in SmallTalk and partially supported in many Frameworks sought to solve the problem of decoupling the user interface from the datamodel. The MFCV pattern is a refinement of the MCV pattern. The MFCV pattern adds a new object to the relationship called the Facade. This refinement brings the MCV pattern more closely in sync with its actual use by most programmers when using a framework, increases the robustness of the architecture, and speeds development.

Additionally, the Facade class becomes a logical repository for methods that handle user commands.

Also Known As

An alternate terminology consistent with most frameworks would be: Model-Document-Window-Control.

Motivation

Two things are guaranteed to change over the life of any project: The user interface, and the data structures. Using the MFCV pattern, coupling between the data model and the UI are kept to a minimum.

Applicability

The MFCV pattern is applicable to any program that has a collection of data and a user interface that acts upon that data. This includes most of today's event-driven programs. It is especially applicable to applications written using a UI framework. When using a typical UI framework the classes defined in the pattern map directly onto typical framework classes.

Structure

Participants

The classes participating in this pattern are: The Model, the Facade, the Controller, and The View.

Model

The Model class is just a shorthand term for the entire data model used by the program. That is, its really the entire collection of classes that make up the data mode.

  • Shorthand for entire data model, whether one class or thousands.
  • Holds all the data used in the program.
  • Changes in Model should only affect the Facade.

Facade

The facade class is an implementation of the Facade pattern from the Design Patterns book. It lies between the data model and rest of the system. Specifically, it has the following duties:

  • Provides API to the rest of the application to access the data model. All data model accesses go through the facade.
  • Translates between Model data formats and UI data formats.
  • Generally also provides functions to read/write the entire data model to permanent storage though that is not a specific responsibility of this pattern. Facades that perform this function are called Documents.
  • Changes to the Facade are only driven by changes to the Model or Controller classes.
  • Responds and processes high-level actions generated by the user or the Controller classes.
  • If the application is using the Command pattern from the Gang of Four book, the Facade is the object that actually collaborates with all Commands that affect the data model.

Controller

The Controller class manages the View objects associated with a UI component, generally a window. It translates actions generated by View objects into commands to the Facade. For instance, a Controller object might translate a particular "ButtonPressed" action from an OK button into an "UpdateData" message for the Facade.

  • Mediates data transfer between the View classes and the Facade.
  • Translates user interface events into high-level actions for sending to the Facade.
  • Creates/Destroys View Classes.
  • Changes to the Controller are usually driven by UI changes.
  • Generally performed by Window or Dialog classes in most frameworks.

View

The view classes are the classes that actually respond to user events and turn them into an actions. For instance, a View object for an "OK" button turns mouse clicks into "ButtonClicked" messages.

  • Responsibe for displaying a single quantum of data. For example, a control for editing colors.
  • Responsible for translating low-level events like mouse clicks and keyboard presses into high-level events.
  • Controller-View groups can sometimes be encapsulated to generate a compound view. For instance, a color editing view, a text edit box and a suitable controller might be combined to make a compound view for editing "named" colors.
  • Changes to the View are only necessary for improving the UI, or changes to their fundamental quantum of data.
  • Generally performed by Control classes in most frameworks.

Collaborations

Each class collaborates between the other classes next to it in the line. The Model collaborates with the Facade, the Facade with the Controller, and the Controller with the View.

  • The Model and Facade collaborate together to translate data to and from the format used by the UI. For instance, it is very common to have to turn a number into a string so that the user can change its value. The string value must then be turned back into a number and validated. This is done by the Facade. The Facade must have knowledge of the structure of the data model, but the Model need not have knowledge of the Facade.
  • The Facade collaborates with the Controller to read and write data from the data model. The Facade doesn't know the needs of the UI is, and the Controller doesn't know the structure of the data model. Generally, the Controller will pull bits of data out of the model via the Facade, and transfer them to one or more View classes. When the user completes an action, the Controller will then use the Facade to modify the data model.
  • The Controller collaborates with the View classes to present a view of the data to the user. The View classes collaborate with the Controller to translate user actions into high-level actions that are ultimately passed back to the Facade as commands.

Consequences

How does the pattern support its objectives? What are the trade-offs and results of using the pattern? What aspect of system structure does it let you vary independently?

  1. All data translation is located in one place, the Facade.
  2. All UI overview knowledge is located in one place, the Controller.
  3. All event handling is located in one place, the View.
  4. The Model and View classes are less fragile and are more likely reuseable between programs.
  5. Each class becomes more tightly focused and therefore easier to develop and re-use.
  6. Test code can be written that directly exercises the Facade class. This aids immensly in debugging the data model.
  7. Model data structure changes only affect the Facade.
  8. UI changes only affect the Controller classes.

Implementation

What pitfalls, hints, or techniques should you be aware of when implementing the pattern? Are there language-specific issues?

  1. A naive criticism of this pattern might be that it adds overhead to the implementation. In practice, this isn't really true. There is little if any need to sub-class the Facade pattern, which means that there is no reason not to make all of its methods in-line if necessary. I personally don't bother because its rare that the time to call a subroutine to call sprintf is higher then the operating system overhead for creating the UI in the first place. When it is significant, I just change the Facade to provide data in larger chunks. For instance, the Facade might return a list of strings rather then return each string individually.
  2. Using a Facade takes some discipline. Its awfully tempting to type

    sprintf(string,"%f",model.value)

    instead of

    facade.GetValueAsString(string)

    On the other hand, how many times have you used an sprintf only to have to go through and replace the formatting code in a hundred places to

    sprintf(string,"%.2f",model.value)

    because you didn't want the dialog box to have 1.999999999999 but rather 2.0? A Facade locates all that code in one place. Also, I personally have found that its the formatting code where I'm most likely to have typos or mistakes. When I use a Facade I only have to get it right once.

  3. Another argument for the Facade is that many applications have to translate between an integer and a text description of the value. For instance, 0 might mean "None", 1 is "Bold", 2 is "Italic". The thing is, that code is generally extremely useful in multiple places in the program. Naive code often begins with a case statement in the Controller class, then moves that code to a separate routine (after cutting and pasting it a couple of times between controller classes). The Facade is a natural home for such code where it can be used throughout the program. Then when you add 3 is "Underline", you don't break the entire program.

Sample Code and Usage

Imagine you want to write a program that allows the user to create a list of named colors. So the data model is fairly straightforward, you have a string and a color. The UI for this might consist of a window with a name followed by a rectangle displaying the color. At the bottom of the window there would be three buttons, "Add", "Change" and "Delete". When the user clicks on Add or Change, a dialog comes up where they can enter a name and edit the Color. Clicking Delete removes the selected color from the list.

So far so good. In most frameworks you would have the following objects:

ColorListWindow is the Controller object for mediating between the following View objects: ScrollingView is a compound view object that implements a View object that can scroll its contents. It consists of a scrollbar and associated View object and is provided by the framework. TextView is a view that displays a string and is provided by the framework. ColorView is a view that displays a rectangle of color. ButtonView is a view that implements a button and is provided by the framework.

ColorEditDialog is the Controller object for mediating between the following View objects: ButtonView is the same button view as above. ColorEditView is a compound View object that implements a color editor. TextEditView is a view that allows the user to edit a string and is provided by the framework.

The data model consists of the objects String, Color, NamedColor, and ColorList. String is the object that represents a string in the framework. Color is the object that represents a color and is provided by the framework. NamedColor is the object that glues a Color object to a String object, and represents the fundamental unit of information used by the program. ColorList is a Collection of NamedColor objects.

ColorDocument is the Facade. It holds a pointer to the ColorList. It has calls that return the number of colors (passed through to ColorList), the Color or name of any color given its index. Also, it has calls to change a NamedColor, to add a new NamedColor, or to delete a NamedColor. Most of these functions are only one or two lines. It also has a function called EditColor that creates a ColorEditDialog for a given color.

Lets look at what happens when the user edits a color. First, the user double clicks on the fifth color in the list, and selects "Change". The ColorListWindow translates this action into the high-level action, EditColor(5). The ColorListWindow is now done.

The ColorDocument receives the action "EditColor(5)". It makes a new ColorEditDialog and passes it "5" in the constructor. The ColorEditDialog creates the necessary controls. It asks the ColorDocument the name and color of the NamedColor numbered 5. It passes that data along to the ColorEditView and TextEditView objects. The ColorDocument is now done until the user hits "OK" or "Cancel".

When the user clicks "OK", the ColorEditDialog retrieves the input data from its views, and destroys the window and its views. It then pass the high-level action "SetNamedColor" to ColorDocument with the right values.

Program Listing

 

Known Uses

Examples of the pattern found in real systems. We include at least two examples from different domains.

Related Patterns

What design patterns are closely related to this one? What are the important differences? With which other patterns should this one be used?

 


©1997 Twin Forces, Inc. All rights reserved.
1300 S. Milton Rd, Suite 206, Flagstaff, AZ. (520) 779-4227, tf@twinforces.com
Comments to pierce@twinforces.com