Cover by Alex MacCaw

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

O'Reilly logo

What Is MVC?

MVC is a design pattern that breaks an application into three parts: the data (Model), the presentation layer (View), and the user interaction layer (Controller). In other words, the event flow goes like this:

  1. The user interacts with the application.

  2. The controller’s event handlers trigger.

  3. The controller requests data from the model, giving it to the view.

  4. The view presents the data to the user.

Or, to give a real example, Figure 1-1 shows how sending a new chat message would work with Holla.

Holla

Figure 1-1. Sending a new chat message from Holla

  1. The user submits a new chat message.

  2. The controller’s event handlers trigger.

  3. The controller creates a new Chat Model record.

  4. The controller then updates the view.

  5. The user sees his new chat message in chat log.

The MVC architectural pattern can even be implemented without libraries or frameworks. The key is to divide up the responsibilities of the MVC components into clearly defined sections of code, keeping them decoupled. This allows for independent development, testing, and maintenance of each component.

Let’s explore the components of MVC in detail.

The Model

The model is where all the application’s data objects are stored. For example, we might have a User Model that contains a list of users, their attributes, and any logic associated specifically with that model.

A model doesn’t know anything about views or controllers. The only thing a model should contain is data and the logic associated directly with that data. Any event handling code, view templates, or logic not specific to that model should be kept well clear of it. You know an application’s MVC architecture is violated when you start seeing view code in the models. Models should be completely decoupled from the rest of your application.

When controllers fetch data from servers or create new records, they wrap them in model instances. This means that our data is object oriented, and any functions or logic defined on the model can be called directly on the data.

So, rather than this:

var user = users["foo"];
destroyUser(user);

We can do something like this:

var user = User.find("foo");
user.destroy();

The first example is not namespaced or object oriented. If we have another destroyUser() function defined in our application, the two will conflict. Global variables and functions should always be kept to an absolute minimum. In the second example, the destroy() function is namespaced behind User instances, as are all the stored records. This is ideal, since we’re keeping global variables to a minimum, exposing fewer areas to potential conflicts. The code is cleaner and can take advantage of inheritance so functions like destroy() don’t have be defined separately on every model.

Models are explored in much more depth in Chapter 3, which covers topics such as loading in data from servers and creating object-relational mappers (ORMs).

The View

The view layer is what’s presented to the user and is what she interacts with. In a JavaScript application, the view would be made up mostly of HTML, CSS, and JavaScript templates. Apart from simple conditional statements in templates, the views shouldn’t contain any logic.

In fact, like models, views should also be decoupled from the rest of the application. Views shouldn’t know anything about controllers and models—they should be independent. Mixing up views with logic is one of the surest paths to disaster.

That isn’t to say MVC doesn’t allow for presentational logic—as long as it’s not defined inside views. Presentational logic resides in what are called helpers: scripts solely for small utility functions related to the view.

The example below, which includes logic inside views, is something you shouldn’t do:

// template.html
<div>
  <script>
    function formatDate(date) {
      /* ... */
    };
  </script>
  ${ formatDate(this.date) }
</div>

In the code above, we’re inserting the formatDate() function directly into the view, which violates MVC, resulting in an unmaintainable mess of tag soup. By separating out presentational logic into helpers, as with the example below, we’re avoiding that problem and keeping our application’s structure MVC-compliant.

// helper.js
var helper = {};
helper.formatDate = function(){ /* ... */ };

// template.html
<div>
  ${ helper.formatDate(this.date) }
</div>

In addition, all presentational logic is namespaced under the helper variable, preventing conflicts and keeping the code clean and extendable.

Don’t worry too much about specifics regarding views and templates—we cover them extensively in Chapter 5. The aim of this section is to familiarize you with how views relate to the MVC architectural pattern.

The Controller

Controllers are the glue between models and views. Controllers receive events and input from views, process them (perhaps involving models), and update the views accordingly. The controller will add event listeners to views when the page loads, such as those detecting when forms are submitted or buttons are clicked. Then, when the user interacts with your application, the events trigger actions inside the controllers.

You don’t need any special libraries or frameworks to implement controllers; here’s an example using plain old jQuery:

var Controller = {};

// Use a anonymous function to enscapulate scope
(Controller.users = function($){

  var nameClick = function(){
    /* ... */
  };

  // Attach event listeners on page load
  $(function(){
    $("#view .name").click(nameClick);
  });

})(jQuery);

We’re creating a users Controller that is namespaced under the Controller variable. Then, we’re using an anonymous function to encapsulate scope, preventing variable pollution of the global scope. When the page loads, we’re adding a click event listener to a view element.

As you can see, controllers don’t require a library or framework. However, to comply with MVC’s architectural requirements, they must be separated from Models and Views. Controllers and states are covered in more detail in Chapter 4.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required