Treehouse

The World Beyond MVC

By on  

This post is a written version of a talk given by Garann Means at LXJS and NYCjs. It has been formatted to fit your screen.

There's no shortage of JavaScript MVC (Model-View-Controller) architectures out there. The best-known is Backbone, but there are others: Spine, Agility, Knockback, etc. And in addition to the range of MVC frameworks, there are MV-whatever variants. This stuff, anecdotally, is pretty popular. As of this writing, Backbone is the 7th most watched repo on GitHub. Developers love MVC.

What makes MVC so appealing, especially for JavaScript where it's still primarily used, on the client? If you're new to application architectures, it's definitely very accessible - the model is data, the view is.. the view, and the controller makes them do stuff. Easy! If you started coding on the server-side, MVC is probably already familiar. Most Object-Oriented Programming embraces the pattern and you can find very popular MVC frameworks for Java, .NET, Python, PHP, etc. The pattern itself actually predates and was first implemented in Smalltalk, after being invented by Trygve Reenskaug in the late 70s, so its relationship with OOP has been there from the beginning. Given the unquestioned supremacy of OOP until fairly recently, it's unsurprising that MVC makes immediate sense to many of us.

JavaScript, however, is not exactly OOP. We can do OOP with it, but the two hardly go hand-in-hand. Therefore, the appropriateness of MVC varies by use case. For data entry, content management systems, and situations where we can pick out clear and obvious "models", it tends to work very nicely. But where the state of an application is more amorphous and not always tracked in the same place, in applications with lots of user interaction before any data actually changes, and in apps with very complex widgets or complex, it's less clear that it's the right choice. And if your site is JS-heavy but still static, obviously, forget it. There's no benefit in doing all that setup on a page that's going to reload and lose it all.

The issue we run into when talking about MVC, or any other architectural pattern, is that, as web developers, these things were not created for us. We can trace the most common patterns back to Design Patterns (aka the Gang of Four book), which was published in 1995. The dawn of our field, literally. These patterns were for programmers building programs primarily for their own use, and certainly not for programmers whose work was easily revealed by going up to the menu and clicking View Source. While those patterns all made their way in some form to the back-end, that canon predates JavaScript completely.

MVC, though, was one of the few ancient methods that made immediate sense. Because it has a clear place for the UI to exist, it's easily applied to the front-end (although, again, that application is not canon). Because any pattern we want to use has to be fudged a bit to get it to fit our context, MVC is a great place to start. But it's not the only option we have.

It seems fair to call Event-Driven Architectures the second most obvious pattern. We use event-driven patterns all over the place in JS, and even in combination with MV* patterns. They work well where we need a lot of messaging, and have less need for clear-cut, classical "objects". For the objects we do have, getters and setters (and soon, Object.observe()) can be used as publishers and subscribers, decoupling events, the core of the application, from the things they affect. The value, though, is that these decoupled events don't need to affect only objects, but can also affect the DOM, or server interactions, or other events, and none of that needs to be packaged up in a Model-View-Controller triad if it doesn't make sense as one.

The Naked Objects pattern bears closest relation to MV*, and it would not be unfair to call it a variant of Presentation-Abstraction-Control (a more distant relative). This one's good for big meaty widgets that need to contain and render their own data, and whose visual representation maps directly to the data they contain. It bears similarity to the drag-and-drop IDEs we used to use to build desktop applications, but without the drag-and-drop bit. Rebecca Murphey used a similar pattern in building the Mulberry mobile app framework, which is a perfect use case because Naked Objects is a great way of organizing a composable framework whose implementations will be better served by a different pattern.

The third pattern I think deserves more examination is Pipelines. This should be familiar to jQuery developers or anyone who deals with a lot of callbacks. Pipelines chain operations together to affect a shared state, which might be a visual representation or just a set of data (or both!). The interesting thing to me is that we can use this pattern both synchronously and asynchronously, for example applying global functions to initialize, render, and wire-up a page, then use instance-specific functions to wait for user interaction, validate it, attempt to save it, and render again, all the while modifying the state of an abstraction of that page. Anything with a state can have a corresponding state diagram in code, with the ability to modify the path it takes depending on the result of each step.

With all of these, as with MVC or any other pattern, you have to consider how and where you want your application tightly or loosely coupled, and whether you need a centralized snapshot of the application, or it's better stored in the components it affects. Things like Naked Objects would be overkill if even your most complex controls are only used once. Things like EDA would be pointless if most of your code is setup and initialization code. And if your site is static, whatever introduces the least framework code while still helping you establish clear conventions would be preferable.

At the end of the day, you should still use Backbone rather than not use anything. However, if you find yourself with an application that fits more easily into some other pattern, you shouldn't be afraid to use it. Sadly, for most of these patterns (and the myriad I haven't even mentioned), you're going to have a hard time finding anything as robust and accessible as Backbone. So, more importantly, if you're sitting down to write a new JS application framework, you'd do all of us a service by exploring an alternative to MVC, so picking the right tool for the job won't be a matter of choosing from a selection of nice hammers with different brandnames to tighten screws. Whatever you choose, and whatever the application, though, remember that all implementations decay and it's just as important to leave the opportunity to improve architecture as it is to leave ways to improve the code itself.

Garann Means

About Garann Means

If you liked this, you can read the rest of my nonsense on my blog, totes profesh (spoiler: it isn't), or check out my micro-blather on twitter.

ydkjs-4.png

Recent Features

  • LightFace:  Facebook Lightbox for MooTools

    One of the web components I've always loved has been Facebook's modal dialog.  This "lightbox" isn't like others:  no dark overlay, no obnoxious animating to size, and it doesn't try to do "too much."  With Facebook's dialog in mind, I've created LightFace:  a Facebook lightbox...

  • Responsive and Infinitely Scalable JS Animations

    Back in late 2012 it was not easy to find open source projects using requestAnimationFrame() – this is the hook that allows Javascript code to synchronize with a web browser's native paint loop. Animations using this method can run at 60 fps and deliver fantastic...

Incredible Demos

Discussion

  1. Javier

    Spaghetti article.. I began to feel bored in the second paragraph.. :S

  2. @Javier: I don’t agree.

    It’s a pretty clear article about the state of JavaScript concerning patterns for front frameworks.

  3. Ivan

    Hi, Garann. Thank you for finding time to write this post.

  4. jeremy

    Can’t view this article on a nexus one. Can’t even see what I’m writing here.

    Looks like the article might be interesting but it refuses to zoom and the “older” and “newer” bars on the side s block most of the text :(

    Please update your site to work no matter what browser is used.

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!