JavaScript MVC
Issue № 290

JavaScript MVC

Once a bit player, JavaScript increasingly takes center stage. Its footprint—the space it takes up on our servers and in our development schedules—continues to grow. So how can we make our JavaScript more reusable and easier to maintain? Perhaps MVC will offer some clues.

Article Continues Below

While MVC is a familiar term to those in back-end application development—using frameworks such as Struts, Ruby on Rails, and CakePHP—MVC’s origin in user interface development lends itself to structuring client-side applications. Let’s examine what MVC is, see how we can use it to rework an example project, and consider some existing MVC frameworks.

What is MVC?#section2

The acronym has been mentioned six times already, and if you haven’t heard it before, you’re probably champing at the bit to find out what it stands for. MVC stands for Model-View-Controller. It’s a design pattern that breaks an application into three parts: the data (Model), the presentation of that data to the user (View), and the actions taken on any user interaction (Controller).

Back in 1978 at Xeroc PARC, Trygve Reenskau recalled the origin of the MVC concept (PDF):

There are four roles in this user interaction paradigm. The human User has a mental model of the information he is currently working with. The object playing the Model role is the computer’s internal and invisible representation of this information. The computer presents different aspects of the information through objects playing the View role, several Views of the same model objects can be visible on the computer screen simultaneously. Objects playing the Controller role translate User commands into suitable messages for the View or Model objects as needed.

In other words, a user does something. That “something” is passed to a Controller that controls what should happen next. Often, the Controller requests data from the Model and then gives it to the View, which presents it to the user. But what does this separation mean for a website or web application?

Foundations#section3

The static document is the foundation of a web page. Each page we’re served represents the state of information on the server at that moment. But, we don’t just get raw data, we get an HTML page that the browser renders in all its CSS-defined beauty.

Years ago, if we wanted to modify that data, the server had to present a page with inputs and textareas to make changes. We then pushed those changes back to the server and waited until it told us that everything was okay. Requesting an entirely new page each time we wanted to make changes quickly became tedious for users—even moreso when they made a mistake and had to re-enter their changes.

The knight in shining armor#section4

Since those early, dark days of the web, JavaScript—with Ajax emblazoned on its shield—has come to the rescue. It allows us to update page elements and send user requests back to the server. Most importantly, it allows our pages to reflect user requests without having to wait for the server.

Now, at this stage of JavaScript and Ajax development and adoption, we need to consider separating our code’s components—MVC-style. Such separation may not be necessary in every situation—in some cases, it may even make things needlessly verbose. As our applications get more complex and require JavaScript interactions across multiple parts of our sites, however, separating JavaScript into Model, View, and Controller parts can produce more modular, reusable code.

Structuring our code#section5

JavaScript is dumb. It doesn’t understand what the HTML document is trying to tell users, or what users really want to accomplish using a page. We, as developers, have to tell our JavaScript what user input means.

Consider the following example. If we need to validate form data, we can set up an event handler. On submission, the event handler’s function loops through a predetermined list of fields and determines how to present any errors it finds.

Tell me if this doesn’t look familiar:

function validateForm(){
   var errorMessage = 'The following errors were found:
'; if (document.getElementById('email').value.length == 0) { errorMessage += 'You must supply an email address
'; } document.getElementById('message').innerHTML = errorMessage; }

This approach works, but it isn’t very flexible. What if we want to add fields or validate a different form on another page? We would have to duplicate most of this functionality for each new field we add.

Toward modularity#section6

The first step toward modularity and separation is to embed extra semantics into the form. Is the field in question a required field? Should it contain an e-mail address? If so, we might use something like this:

<input type="text" class="required email">

Our JavaScript will loop through all the form fields, pull the attributes out of the class, and act on them from there. (The class attribute serves a dual purpose here, because it can also be used as a hook for CSS. How convenient!)

The JavaScript reads the metadata—that is, the information that describes the data—and acts on the data based on those rules. But at this point, the data and metadata are still tightly intertwined with the structure and semantics of the markup. Additionally, this method is limited. Conditional logic is hard to embed within HTML constructs. For instance, we can’t say that a field is required only if another field is completed (well, we can, but it’s usually quite awkward).

<input type="checkbox" name="other"> Other
<textarea class="dependson-other"></textarea>

In the preceding example, the dependson prefix indicates that the textarea depends on the presence of another field—in this case, on other. To avoid this awkward approach, let’s look at defining this business logic in JavaScript.

Using JavaScript to describe things#section7

While we can embed some semantics and metadata into HTML, we ultimately need to get that information into our JavaScript layer. Describing data within JavaScript can be quite handy.

Here’s an example:

var fields = {
   'other': { 
       required:true 
       },
   'additional: {
       'required': {
           'other':{checked:true},
           'total':{between:[1,5]}
           },
       'only-show-if': {
           'other': {checked:true}
           }
       }
};

In this example, the additional field has several dependencies. Each of those dependencies can be described and can have various layers of information defined within them. In this case, the additional field requires two fields to meet conditions. And the additional field should only show if the user has checked the other checkbox.

At this point, JavaScript is being used to define the fields and business logic behind how validation should occur. At one level, we’ve isolated some of the data model into its own object, but the validation still expects the data to be available in a specific variable. It also expects a field on the page that shows a summary view of errors.

Although we’ve achieved a bit of separation, the validation process still has too many dependencies: Data validation and the presentation of validation errors is still tightly coupled. The validation function still ensures that the event gets captured and that the form doesn’t submit until everything has been entered correctly.

Let’s consider how we might structure the code using the MVC pattern, and then return to our validation example.

The Model#section8

Since the MVC pattern has three components, we should try to separate our application into at least three main objects.

Separating the Model into its own object will be easy—as we saw in the earlier validation example, this tends to happen quite naturally.

Let’s look at another example. If we had a calendar of events, the event data would be stored in its own object. Methods added to the object abstract the process of interacting directly with the data. These methods are often called CRUD tasks, for create, read, update, and delete.

var Events = {
  get: function (id) {
    return this.data[id];
  },
  del: function (id) {
    delete this.data[id];
    AjaxRequest.send('/events/delete/' + id);
  },
  data:{
   '112': { 'name': 'Party time!', 'date': '2009-10-31' },
   '113': { 'name': 'Pressies!', 'date': '2009-12-25' }
  }
  metadata: {
    'name': { 'type':'text', 'maxlength':20 },
    'date': { 'type':'date', 'between':['2008-01-01','2009-01-01'] }
  }
}

We also need a way to describe the data, so we’ll add a property that describes the fields an item might have, including any constraints.

The CRUD tasks also save state changes to the server. In this example, the delete function removes the entry from its locally stored data and then sends a request to the server to instruct it to delete the item.

When storing data, use a key—it’s the most efficient way to retrieve the data from the object. This is normally the database’s primary key. (The last example uses a numeric id.) For an event calendar, storing values separately for each month may be more practical. It saves having to loop through all the events trying to find the ones that need to be rendered to the page. Of course, you should find the approach that works best for you.

The View#section9

In the MVC pattern, the View accepts data and determines how to display it. The View may use the existing HTML, it may request a new block of HTML from the server, or it may build new HTML using the DOM. It then combines the provided data with the View and displays it to the user. It’s important to note that the View doesn’t care how to get the data or where the data comes from. It takes the data it gets.

View.EventsDialog = function(CalendarEvent) {
   var html = '<div><h2>{name}</h2>' +
              '<div class="date">{date}</div></div>';
   html = html.replace(/{[^}]*}/g, function(key){
        return CalendarEvent[key.slice(1,-1)] || '';
        });
   var el = document.getElementById('eventshell');
   el.innerHTML = html;
}var Events.data = {
   '112': { 'name': 'Party time!', 'date': '2009-10-31' },
   '113': { 'name': 'Pressies!', 'date': '2009-12-25' }
  }View.EventsDialog(Events.data['112']); // edits item 112

Stepping through the preceding example, we have three parts: the EventsDialog function that expects a JSON object with name and date properties, the Events data property that stores calendar events, and the call that sends a specific event to the events dialog.

The Events Dialog View can then be extended to include additional methods that enable interaction. In the following example, the Events Dialog is given open and close methods. By doing this, we make the View self-aware and also provide points of contact that will allow a Controller to manage the View without needing to know the inner details of the object.

View.EventsDialog = function(CalendarEvent){ ... }
View.EventsDialog.prototype.open = function(){
   document.getElementById('eventshell').style.display = 'block';
}
View.EventsDialog.prototype.close = function(){ 
   document.getElementById('eventshell').style.display = 'none';
}var dialog = new View.EventsDialog(eventObject);
dialog.open();
dialog.close(); 

Generalizing Views#section10

Making Views aware of the data model and data retrieval method is an easy trap to fall into. Separating those functions, however, allows us to reuse the dialog for other things. In this example, if we separate the event data and the dialog, we can generalize the dialog to view or edit any data model, not just events.

View.Dialog = function(data) {
   var html = '<h2>' + data.name + '</h2>';
   delete data.name;
   for(var key in data) {
      html += '<div>' + data[key] + '</div>';
   }
   var el = document.getElementById('eventshell');
   el.innerHTML = html;
}

We now have a generic way to view items for any object—not just events. On the next project that needs dialogs, we’ll drop this code in and be done.

Many JavaScript frameworks are designed with this data agnosticism already in place. YUI controls, jQuery UI widgets, ExtJS, and Dojo Dijit are built from the ground up with generalization in mind. As a result, it’s easy to augment applications with existing controls.

Handling View methods#section11

As a general rule, a View shouldn’t run its own methods. For example, a dialog shouldn’t open or close itself. Leave this to the Controller.

If a user clicks on a Save button within a dialog, that event is passed to a Controller action. The action can then decide what the View should do. Maybe it closes the dialog. Or maybe it tells the View to display an “in-progress” indicator while the data saves. Once the data is saved, the Ajax completion event fires off another controller action, which tells the View to hide the indicator and close the dialog.

However, there are situations in which Views should handle their own events or run their own methods. For example, a View could have an input range with a slider that allows the user to pick the value. The View handles the logic for that slider interaction and how it displays the resulting value. There’s no need to have a Controller micromanage that interaction.

The Controller#section12

Now, how do we get the data from the Model to the View? That’s where the Controller comes in. A Controller activates after an event occurs. That may be when the page loads or when a user initiates an action. An event handler is assigned to a controller method that will do the user’s bidding.

Controllers.EventsEdit = function(event) {
   /* event is the javascript event, not our calendar event */
   // grab the event target id, which stores the id
   var id = event.target.id.replace(/[^d]/g, '');
   var dialog = new View.Dialog( Events.get(id) );
   dialog.open();
}

This pattern really comes in handy when data is used in various contexts. For example, say we’re editing an event displayed on a calendar. We click the delete button, and now need to get rid of the dialog and the event on the calendar, and then delete the event from the server.

Controller.EventsDelete = function(event) {
   var id = event.target.id.replace(/[^d]/g, '');
   View.Calendar.remove(id);
   Events.del(id);
   dialog.close();
}

Controller actions become simpler and easier to understand. This is key to building a maintainable application.

Break it up#section13

Now we know how to break our code into its constituent parts, let’s revisit the validation example we started with. How can we design it to provide maximum flexibility using the MVC pattern?

Validating our Model#section14

The Model determines whether the data is correct or not using a method. It’s not concerned with how to present the summary view. It just needs to report which fields didn’t make the grade.

Previously, in the validation example, we had a simple variable called fields that stored some metadata about our data model. We can extend that object with a method that can understand and inspect the data given to it. In the following example, we have added a validate method to the object. It can loop through the data given to it and compare that data against the requirements defined within its internal metadata.

var MyModel = {
   validate: function(data) {
      var invalidFields = [];
      for (var i = 0; i < data.length; i++) {
         if (this.metadata[data.key].required && !data.value) {
             invalidFields[invalidFields.length] = {
                field: data.key, 
                message: data.key + ' is required.'
                };
         }
      }
      return invalidFields;
   },
   metadata: {
      'other': {required:true}
   }
}

To validate our data, we provide an array of key/value pairs. The key is the field name and the value is what the user entered into the field.

var data = [
   {'other':false}
];var invalid = MyModel.validate(data);

Our invalid variable now contains a list of any fields that didn’t validate. Now we’ll pass the data to the View to display the errors on the page.

Presenting the invalid fields#section15

In this case, we need to display an error message on the page. This display will be a View, and will expect data to be passed to it from the Controller. The View will use that data to construct the error message that is shown to the user. Because we’ve written it generically, this View can be used in many situations.

(Line wraps marked » —Ed.)

View.Message = function(messageData, type){
    var el = document.getElementById('message');
    el.className = type;
    var message = '<h2>We have something to bring to your »
    attention</h2>' +
         '<ul>';
    for (var i=0; i < messageData.length; i++) {
       message += '<li>' + messageData<i> + '</li>';
    }
    message += '</ul>';
    el.innerHTML = message;
}
View.Message.prototype.show() {
 /* provide a slide-in animation */
}

The type is attached to the DOM element as a CSS class, allowing us to style the message appropriately. Then, the function loops through the message data and inserts it into the page.

Hooking it all together with a Controller#section16

Our Model stores our data and can tell us whether the data validates. We have a View, the error message, that we use to display success or failure and pass in any text to be shown to the user. The last step is to validate the form when the user tries to submit it.

/* use the event binding of your friendly neighbourhood 
   JavaScript library or whatever you like to use 
*/ 
addEvent(document.getElementById('myform'), 'submit', »
MyController.validateForm);

With our event bound to our controller action,  we capture the data, validate it, and present any errors.

MyController.validateForm = function(event){
    var data = [];
    data['other'] = document.getElementById('other').checked;
    var invalidFields = MyModel.validate(data);    if (invalid.length) {
       event.preventDefault();
       // generate the view and show the message
       var message = new View.Message(invalidFields, 'error');
       message.show();
    }
}

The data array contains the field values. The Model validates the data, and returns a list of invalid fields. If any fields are invalid, the form submission is cancelled and the message data is passed to the View. After that, the View displays the message on the page.

We’re done! We’re left with a reusable message View and Model validation methods.

Handling progressive enhancement#section17

In our validation example, the MVC structure works well with progressive enhancement. The JavaScript simply augments the page to help it do its thing. By separating our code, fewer components will need to understand what is happening on the page. This separation can actually make progressive enhancement easier, since there are fewer interventions in the HTML document.

With an MVC structure like this, we might want to load the page and then to do an Ajax request to pull in the initial data from the server to populate the initial view. However, this can create the illusion of a slow interface, since two requests need to be made before the user can interact with the page: the first request to load the page and the second request to load the data into the page.

Instead, render the page normally—with static data. This is your initial state. The data contained within the initial state is also stored as JavaScript at the bottom of the page. Once the page loads, the JavaScript layer of your application is already set to go.

Additional data can even be preloaded, if not initially seen. In a calendar example, the events for the current month are rendered in the HTML, but the JavaScript layer can be made aware of the current, previous, and next month’s data. The additional load time is minimal but the user can then move forward and back without having to request new data from the server.

Frameworks#section18

The JavaScript MVC frameworks that are popping up provide a more structured and powerful approach to MVC development than what I’ve detailed here. Having a deeper understanding of how this pattern can be applied to your work should help, whether you roll your own or use an existing framework.

A few MVC frameworks include:

Whether you need a formal framework in place or not depends on how complex the application is. If it’s a simple application, a framework’s overhead might not be worth it.

Keep in mind that rolling your own MVC framework doesn’t have to be rigid. It can be as flexible as you want it to be.

Finally#section19

Like anything else in development, you’ll have to decide if the trade-off of this kind of separation is worth it. For small applications where you only have a few functions, this type of separation is surely overkill. The larger your application gets, though, the more it benefits from the separating code into Model, View, and Controller.

About the Author

Jonathan Snook

A web designer and developer based in Ottawa, Canada, Jonathan Snook enjoys front-end work and hardcore server-side challenges. He shares tips, tricks, and bookmarks at Snook.ca. Jonathan is currently Lead Developer at Squarespace.

27 Reader Comments

  1. In my experience MVC is a synonym for overflowing complexity. I found it’s more of a Monk thing (Adrian Monk) than a real helper in programming robust code.
    While with a direct hacker approach you need usually one piece of code, with the MVC pattern you need (at least) three. And even if it sounds very well to have logic and representation divided – it’s a self-deception.

    You will never ever achieve that goal because you can never represent something that didn’t pass your logic handlers.
    So each time you implement additional functionality you will need tons of “pattern”-code. Leading to more code, more complexity, more download-time, more interfacing, harder debugging…

    I don’t like it. I like the agile programming of small collaborating components (some of them actually meet the MVC concept…).

  2. Actually, this a very good article as it will introduce a lot of people to a very common programming acronym and concept and, like it or not websites are becoming more and more “programmable”.

    However, the articles does fail to raise the problems of client-side validation – if a user has Javascript disabled or the user is a “bot” then the validation will not occur. You always need server-side validation and trying to do this in Javascript is an invitation to disaster.

    What Javascript does very well is allow you to provide good user feedback in realtime – avoiding the problem of users filling out a whole form, pressing submit, waiting and then being told they’ve made some mistakes. Some of the work can be split between the browser and the server or Javascript can simply pass messages back and forth using AJAX (yuck), JSON (less yuck) and preferably SSE. Future extensions to HTML might allow browsers to implement some of this directly based on the metadata.

    Most web-frameworks now provide transparent generation of this kind of code so you don’t have to worry about it yourself but it’s a very good idea to have some understanding of what’s actually going on.

    @proxiss – loosely coupled components are certainly preferable but I’d rather have developers working with some standard programming model rather than hacking it every which way each time. More time is spent reading code than writing it.

  3. @proxiss: I hoped to temper the article with an understanding that it’s practical in more complex applications and, in my experience, has actually led to less code and greater simplification because of it. With some of the upcoming stuff I’ve been working on at Squarespace, for example, this pattern has come to good use as different models have to represented in different states, including config dialogs, in-document layout, etc. Adding new models to edit is a matter of editing one component, not three. I’ve had other projects, as well, that have come close but would have been easier to develop using a stricter MVC methodology. Instead, there was too much dependence between components, making it harder to work on as the application got more complex.

    @Charlie Clark: The section on Progressive Enhancement was meant to address the issue but admittedly, didn’t specifically mention server-side validation. Yes, it’s always important to perform these tasks on the server-side. “Never trust anything from the client.”

  4. @proxiss – As your program grows in size, you will be forced to consolidate common code fragments, or code maintenance will quickly become unmanageable. The only sane way to do that is to generalize your code so that it’s re-usable, and that is exactly what MVC accomplishes. But if your program is so small that you hardly have any common code fragments, then of course you shouldn’t use MVC.

  5. I’ve seen the term MVC pop up over the past few years, always wondering what’s so great about it. I have yet to find an answer. I’ve worked with a couple of systems that implement a MVC methodology and trying to troubleshoot or debug MVC code ends up taking far longer than doing the same with non-MVC code. One idea behind MVC is that a system should be designed to be able to accommodate a large variety of recurring patterns when in fact, they rarely recur. Maybe I haven’t worked with MVC enough, but from the experience that I have had with it, MVC ends up creating so much obfuscation that it becomes totally unwieldy. The time it takes to develop a robust MVC far outweighs the benefits, as the time required to maintain and debug it will trump any times it saves in writing code that uses the MVC. I agree with virtually all of what proxiss wrote earlier.

    To me the real issue, or problem, lies in the fact that we’re forcing people to create MVC patterns to account for shortcomings in whatever language it is that they’re using. In other words, why should we have to develop such complex structures to account for patterns that have become so commonplace? Validating email? Any language by now that is used on the web should have this built-in. Using JavaScript as an example, why after nearly 15 years of existence does it not inherently do something as simple as email validation? The problem exists in the language itself not keeping pace with demand; therefore we have to come up with workarounds until it does so.

    I consider objects, functions, methods, etc. all ways to reuse code quite easily. I say the problem is that the tools we are using are not updated as often as they should be which forces us to come up with these workarounds. Elegance lies in simplicity. While MVC may have its place, I’m sure we’ll look back at some point and question what were we thinking. JavaScript is popular because it is dead simple to use, not because it can be bent into a framework.

  6. @catchmyfame – What you’re really arguing for is a library to handle all your commonplace patterns, such as jQuery or Dojo. A programming language itself has no place in dealing with ever-changing specifications for things like input validation. Imagine having to update your JavaScript engine every time one of the many RFC specifications change, when you could simply link to an updated library.

    Try implementing a Content Management System sometime, or design a website with hundreds of dynamic pages, and you’ll see where MVC really shines. But if you don’t have the complexity to warrant it, then don’t use MVC. It’s as simple as that.

  7. Geoffrey, I did in fact just recently implement a CMS which uses a MVC and it was a nightmare to troubleshoot. Also, how often do RFC specs change? Not often. I hardly think that something as essential as email validation is too much to ask to have in a language like JavaScript.

  8. I agree with catchmyfame. Why bother with generalization on every single subject. I.e. PHP was encouraged enough to pack the http-post mechanism into the core engine (_POST array) – and PHP has i.e. a simple “mail()” call that does what you expect.
    Seems they are not afraid of RFC changes…

    On the other hand, Geoffrey, you have generalized libraries that may handle every – never needed – use case for you (like javax and javamail), but force you to write tons of code (and xml configurations) for the one simple appliance you need in 99% of all cases.

    I also agree with Geofffrey – choose your tool carefully, and choose a tool that’s not too much generalized.

    We’re wasting too much time with foreseeing things that never eventuate.

  9. I think, the idea is very good, but in most cases the usage of a MVC principle is just an overdose of script (except in large scaled projects).

    I really like the way, code is seperated in its logic functions, but in the case of JavaScript, there are better ways. I mean writing some pieces of generalized code, that give me the amount of flexibility can have nearly the same result, without making the issue that complex. (I aggree – in very large project there may be a point, you can think about the usage of a JSMVC.)

    Thank you for the article. Good work.

  10. John Resig should be mentioned somewhere in the article considering that his work alone likely accounts for 50% of the revolution in JavaScript we’ve been seeing in the last 2 years. I messed with other frameworks and, like everybody else, came to jQuery like, “Oh my god. I can’t believe it”. Without jQuery (and some help from Prototype) JavaScript wouldn’t exist anymore.

  11. I like the idea of creating HTML templates in JS and replacing using regexp. In fact a lot of JS frameworks have this functionality built-in (see String.substitute() in Mootools for example). However you’re still mixing concerns. Much better in these cases – IMO – to keep most of this logic in the controller… of the web server. This keeps your views in HTML for the designers, and you’d just use AJAH to pull the rendered views in to the client. Also helps to avoid duplicating logic in the client/server. In your example JS would validate the form on the server and the server would return the HTML chunk of errors – if any. I think much more useful than MVC for JS is event delegation – a different kind of abstraction that also helps with development and maintenance in the long term.

  12. @rloaderro: HTML generation should be done in the view, whether it’s on the server or client. The controller in an MVC architecture should act as a mediator. I tend to take a couple approaches to HTML generation depending on the project. If there are a variety of ways that the HTML may get generated, such as within a CMS with multiple object types, then rendering on the server is (I find) easier to maintain. However, in apps that have a more singular focus (like a calendar), including an HTML template within the page, such as in a JS-embedded template, works well and usually means less data having to be sent down the pipe.

    As to others who feel this is overkill, it can be. But it also doesn’t have to be. Here’s an example: you’re using jQuery UI to provide sliders for a mortgage calculator. The UI components are your view. The event management is your controller. The question, then, is whether you need a dedicated object for your model. If this was all the page was doing, then not likely; event management and data management would be combined into a single function and that’s okay. If the calculator was part of a larger app such as a budget estimator that needs to save income and expenses to a server, then it makes sense to combine entries into a model that can save values to the server while the event delegation continues to remain simple. How much more complex have I made the application over just the calculator? One object. Is that overkill? I don’t think so.

  13. I’m disappointed by the responses to this post from the Javascript and HTML developers out there. This kind of framework is exactly what JS needs.

    I had the same initial reaction when applying MVC design patterns to Adobe Flex a few years ago. I thought it was introducing a level of verbosity and complexity that not only made development slower, but actually ran slower as well. But, in the end, the goal wasn’t small and fast code. It was manageable code. And in any medium-to-large project, IMO, manageable is many times more important than small-and-fast.

    I’m picking up Ruby on Rails now as well and I’m even more convinced that MVC is the right way to go for front-end web development.

    1. Project Size
    Everyone is correct that you can build a small project without using a framework – just like you can build a bookshelf or fix a broken pipe without going by the book. But just because you can doesn’t mean you should. And as web development professionals we should be advocating the correct way to do the job, not the “good enough” way. That means not only frameworks, but testing and documentation as well.

    If you’re a small web development shop who builds one-off projects for clients, you probably don’t need a framework. Every new project begins from scratch with a few utilities and snippets you find useful. But in my experience I’ve always had to maintain a site or web application over many months and years. And I’ve had to hand that project off to other developers to maintain even longer than that. If you’re in that line of work, you need to do things right, even if the project initially seems small, because things always change.

    In fact, I wouldn’t even want to work with a small shop that didn’t use some kind of framework, even if it was just homebrew, because that would not only demonstrate a lack of professionalism in their craft, but also a sense that they’re not learning from their experience to build future projects more efficiently.

    2. “Overflowing complexity”
    I think it’s a common mistake for people to confuse verbosity with complexity. MVC is actually a lot simpler than most of the homegrown complexity management systems I’ve seen used with HTML/JS code.

    From a bug report, I can usually tell whether or not the issue lies in the model, view, or controller, and I structure my filesystem in such a way to make it easy to find these files. And everyone else who comes along after me, once they understand the framework, knows where things are supposed to be. (In RoR, it’s called “convention over configuration”)

    In my experience with the “direct hacker approach”, I find myself and others constantly searching through a flat file system, grepping through folders full of .js files looking for the function name or variable that is supposed to be used in some context. And once a bug is found, everyone has their own special way of fixing it, which may solve the immediate bug, but may also have some unwanted side effects which are hard to track down because the relationship between different .js files isn’t explicit, either by naming convention, folder structure, or any of the other things a framework provides.

    But, I’ll admit, there is something annoying about the verbosity of frameworks. You do end up with a lot of template code that doesn’t do much, bloats your code base, and may make your site slower. But I find template code to be more manageable. It’s like carving little expansion slots into your code for that next big feature request. Everyone can agree on where to start, instead of everyone carving out their own slots wherever they like after the feature request is made. Seeing empty slots also makes it easier to see where code may be lacking in things like validation, security, or visual design. Finally, it makes it easy to scope tasks knowing that I don’t have to reinvent any constructs to deal with a feature request. I can just say “I can do that, and I know exactly where to start, and it will take me 1 hour to complete”. That’s valuable if you’re working with an agile team.

    Once you’ve decided that you’ve made the correct architecture decision, verbosity is just something you manage. Most people use code generation to create templates so the only thing they have to write is the customization. But the best approach is abstraction. Assembly was powerful, but it was verbose, so we built languages on top of it to abstract away the verbosity and complexity and just deal with the stuff that matters. Ruby is a excellent case study in this overall. jQuery and prototype do this well for JS. But RJS in Rails, Google Web Toolkit, and Objective-J are the places I’ve been looking to for abstractions that will make MVC design patterns in JS less onerous.

  14. I have to say that I totally agree with eddroid on this one. Following a pattern will lead to more maintainable code in most cases, and the MVC pattern is a well known pattern that many developers know how to use already. You don’t even need a framework for this, as long as you are following the pattern it will help you out a lot.

    We are used to patterns on the server side, and with todays javascript heavy pages, why should we not use one on the client side as well? We all know how easily javascript can get out of hand and become a mess.

    Thanks for a great article.

  15. Jonathan, your article was spot on about having an MVC framework in JavaScript. However, I have to disagree with your decision to put your validation code inside of the Model class instead of the Controller. In your example, the data validation is very simple and only deals with the format of the data, but in many cases data validation includes much more than just format checking, and can include specific business logic and view settings which all belong in the Controller not the Model.

    For example, in your calendar scenario if you accepted date inputs, the validate code would be much more complex. What if you wanted to define business logic that said they could not enter dates on a Sunday? Or what if the View had a checkbox that said “Exclude Holidays”? Or what if you had to make an AJAX call to verify that you didn’t have a meeting on that date? As you can see, validation code is much more than just “format checking” and can get quite complex and may require business rules. Thus instead of putting some validation in the Model and some in the Controller, make it consistent and maintainable and put it all in the Controller.

    My 2 cents.

  16. I think the problem with evangelizing MVC is that it only seems useful in very large, very complex projects. Most of those projects usually contain code that the developer/business would prefer to keep very close to the vest.

    I notice that this article did not even contain a working demo.

    Are there any open-source, non-minified MVC projects available to be used as good examples of MVC method and its usefulness?

  17. Here’s a demo for you: go to applebox.com.au .. hit the browse DVDs button. The app is run as a completely in-browser JavaScript MVC with a controller that manages multiple iframes (as views) and switches the z-Order to display the current ui. This is closer to a typical server-based MVC product where page flow is managed server-side .. EXCEPT the page flow is managed in-browser.

    To my mind the article provides an MVC model that is an example of widget-based data visualisation/control, rather than a more typical page-based visualisation that most web apps exist as today (note this includes Single Page Apps where there’s plenty of widgets and AJAX hijinks .. but which ultimately must face the issue of navigating to another page/SPA once the full capability of a given page/ui is explored).

    The article is great .. but it doesn’t point out the huge advantage of going MVC in the browser .. and that is maintaining state client side, and reducing the server to only needing to serve stateless data. With APPLEBOX, once a UI/View is realised, it maintains it’s state and is shuffled back out of view (in the iframe stack) until it is needed again. When the controller needs to return to it .. it bring it forward and the ui then retrieves whatever data it needs. This means no reloading of extensive js libs and ui widgets per page navigation.

    APPLEBOX is 2 years old now, and the architecture is rock solid. Whilst its great to see frameworks such as sproutcore, JavaScriptMVC and others out there, I’d like to see dojo/jquery/yui/ext to step up into this new area, and provide some application controls (starting with mvc) rather than simplying being widget or javascript foundation toolkits.

  18. I agree with the post above: if the likes of jQuery and Mootools start encouraging people to write mvc javascript, everybody will use it.
    That is the only way!

  19. Jonathan is right, for smaller applications it is not always worth it to type so much code. But now, the (increasingly used) frameworks make it easier to write JavaScript MVC—so I also think this could accelerate the spread of MVC.

  20. MVC designed systems are great, but they have become all the rage in good ways and bad. I’ve come across quite a few projects that have way too much code in creating a proper MVC (for future development maybe?), only to have the system do something that could easily be done with a fraction of the code, yet still be completely usable for other programmers who stumble across the code. So in mu opinion, K.I.S.S., unless you know you’ll be expanding the project to a decent size in the future.

  21. I’m glad you are publishing more technical articles and less fluffy ones. Still not convinced MVC is the way to go for Javascript RIA.

    It would be nice if one could port some an Actionscript framework (PureMVC springs to mind) to Javascript, but I doubt that would be worth it, or even feasible.

  22. Interesting article, I wasn’t aware of people trying to implement MVC into front-end code. I’d guess it’s coming from the .net boys trying to cope with javascritped business logic.

    I’m not sure what you’ve described is actually MVC. You’re mixing templates into the javascript and using AJAX to pull data. Also, there’s that whole issue of application behaviour code supplying business logic to the entire application through things like validation routines. It’s the job of the back-end controller to define relationships not the ‘view’ behaviour code.

    A much better approach would be to add the elements

    and have your behaviour logic read the content of those elements to control client event handling. Let’s look at an example you describe concerning the preloading of a calendar. You load your special event days into the ‘database’ as a table for those months prior and ahead of what is displayed. You might call this client-side database normalisation. Your controller can then read the recieve the next click event, the model can retrieve the special event days and the view fetches and builds the template which is inserted as a widget by the controller.

    For brevity. This is more like what the setup of MVC validation messages, as you’ve described, should look like on the page:

    {varMessageTitle}

      {loop varMessageData as Data}

    • {varData}
    id message classes
    1 Your email address is invalid warning required
    id name requires 1 email_address has_email_checkbox

    In any event I still think that MVC for web application development is a collective madness which we’ll all look back on in ten years time and have a good laugh. MVC doesn’t clearly define ORM as an inherant part of the pattern, which, makes CMS development obtuse at best.

  23. @waffle: doing view rendering on the server is definitely a valid approach. However, the tradeoff for me is how much time/bandwidth do you sacrifice in doing so. If you’re rendering a complete calendar of events for each month, it’s almost pointless to do it via Ajax—especially if there aren’t any events within a particular month. I prefer pulling in just a JSON request because it’s smaller. Storing that information client side then becomes part of the model (essentially, keeping track of state and syncing with the server).

    Are we going to look back to server development 10 years from now and all laugh about having used MVC? With the increasing complexity of client-side apps (not only on the web but also in desktop apps like AIR and Titanium), it seems like a natural choice.

  24. I tend to agree with Eddroid. MVC isn’t new and the fact that it has survived decades for many similar discussions such as this to be taking place today gives everyone something to think about, especially its detractors.

    Even if I’m doing a small dirty project, I still find more merits doing it right. MVC patterns for smaller projects isn’t going to give you that much more overhead in any case. Backtracking your codes a year later won’t make much of a difference in a small project whether its done with MVC or not. But it does make a difference when you are working with a team. Your project may need to spin off to something larger, or open-source, etc from the same code base. Then I’d think your MVC foundation would do you justice.

    I’d rather not be caught realizing this a year later into development.

    Essentially, I look at the quest of applying MVC patterns for javascript/ajax more than just for goodness’ sake, but a case of developing healthy coding habits, seeing and thinking right. A cause with more benefits than not, most certainly.

    On the server side, I like codeigniter for its loosely coupled design which gives developers more flexibility. I could stray from convention where necessary. Likewise, I think in browser MVC, we should also find that balance.

    It isn’t too difficult to consume a fish without swallowing its bones. Great article Jonathan!

  25. There are other patterns to separate concerns. MVP, Humble Dialog, and even Presenter First.

    For me the separation helps because I test first then write my code. When I need to refactor, adding new behavior to my app, separation is what I need.

    Use of JavaScript is to give a more responsive experience the user. An example of this would be if you wanted to display some markers on a google map. The addresses are stored on your server. The addresses have no geocoding. User requests data from server. Client requests geocoding from a geocoding service. Display markers on google map. The other way would be my server having to request geocoding. then sending data to client.

    OBTW why not have the address be behind somebody else’s API. So now all my server has to serve up is HTM, JavaScript, and CSS. Let the client pay for the bandwidth.

    Now my business costs go way down. My programmers (me) don’t have to invest in backend software maintenance costs. Learning PHP, Python, Ruby, DOTNET, only so far as needing to know how to get a server up and running.

    Hmmm…. wonder if you could write a mongrel-like server in JavaScript. Just embed SpiderMonkey.

  26. MVC was first put in practice in the development of the Smalltalk GUI. The latest work by the same team is the Squeak language and environment. Squeak has a GUI toolkit named Morphic which is not strictly MVC because after 30 years of trying they concluded it is just not worthwhile to separate the view from the controller, as the two are naturally very interdepedent. So for GUIs and client-side web programming the way to go is M/VC: split the model from the rest, and be happy.

Got something to say?

We have turned off comments, but you can see what folks had to say before we did so.

More from ALA

I am a creative.

A List Apart founder and web design OG Zeldman ponders the moments of inspiration, the hours of plodding, and the ultimate mystery at the heart of a creative career.
Career