Model View Controller: History, theory and usage

MVC logo

Recently I have been fascinated with how to structure web-applications, especially web-applications that use a lot of JavaScript. To learn more I have done some research into one of the most widely used design-patterns: Model-View-Controller (MVC). This blog post explores how MVC is used in Smalltalk, Ruby On Rails, .Net and Cocoa. I also implement Smalltalk's and Cocoa's MVC patterns using jQuery and CoffeeScript.

The history of MVC

MVC is really old and was first described in 1979 by Trygve Reenskaug, then working on Smalltalk at Xerox PARC. Being over 30 years ago does not mean it's dead, far from it... Today MVC is used in most modern web and GUI frameworks, including:

  • Ruby On Rails: A popular Ruby web-framework
  • Apple Cocoa: Apple's framework for developing Mac OS and iOS applications
  • ASP.Net Framework: Microsoft's web-framework for implementing web applications
  • Apache Struts: A popular Java web-framework
  • ... And many many more languages and frameworks

The main objectives of MVC

Model-View-Controller as the name applies considers three roles:

  • Model: manages the behavior and data of the application domain
  • View: represents the display of the model in the UI
  • Controller: takes user input, manipulates the model and causes the view to update

There isn't a standard definition of the MVC pattern and many frameworks use a slightly different version. This said there is a core idea of what MVC tries to achieve:

  • Separating the presentation from the model:
    Enables implementation of different UIs and better testability
  • Separating the controller from the view:
    Most useful with web interfaces and not commonly used in GUI frameworks

In most implementations the separation between the model and the view is most important. Martin Fowler's notes following interesting thing about Smalltalk's original MVC pattern [in his book Patterns of Enterprise Application Architecture]:

The irony is that almost every version of Smalltalk didn't actually make a view/controller separation.

To make things more clear let's take a look at how the MVC pattern is implemented across different programming languages and frameworks.

Smalltalk MVC

The first implementation of the MVC pattern was found in Smalltalk-80 - a programming language released in 1980. Smalltalk is a pure object oriented programming language that's very interactive and MVC was one of the core features of the implementation.

The main objective of using MVC in Smalltalk was separating the application logic from the user interface - - enabling reuse of the model to implement several user interfaces:

Smalltalk separating the application logic from the user interface

Smalltalk's dependency between model, view and controller:

Smalltalk MVC dependency structure

Things to note about Smalltalk's dependency structure:

  • The model does not depend on the view or the controller
  • Observer pattern was used to update views when models changed
  • Smalltalk-80 MVC did not make a view/controller separation

Ruby On Rails MVC

Ruby on Rails is a very popular Ruby web-framework that uses MVC.

The client-server environment of web-applications makes things more complicated than the original environment that MVC was invented in. This is mostly because the view can't easily observe the model (at least not without Ajax or Comet communication).

Overview of Rails MVC:

Ruby On Rails MVC overview

Things to note about Rails MVC:

  • It's a lot different from the original Smalltalk MVC pattern since Rails operates in a very different environment than a typical Smalltalk application
  • The model does not depend on the view or the controller
  • There isn't a direct dependency between the view and the model. The controller collects all the needed data from the model and passes it to the view
  • Given that Rails operates in a client-server environment the view does not update automatically when the model changes
  • Most of today's MVC web-frameworks use a pattern very similar to the one Rails uses

Cocoa MVC

Apple's Cocoa framework is used to create Mac OS X and iOS applications. Cocoa uses a lot of design patterns and MVC is one them.

Cocoa's MVC puts a lot importance on the controller and this makes it a lot different than the original Smalltalk MVC. A Cocoa controller acts as a mediator between the view and the model [this is commonly known from the Mediator pattern]:

Cocoa's MVC pattern

The reason to use the mediator pattern is probably because the data flow is cleaner than the traditional MVC found in Smalltalk, which looks like this:

Cocoa's Traditional MVC pattern

The above graphics are from Apple's Cocoa Design Patterns. I recommend reading these documents if you want to know more about Cocoa's design.

ASP.Net MVC framework

ASP.Net started off using a pattern called Model-View-Presenter, but this pattern got "replaced" when Microsoft introduced ASP.Net MVC, which implements a similar MVC pattern used in Rails or Django.

CodeGuru has a good blog post on MVP vs. MVC and in it there's a good graphic explaining the difference between these two patterns:

ASP.Net MVP vs. MVC

Exploring MVC with jQuery and CoffeeScript

I have done some experiments with sample implementation of MVC patterns using jQuery and CoffeeScript.

First do note that the idea of using MVC in JavaScript isn't new and there are already some JavaScript frameworks that use this approach:

In following implementations I will only implement Smalltalk's and Cocoa's MVC patterns. Rails or ASP.Net MVC patterns are done in a backend environment and I don't think it makes sense to use them for client-side code.

What example to implement?

To make things as simple as possible we want to implement a counter button that increases its value when clicked. A simple HTML implementation could look like this:

<button onclick="this.innerHTML = parseInt(this.innerHTML) + 1">1</button>

We are interested to see how the above code could be structured using a MVC pattern.

Following examples will use a lot more code than a simple HTML implementation and this is fully expected. The reason to use MVC isn't to use fewer lines of code, but to structure code so it's easier to reuse, maintain and test.

Implementing Smalltalk's MVC

Smalltalk's MVC did not make a separation between the view and the controller and it used the observer pattern to update the view. Following this philosophy the button example could look like this:

class ModelCounter

    constructor: ->
        @observers = []
        @value = 1

    increaseValue: (delta) =>
        @value += delta
        @notifyObservers()

    notifyObservers: =>
        obj.notify(this) for obj in @observers

    registerObserver: (observer) =>
        @observers.push(observer)

class ViewCounterButton

    constructor: (opts) ->
        @model_counter = opts.model_counter
        @button_class = opts.button_class or 'button_counter'
        @model_counter.registerObserver(this)

    render: =>
        elm = $("<button class=\"#{@button_class}\">
                #{@model_counter.value}</button>")
        elm.click =>
            @model_counter.increaseValue(1)
        return elm

    notify: =>
        $("button.#{@button_class}").replaceWith(=> @render())

The above code could be initialized with following code:

$(document).ready( ->
    model_counter = new ModelCounter()
    view_counter = new ViewCounterButton('model_counter': model_counter)
    $('body').append(view_counter.render(),
                     view_counter.render())
)

Implementing Cocoa's MVC

Like noted before Cocoa's MVC pattern uses the Mediator pattern so the controller acts as a mediator between the view and the model. Following this philosophy our button example could look like this:

class ModelCounter

    constructor: (@value=1) ->

    increaseValue: (delta) =>
        @value += delta

class ControllerCounter

    constructor: (opts) ->
        @model_counter = opts.model_counter
        @observers = []

    getValue: => @model_counter.value

    increaseValue: (delta) =>
        @model_counter.increaseValue(delta)
        @notifyObservers()

    notifyObservers: =>
        obj.notify(this) for obj in @observers

    registerObserver: (observer) =>
        @observers.push(observer)

class ViewCounterButton

    constructor: (opts) ->
        @controller_counter = opts.controller_counter
        @button_class = opts.button_class or 'button_counter'
        @controller_counter.registerObserver(this)

    render: =>
        elm = $("<button class=\"#{@button_class}\">
                #{@controller_counter.getValue()}</button>")
        elm.click =>
            @controller_counter.increaseValue(1)
        return elm

    notify: =>
        $("button.#{@button_class}").replaceWith(=> @render())

The above code could be initialized with following code:

$(document).ready( ->
    model_counter = new ModelCounter()
    controller_counter = new ControllerCounter('model_counter': model_counter)
    view_counter = new ViewCounterButton('controller_counter': controller_counter)
    $('body').append(view_counter.render(),
                     view_counter.render())
)

Conclusion and further reading

Model-View-Controller has lasted over 30 years and is used in most modern GUI-frameworks and web-frameworks. It has proven its worth and it's here to stay. I would expect it being used more and more, especially for next-generation JavaScript frameworks.

As my examples show, MVC does produce more code than hack-and-slash HTML code and it's not that suitable if you code small web-applications. But it should be very suitable if you want to code large web-applications where maintainability, reuseability and testability are important.

I suggest reading following books and posts if you want to dig deeper into the MVC pattern:

Book references

Article references

22. Mar 2011 Code · Code improvement · Design · JavaScript
© Amir Salihefendic