Skip to main content

Backbone.js: In the Beginning, There Was JavaScript

Posted by manning_pubs on June 6, 2013 at 11:14 PM PDT



Backbone.js: In the Beginning, There Was JavaScript

by Samuel M. Breed, author of Backbone.js in Action

Backbone is a library for structuring web applications. Since the dawn of the Internet, forward thinking developers have known that it is more than just a means of serving static HTML documents, but rather a platform made for applications. JavaScript has evolved into an ecosystem that's awash with libraries and frameworks for helping you write rich, interactive front-end experiences; a modern web developer has many tools to choose from. The trouble is that there are actually too many choices to make, and it is easy to end up with a messy, unstructured application on your hands. In this article, based on chapter 1 of Backbone.js in Action, author Samuel Breed explains how Backbone helps to solve this problem in a way that is lightweight and flexible. Save 40% on Backbone.js in Action with Promotional Code bbjsjn, only at manning.com.

Even after almost two decades of consistent usage, there's still a lot that JavaScript can't do. There's even more that's not terribly obvious when you set out building applications with it, especially when it comes to assembling an interactive, single page user experience. Backbone gives you generic tools for helping organize and structure front-end applications. By focusing on mechanisms for managing your data and structuring interfaces around a synchronous event system, Backbone provides structure in a world that encourages you to created tangled piles of anonymous callbacks and jQuery selectors.

This article explores the concepts that Backbone uses to build a foundation for applications. In order to really know a person or a discipline or library, you first must know where it came from.

When it was first conceived at Netscape in 1995, JavaScript was meant to give developers a way to interact with web pages in the browser. Its primary programming interface is the Document Object Model (DOM), a standardized set objects, functions and properties that represent the state of the HTML document in the browser. Commonly referred to as the DOM, this set of APIs is what allows JavaScript access to manipulate a page's content and to respond to user interaction. The DOM is a mess for several reasons, and this sentiment inspired libraries like jQuery to simplify how you interact with web pages. But with great power comes great responsibility: many developers have fallen into the trap of tying up the state of their front-end application in the DOM by embedding information in markup, using inline AJAX calls in a procedural fashion or otherwise making a bit of a mess when wiring up interactive, dynamic applications.

For many years, JavaScript was viewed as a toy language that was not well suited for doing much more than creating pop-ups, occasionally validating a form, or making some text animate across the page. When not being conflated with Java, JavaScript took a backseat role until, as if from nowhere, large, mature JavaScript applications began to pop up everywhere. Dynamic, single page applications like Gmail and Google Maps showed that rich user experiences were not only possible to implement in JavaScript, but that those experiences could offer clean and boundary pushing user experiences that made traditional multipageload apps look impossibly clunky by comparison.

Recently, the pace at which JavaScript evolved as a language had increased dramatically. Fueled by competition between browser vendors, JavaScript performance was pushed forward in leaps and bounds, widening the doors of what is considered possible and practical to do in JavaScript. New standards and specifications like HTML5, CSS3, and ECMAScript 5 have led to a new generation of applications that are characterized by fast, well-designed user experiences that have come to define some of the most trafficked sites on the Internet. Simultaneously, the number of libraries, frameworks, and tools for writing JavaScript underwent a similar renaissance. Open source projects like jQuery and Underscore created layers of abstraction on top of the DOM and the “bad parts” of JavaScript to make it as easy as possible for developers to manipulate pages, add animated effects, and respond to user input.

By leveraging the functionality of other frameworks and libraries, the developers at Document Cloud built a compact and potent library for creating and managing JavaScript applications. Appropriately named, Backbone gives your applications just a few structural components—the mainstays that you attach all of the functionality of your app to. Because of its implementation-agnostic nature, Backbone works well in a wide variety of situations, from embedded widgets like Disqus comments, to massive applications like USAToday.com. By seeking to provide structure rather than to make a comprehensive API that covers every edge case of every problem you're likely to encounter, Backbone is uniquely flexible.

Patterns for client-side applications

If you are familiar with an object-oriented programming language, you have likely come across the term Model-View-Controller (MVC) before. The MVC pattern is often found in server-side frameworks like Ruby on Rails or Django, where its used to negotiate the storage, presentation and management of data in a way that's well-isolated and testable. As we'll see in the upcoming pages, Backbone borrows heavily from MVC and it's derivative patterns—but what emerges is something a bit different—the same metaphors are used, but they take on a different meaning when applied in the browser. These patterns are colloquially know as MV* when applied to front-end applications. But before we can dig into that ever-so-important asterisk, we need to talk about MVC and why it even matters in the first place.

Model-View-Controller

In the simplest terms, MVC is used on the server to organize and separate concerns. By keeping Models, Controllers, and Views as distinct interfaces, its easier to add features or making changes to an application over time. The alternative is to create what are known as monolithic applications; apps that have all of their logic for display, persistence and presentation all in one place. As illustrated in figure 1, MVC provides a template for structuring the different concerns of an application: Models represent the domain specific knowledge and data in the application, and are capable of notifying observers of state changes (changes to the underlying data they represent); Views typically represent the UI layer, displaying model data and listening to changes in the model's state; Controllers handle user input and relay any changes that need to happen on the model layer.


Figure 1 A traditional Model-View-Controller relationship

The main problem addressed by MVC is the tendency for monolithic applications to be prone to difficult-to-solve bugs that result from complex logic or tightly coupled classes. Tight coupling is a byproduct of most procedural scripting languages and happens when a single class is dependent on the inner workings or implementation details of another, possibly unrelated class. For instance, the act of making database calls directly from a presentational template is an example of tight coupling; the template is responsible for both outputting an HTML template and communicating with a database or ORM to retrieve the data its presenting. When these monolithic architectures are left unchecked, it becomes difficult to test or isolate different areas of functionality. Structured and maintainable code is important to developer productivity, and helps developers craft software more effectively. MVC patterns address this problem by applying to divide the responsibilities in your application.

Model-View-Presenter

There are a host of similar patterns with similarly named acronyms, the most important and most relevant to Backbone is the Model-View-Presenter pattern (MVP). MVP is a derivative of MVC, but shifts all of the middleman functionality to a Presenter, rather than wiring views and controllers directly to the model. Model-View-Presenter (figure 2) is the closest approximation to the relationships that exists between Backbone Core classes, your server and the DOM.


Figure 2 The Model-View-Presenter pattern

But try to not get hung up on the semantics of MVP vs. MVC vs. MV*—the takeaway is that separating the areas of functionality in your application is the simplest way to avoid monolithic architectures that are hard to grow, scale and change over time. The assumptions you have about your software projects on day 1 tend to be way different on day 30 or day 60, so being flexible is a key trait of a successful developer or piece of software.

MV*, a pattern for real-world applications

In client-side JavaScript applications the need for patterns to help separate functionality is just as much of a reality as it is on the server. If you've ever written an application with a DOM abstraction library like jQuery, you've probably run into the problem of monolithic files, where a lot of disparate functionality is crammed together into a single file. The main goal of separating functionality is to reduce cognitive load, either for a future version of you or other members of your team that might not have been around when the project was setup. In Backbone, the diagram looks a little bit different.

Backbone combines the concept of a View and a Controller, which is similar to the Presenter in MVP, as seen in figure 3. But rather than making this a specific abstraction, Backbone Views are bound to a piece of the DOM and are responsible for updating it. So a Backbone View is really like a Presenter/Controller and a View, but it is still distinctly separate from the DOM itself or the template it uses to format and present its data. This is necessary because in JavaScript there is not a clean separation between the View layer (the HTML/CSS) and the Controller or Presenter layer (the JavaScript that interfaces with DOM APIs)—invariably JavaScript is going to be the primary interface for reading and updating the state of the DOM, so having true isolation between the two layers isn't all that practical. Backbone also introduces the concept of a Router, which is a means of delegating and initiating state changes in the application's URL, either with hash URLs (that take the form /#/posts/123) or with the HTML5 pushState API (which look like normal URLs, but don't cause a page reload when the URL changes.)


Figure 3 MV* in Backbone

Backbone doesn't quite fit MVC, nor does it line up exactly with the MVP pattern; the term that's been coined to describe Backbone (and similarly minded frameworks) is, fittingly, MV*. The asterisk denotes that there's some grey area around what the controller/presenter is responsible for since it's largely up to the interpretation of the developer using Backbone in their app.

Summary

Building modern JavaScript applications is complicated business. A plethora of choices stand between a developers' vision and the actual work of implementing it; choosing between libraries, frameworks, build processes and development tools is just the tip of the iceberg when developing a complex JavaScript application. Backbone helps simplify some of those choices, while still leaving the door open for you to custom tailor your implementation to fit the needs of your project. We've seen how Backbone is composed of distinct components that fit together in a larger pattern and how those patterns help to separate and organize concerns when building different type of applications.


Here are some other Manning titles you might be interested in:

Ext JS in Action, Second Edition

Ext JS in Action, Second Edition
Jesus Garcia and Jacob K. Andresen

Secrets of the JavaScript Ninja

Secrets of the JavaScript Ninja
John Resig and Bear Bibeault

Third-Party JavaScript

Third-Party JavaScript
Ben Vinegar and Anton Kovalyov