Building Backbone Plugins

Eliminate The Boilerplate In Backbone.js Apps

Derick Bailey and Jerome Gravel-Niquet

This book is for sale at http://leanpub.com/building-backbone-plugins

This version was published on 2013-07-30

*   *   *   *   *

This is a Leanpub book. Leanpub empowers authors and publishers with the Lean Publishing process. Lean Publishing is the act of publishing an in-progress ebook using lightweight tools and many iterations to get reader feedback, pivot until you have the right book and build traction once you do.

*   *   *   *   *

© 2013 Muted Solutions, LLC. All Rights Reserved. Backbone.js and the Backbone.js logo are Copyright 2010-2013 Jeremy Ashkenas and DocumentCloud Inc.

Formerly Known As…

I originally titled this book “Prosthetics And Orthotics”, as a play on the idea of adding something on to a backbone… adding artificial limbs or additional things that help make your life more comfortable. I changed the name due to the amount of confusion that name was causing.

If you’re looking for the “Prosthetics and Orthotics” Backbone book, this is the one.

Quotes And Praise For Building Backbone Plugins

“It was the perfect read given that I was using backbone in a a unstructured manner leaving many design paradigms in the dust. The book is a great guide on how to transition from a mediocre backbone web developer to a full-fledged software engineer with backbone under their tool belt.” - Peter Tseng

“im currently sheding tears of joy while reading your book… #AMAZING” - @Lunatikzx

“LOVE IT” - @sheldonj1983

“AWESOME!” - @wbingham

“that [old] cover makes the pins in my knee hurt :D” - @scottpu

A Work In Progress

This book is a work in progress, with many of the chapters complete, additional chapters in rough draft, and one or two chapters planned beyond that. Expect this book to change over time, with edits and additional chapters being added. The amount of demand I am seeing from early adopters will largely determine the schedule that I keep for additional releases, and the eventual price that is charged for the finished product.

Please Provide Feedback

Any and all feedback that I receive on the book is greatly appreciated. Whether it’s positive, negative, grammer and speling (see what I did there? :D), content suggestions or otherwise.

Please feel free to contact me with any feedback that you have. The more feedback I get, the better the book will be.

twitter: @BackbonePlugins

email: backboneplugins@mutedsolutions.com

Please feel free to leave comments on the Leanpub page for this book as well.

Preface

Better, Faster, Cheaper

Building Backbone.js applications without the use of plugins, add-ons and project-specific abstractions is a waste of time and money.

If every feature of every system (in any language or platform) had to be built form the ground up, no one would deliver anything of real value. Instead, we build systems on top of systems - the abstractions, plugins, libraries and frameworks that perform the core functions of the platform and infrastructure we need. But even with the use of existing add-ons and abstractions, the understanding of how to effectively build your own abstractions and re-usable components is a necessary part of software development. JavaScript and Backbone.js applications are no different than any other application or system in this regard. It is our responsibility as developers, technical leads and architects, then, to look for ways to effectively use and create re-usable plugins, add-ons and abstractions.

But while Backbone is no different than any other system in the need for abstractions, it does provide some unique and interesting ways in which we can build our reusable pieces. And having an understanding of how to use Backbone effectively means more than just using the existing components that it comes with, or existing plugins built by other developers. It means understanding how all of the pieces fit together, and how those pieces can be extended and augmented. It means understanding how to pull apart the general needs of a component to create something that can be extended in to a specific scenario. And it means knowing how to recognize and extract the patterns that we create in our own applications, in to re-usable components that may be deliverable as plugins and add-ons in themselves.

This book, then, will show you how to effectively use Backbone.js by building abstractions, add-ons and plugins for your own applications and as open source projects. It will give you the knowledge you need to work with the components that Backbone includes, build complementary objects to be used within JavaScript and Backbone applications, and ultimate save time and money while delivering more features.

What Is Backbone?

Backbone.js is a small library of objects that aim to provide structure to JavaScript applications. It provides a handful of building blocks and tools that help us to build applications with a better architecture, separation of concerns and smaller, focused pieces that all add up to a larger application, including:

Backbone.Model: A set of data, and optionally logic, representing an entity in the application

Backbone.Collection: A group of related models, with standard functions for retrieving models, iterating over the models, etc.

Backbone.View: Views provide a way to encapsulate and organize jQuery or other DOM manipulation library code, and manage, manipulate and respond to the DOM through declarative DOM events, model and collection event bindings, etc.

Backbone.Router: Respond to changes in the application’s URL, providing bookmarkable and navigable URL’s based on tokenized representations of the application state

Backbone.History: Manage the actual browser history, forward and backward buttons, and respond to configured routes. The History object does the actual work that routers define, allowing multiple routers to exist in a single application.

Backbone.Events: Provide an event-driven, or public/subscribe architecture, allowing application components to be decoupled from each other while still allowing communication to happen between them

Backbone.sync: Provides an abstraction for model and collection persistance. The default implementation expects a REST-like API on a server, communicating with JSON over jQuery AJAX calls

For a more complete introduction to Backbone and it’s components, see the following resources:

Addy Osmani’s Backbone Fundamentals

My Intro To Backbone Screencasts

My Additional Resources

Why Are Plugins And Add-ons Neccessary?

In spite of - or perhaps because of - the flexibility, simplicity and power in the components that Backbone provides, it does not provide everything that a developer needs to create a complete application. There are several concerns that many applications have which Backbone does not directly address, or which Backbone provides some support without a direct implementation.

For example, Backbone’s View provides a default render method that does nothing. It takes no parameters and it produces no observable changes as a result of calling it. However, this method is built in to Backbone.View to illustrate the common practice of providing a render method on a view, which will generate the HTML structure that the view is to manage.

On the flip side of that coin, Backbone’s Model and Collection provide no method of handling nested or hierarchical models and collections. It’s up to the developer and the individual project to set the standard for adding this support, when it’s needed.

In both of these cases, there are existing plugins and frameworks that provide solutions for Backbone-based projects. Frameworks such as my own Backbone.Marionette or Tim Branyen’s Backbone.LayoutManager provide a default, but easily changeable, rendering solution for Backbone views - among many other benefits and capabilities. There are a handful of tools that can provide nested and hierarchical models, such as Backbone-Relational, and many other tools, add-ons, plugins and frameworks that provide a tremendous amount of power, flexibility and capabilities on top of what Backbone provides. For a more complete list of the available plugins and frameworks, see the Backbone Wiki.

With these existing add-ons, plugins and frameworks available, there is often enough for an application of any size to be completed. But there are also times when the feature set of a specific add-on, or the implementation of an individual framework, may not play well with the opinions and needs of the development team working on an application. There are also scenarios where an individual application needs a very specialized set of functionality to work properly - one that needs to be repeated several times throughout the application, but is also specific enough to the project that it cannot be generalized in to an open source project. In either of these cases, and in many other more subtle scenarios, it is beneficial to understand how to create your own plugins and add-ons for Backbone so that you can take full advantage of encapsulated functionality, customized for your application’s needs, while still playing well with existing add-ons. Creating your own add-ons and plugins is both easy, and tremendously frustrating at the same time. Add-ons that are seemingly simple, such as creating the ability to have a “selectable” model and collection via my Backbone.Picky, are quick to build and be useful, but become very complex as the more subtle edge cases are discovered.

Throughout this book, I’ll walk you through the tools, tricks and lessons learned for building the smallest of add-ons through the largest of application frameworks such as Backbone.Marionette. I’ll teach you the tricks that I’ve learned, show you the pitfalls to avoid, and walk you through the construction of add-ons that are both useful and easy to use, while not creating an undue burden for the developers that are maintaining them or the developers that are using them in their applications.

Who Should Read This Book?

This book is aimed at developers that are already familiar with building Backbone.js applications of any scale, and are looking for ways to reduce their development efforts, clean up their code base, and provide standardized implementations for their teams to use in products and projects. It will show how to take a large code base and reduce duplication and boilerplate code down in to managable, customizable and flexible chunks that an entire team can then apply.

The ideal reader is a person who is building medium to large sized applications in Backbone, and may or may not be part of a team. You may be a team lead, looking to simplify the architecture and implementation of a large project, or a sole-developer or contractor, looking for more effective implementation patterns for your Backbone applications. If you’re writing applications and noticing a trend in the amount of boilerplate code, a series of patterns of implementation, or are looking for insight in to how to recognize these patterns, then this book is for you.

This book is not a general introduction to Backbone and its core concepts. There are plenty of books, screencasts, blog posts and other materials that cover a general introduction in great depth. Rather, this book will take your existing knowledge of building Backbone applications to a new level, showing you how to create common abstractions and re-usable implementations that may benefit your project specifically or be more broadly applicable and deliverable as open source.

Additionally, this book is not a general introduction to JavaScript, protoypal inheritance, design patterns, or test-driven development. While this book will touch on these subjects and show how to effectively make use of them in order to produce the highest quality, maintainable and flexible code, it is assumed that are at least familiar with the core JavaScript, it’s inheritance system, design patterns and unit testing in general.

For a general introduction to JavaScript, Backbone, protoypal inheritance, design patterns or test driven development, please see Appendix B for a list of resources.

Part 1: Backbone Views

Nearly every developer that works with Backbone quickly realizes that while Backbone is very flexible and powerful, it also leaves a lot of “boilerplate” code and small decisions up to the developer. Boilerplate is the code that has to be written all the time, every time, just to get the project or component off the ground. It’s the code that is necessary because the desired functionality won’t work without it. It’s the repetition and redundancy of copy & paste from object to object. But it is also the code from which patterns and re-usable snippets are often created.

The first place that developers see boilerplate is usually working with views. Views tend to require a number of things to work properly: data serialization, HTML template definition, template compilation and rendering, and more.

In part 1, the boilerplate of views will be eliminated. A generic render method will be built for views. Specialized view types will be extended from a custom a base type. The ability to add new view types that offer flexibility through code and configuration will be there, as well.

Chapter 1: View Rendering

A typical Backbone view will need to render some HTML and have that HTML populated in to the view’s $el. A simple example, using UnderscoreJS’ templates, might look like this:

 1 HelloWorldView = Backbone.View.extend({
 2
 3   render: function(){
 4     var renderedHtml = _.template("<h1>Hello world!</h1>");
 5     this.$el.html(renderedHtml);
 6   }
 7
 8 });
 9
10 var view = new HelloWorldView();
11 view.render();
12
13 console.log(view.$el); //=> "[<h1>Hello world!</h1>]"

If there is any data needed from a Backbone.Model, I can change the render method to include it when calling the template method:

 1 DataDrivenView = Backbone.View.extend({
 2
 3   render: function(){
 4     var renderedHtml = _.template("<h1><%= message %></h1>", this.model.toJSON());
 5     this.$el.html(renderedHtml);
 6   }
 7
 8 });
 9
10 var model = new Backbone.Model({message: "Hello Data-World!"});
11 var view = new DataDrivenView({
12   model: model
13 });
14
15 view.render();
16
17 console.log(view.$el); //=> "[<h1>Hello Data-World!</h1>]"

And if I need to render a collection of items in to my view’s template, I can swap out this.model for this.collection and iterate through the items in the template:

 1 CollectionView = Backbone.View.extend({
 2
 3   render: function(){
 4
 5     var data = {
 6       items: this.collection.toJSON()
 7     };
 8
 9     var renderedHtml = _.template("<h1><% _.each(items, function(item){ %><%= mes\
10 sage %> <% }) %>!</h1>", data);
11
12     this.$el.html(renderedHtml);
13   }
14
15 });
16
17 var collection = new Backbone.Collection([
18   {message: "Hello"},
19   {message: "Collection"},
20   {message: "Driven"},
21   {message: "World"}
22 ]);
23
24 var view = new DataDrivenView({
25   collection: collection
26 });
27
28 view.render();
29
30 console.log(view.$el); //=> "[<h1>Hello Collection Driven World!</h1>]"

In this case, I had to add a bit more to the render method. Not only did the template have to do the iteration for me, but the data that I passed in to the template needed be wrapped in a parent structure so that I could do the iteration. In the end, though, this view rendered the expected results in to the $el.

In looking at these three examples, there are several things that I can say are the same and several things that I can say are different. It can also be said that there is a lot of boilerplate between these three examples. It is boilerplate like this that become the basis for creating plugins and add-ons.

Extract Whats Common, Specify The Differences

Boilerplate code gets very frustrating very quickly. Having to type the same code over and over again is never fun. Copy and paste tends to be the first answer to that problem, but this quickly falls apart. Any time there is a change to the pattern of code being used, all of the places where this copy and paste occurred have to be updated. In any application of any substantial size, this is going to be a nightmare and it’s likely that at least one location that needs to be updated won’t be. To fix both the boilerplate problem and prevent the problems associated with copy & paste programming, the common parts of the solution can be abstracted away from the specifics of each use.

In the previous view rendering examples, there are some very obvious bits of code duplication or boilerplate. Each of the view’s render methods does the following:

Make a call to the _.template method

Pass an HTML template, as a string, to the template method

Replace the HTML contents of the $el property on the view

The differences between these methods can also be seen fairly easily:

The first view does not use any data

The second view calls this.model.toJSON() to get data, and passes that to the _.template function

The third view calls this.collection.toJSON() to get data, wraps that in another object literal, and passes the resulting object to the _.template function

The third view shows not only a more complex example, but also a hint at how the common parts of the render functionality can be extracted in to something reusable. The use of the data variable in this view shows me that I don’t have to supply all of the parameters to each of these function calls as literal values. Instead, I can extract them to variables.

For example, if I extracted all of the parameters in the third example, it might look like this:

 1 Backbone.View.extend({
 2
 3   render: function(){
 4
 5     var template = "<h1><% _.each(items, function(item){ %><%= message %> <% }) %\
 6 >!</h1>";
 7     var data = {
 8       items: this.collection.toJSON()
 9     };
10
11     var renderedHtml = _.template(template, data);
12     this.$el.html(renderedHtml);
13   }
14
15 });

I can take this a step further as well, with the template variable. Since this template is not going to change from one call of the render method to another, I can move this out to the view definition:

 1 Backbone.View.extend({
 2   template: "<h1><% _.each(items, function(item){ %><%= message %> <% }) %>!</h1>\
 3 ",
 4
 5   render: function(){
 6     var data = {
 7       items: this.collection.toJSON()
 8     };
 9
10     var renderedHtml = _.template(this.template, data);
11     this.$el.html(renderedHtml);
12   }
13
14 });

With the template extracted to the view definition, the render function becomes much easier to read and understand. The only code left in this function that is different than the other examples, is the call to create the data. The calls to render the template and populate the data are done with variables now. If I can take this one step further and extract the process of serializing the data that the view needs, then I’ll have a way to make this view rendering completely generic.

 1 Backbone.View.extend({
 2   template: "<h1><% _.each(items, function(item){ %><%= message %> <% }) %>!</h1>\
 3 ",
 4
 5   serializeData: function(){
 6     return data = {
 7       items: this.collection.toJSON()
 8     };
 9   },
10
11   render: function(){
12     var data = this.serializeData();
13     var renderedHtml = _.template(this.template, data);
14     this.$el.html(renderedHtml);
15   }
16 });

This view now has a completely generic render method, with two additional attributes that provide the template and the data that the view needs when rendering.

To create a generic base view out of this, I can take advantage of Backbone’s extend function. Whenever I extend from a type that Backbone provides, the extend method comes along with it. This method is like the extends keyword in Java, or the : inheritance character in C#. The mechanics of how it works are different, as JavaScript and Backbone use prototypal inheritance, but at a high level it is just a form of inheritance.

Given that, I can create a base view that provides the rendering mechanics for an application, like this:

 1 BaseView = Backbone.View.extend({
 2   render: function(){
 3     var data;
 4     if (this.serializeData){
 5       data = this.serializeData();
 6     };
 7
 8     var renderedHtml = _.template(this.template, data);
 9     this.$el.html(renderedHtml);
10   }
11 });

Then when I need a specific view to render with a template and data, I only need to extend from that BaseView view instead of Backbone.View. In this case, all three of the previous views that I had created would be able to extend from it. Even the first view that does not need to render any data will work fine, as this BaseView has provided a simple check around the existence of the serializeData method. If this method does not exist, it won’t be called. The data variable would be undefined at that point, and it would be ignored by the UnderscoreJS template function.

 1 HelloWorldView = BaseView.extend({
 2   template: "<h1>Hello world!</h1>"
 3 });
 4
 5 DataDrivenView = BaseView.extend({
 6   template: "<h1><%= message %></h1>",
 7
 8   serializeData: function(){
 9     return this.model.toJSON();
10   }
11 });
12
13 CollectionView = BaseView.extend({
14   template: "<h1><% _.each(items, function(item){ %><%= message %> <% }) %>!</h1>\
15 ",
16
17   serializeData: function(){
18     return {
19       items: this.collection.toJSON();
20     };
21   }
22 });

These three views, extending from the new BaseView, no longer have any of the boilerplate rendering code in them. They only specify the differences that each of the views needs.

Lessons Learned

This chapter has provided a quick introduction to creating a simple yet valuable plugin for Backbone. And there are several lessons that can be pulled from this particular abstraction. Some of them are specific to views and rendering of views, but others can be generalized in to something more broadly applicable.

Solve Real Problems

The rendering example isn’t just an academic exercise to show how to pull apart several implementations and create something re-usable. It’s a real-world solution, based on a real world problem. Developers have written the same rendering code in different view definitions a countless number of times.

Extract Common Code

By examining the differences between the three view definitions and rendering processes, we were able to spot the similarities - this things that were the same. The process of converting the various method parameters in to variables also helped us see what was common and what was different. We ended up with a few lines of code that were repeated through all of the views, and a few lines of code that were specific to each view.

Specify The Differences

Once we had the commonalities in the different view implementations identified, it was easy to see what was different as well. Those differences were then extracted from the core render method in a manner that allowed the render method to be flexible to the different needs of each view. Every view had a template to render, but each view’s template was different. Specifying the template as part of the view definition allowed the render method to render the template without having to know what the template’s contents were. The data used in rendering followed the same pattern initially, but also added the check to see if we needed to provide any data for the rendering. Specifying the differences for each view, within the view’s definition, allowed the commonalities to work properly, and provided more flexibility.

Backbone.View Extension Points

Every Backbone.View instance has a render method. This method is empty by default, but provides an extension point that we can use to provide rendering for our view. There are a number of other methods and extension points in Views, as well. Some of them are better to use than others, though. Sometimes it’s in our best interest to avoid providing an implementation for a specific setting, while other times Backbone expects us or at least encourages us to provide an implementation.

Chapter 2: Naming And Namespacing Your Plugin

JavaScript has the notion of “global” variables and objects within a browser. Every object, variable or function that is defined in the browser’s JavaScript runtime lives in the global scope by default. This is not a big deal with very small applications. But when an application begins to grow, and begins to use plugins such as jQuery, Underscore and Backbone, it becomes very important to not “pollute” the global scope with too many objects.

The risk of too many global objects or variables is that they will have the same name as another part of the project or another library. How many projects have a config object or method, for example? If they all used the same config object in the global scope, nothing would work together as they would be clobbering each other’s global object.

Building namespaced code is one way to avoid polluting the global space, and most popular libraries do this in some way. Backbone provides the Backbone namespace, for example. The View, Model, and Collection types all hang off of this namespace. And the BaseView that I just created should follow suit. It should be namespaced to either my application or the name of the plugin that I am building.

Unfortunately, JavaScript doesn’t have a formal concept of namespaces, like Java, C#, Ruby and other languages do. But that doesn’t mean we can’t use a namespace pattern to facilitate the same functionality. In fact, there are many options for making this work, including:

Object literal namespace objects

The Revealing Module pattern

… and more variations

Any object can be used as a namespace. All I need to do is assign one object to an attribute of another object, and I effectively have a namespace. This can be a dangerous thing to do, though, as I may accidentally override existing data or functionality on an exsiting object. Instead, it is a better idea to use an empty object literal as the namespace. This way, I am less likely to override something important.

To create an object literal as a namespace, just create an object literal and then assign objects as attributes. For example, the BaseView can be attached to a BBPlug namespace (short-hand for “Building Backbone Plugins”) like this:

 1 var BBPLug = {};
 2
 3 BBPlug.BaseView = Backbone.View.extend({
 4
 5   render: function(){
 6     var data;
 7
 8     if (this.serializeData){
 9       data = this.serializeData();
10     };
11
12     var renderedHtml = _.template(this.template, data);
13     this.$el.html(renderedHtml);
14   }
15 });

To extend from this object, I must specify the entire path to the object, BBPlug.BaseView:

 1 HelloWorldView = BBPlug.BaseView.extend({
 2   template: "<h1>Hello world!</h1>"
 3 });
 4
 5 DataDrivenView = BBPlug.BaseView.extend({
 6   template: "<h1><%= message %></h1>",
 7
 8   serializeData: function(){
 9     return this.model.toJSON();
10   }
11 });
12
13 CollectionView = BBPlug.BaseView.extend({
14   template: "<h1><% _.each(items, function(item){ %><%= message %> <% } %>!</h1>",
15
16   serializeData: function(){
17     return {
18       items: this.collection.toJSON();
19     };
20   }
21 });

For a more complete list of options and possibilities for namespacing and providing protection for your code, and why, see Stoyan Stefanov’s JavaScript Patterns from O’Reilly press.

Now the three views that I am working with are all extending from the correct BBPlug.BaseView. Any additional objects, functions, data, configuration or other bits that my plugin needs will also hang from the BBPlug object. This way, my plugin will not interfere with other plugins and libraries. I only need to be careful to remember to use the BBPlug namespace and always declare my variables with the var keyword. But I honestly don’t worry about this too much. Tools such as JSHint will analyze my code and ensure that I am correctly namespacing and declaring everything.

This simple object literal as namespace will be sufficient for now. Later, the Revealing Module pattern will be used to help create privacy and encapsulation. But that can wait.

Lessons Learned

Java, C# and other languages provide an explicit construct for namespacing, but JavaScript does not. This does not mean that the concept is not important, though. Namespacing can and should be done in JavaScript. It just has to be done within the constructs that JavaScript provides - as more of an idea than an explicit syntax.

Don’t Pollute The Global Namespace

Namespacing our abstractions is very important. If we don’t provide a single, global object for all of our code to hang off of, we run the risk of either breaking someone else’s code or library, or having another developer or library break our code. There are several options for implementing a namespace in JavaScript, and none of them are specific to Backbone. But Backbone provides a good example of using a namespace, and we created our own with a simple object literal.

Chapter 3: Complex And Divergent Views

The BBPlug.BaseView will allow an application to have a consistent method of rendering templates and data. There are some rather restricting limitations in it, though. If a view has any custom code that needs to run on the rendered HTML, for example, it can’t - not easily at least. Additionally, the requirement of providing a serializeData method will create some duplication in all of our views - which is what we were setting out to avoid in the first place.

Fortunately, these limitations on flexibility and capabilities are solvable at the same time that the code duplication can be significantly reduced.

onRender

In an application of any size beyond a simple ToDo app, a number of views will need to have some very specialized code run against the HTML that is rendered. For example, if a view is rendering a list of comments for a blog post, it may be desirable to show when the individual comments were added using the standard “(time) ago” format: “10 minutes ago”, “2 months ago”, “over a year ago”, etc. This format can be easily obtained using the moment.js plugin, but where would the call to this plugin go in the current BaseView implementation?

With the current implementation, the BaseView’s render method may have to be overridden. This isn’t too bad, I guess. I can call in to the BaseView’s render method through it’s prototype, allowing the standard render to take place and then running my code to format the dates correctly.

 1 CommentView = BBPlug.BaseView.extend({
 2   template: "...",
 3   serializeData: function(){...},
 4
 5   render: function(){
 6     // use the BaseView's prototype to do the default render
 7     BBPlug.BaseView.prototype.render.call(this);
 8
 9     // call moment.js' to format our dates correctly
10     var commentDate = this.model.get("date");
11     var timeAgo = moment(commentDate).fromNow();
12
13     // update this view's DOM with the correct format
14     this.$(".comment-date").text(timeAgo);
15   }
16 });

This is functional. It will correctly show the “(time) ago” format that the view needs. But it does so at the cost of an undue burden on the developer that is using this plugin. Every time this code is needed, the developer that is writing it has to remember to call the prototype’s render method. Now there may be some scenarios where this is necessary, but something as common as manipulating the view’s DOM elements after rendering is going to produce a lot of code duplication - boilerplate - and create a host of potential problems, like forgetting to call the prototype method.

To correct this, the BaseView can allow an onRender function to be specified on views that extend from it. If this method is provided, it will be called after the view has been rendered. This will allow a specific view to modify the DOM as needed, without having to override the render method.

 1 BBPlug.BaseView = Backbone.View.extend({
 2   render: function(){
 3     var data;
 4     if (this.serializeData){
 5       data = this.serializeData();
 6     };
 7
 8     var renderedHtml = _.template(this.template, data);
 9     this.$el.html(renderedHtml);
10
11     // Call the `onRender` method if it exists
12     if (this.onRender){
13       this.onRender();
14     }
15   }
16 });

Now I can modify the CommentView to use the onRender method instead of overriding the render method directly:

 1 CommentView = BBPlug.BaseView.extend({
 2   template: "...",
 3   serializeData: function(){...},
 4
 5   onRender: function(){
 6     // call moment.js' to format our dates correctly
 7     var commentDate = this.model.get("date");
 8     var timeAgo = moment(commentDate).fromNow();
 9
10     // update this view's DOM with the correct format
11     this.$(".comment-date").text(timeAgo);
12   }
13 });

This may only save one or two lines of code and one comment in the view, but when that one line is added up 20, 30, or 300 times in a very large application, it can make a significant difference.

Default serializeData Implementation

There are still some chunks of boilerplate code in the CommentView and previous view implementations from the last chapter. Each of the views, though it has extended from the BBPlug.BaseView, must provide a serializeData method if it needs data in the template. Most of the time the data that is needed will be one of two things: this.model.toJSON() or {items: this.collection.toJSON()}. Rather than repeating this code in each view that needs it, a default serializeData implementation can be provided.

 1 BBPlug.BaseView = Backbone.View.extend({
 2
 3   serializeData: function(){
 4     var data;
 5
 6     if (this.model){
 7       data = this.model.toJSON();
 8     }
 9
10     if (this.collection){
11       data = { items: this.collection.toJSON() };
12     }
13
14     return data;
15   },
16
17
18   render: function(){
19     // ...
20   }
21 });

By including this default implementation of serializeData, a view that needs either a model or a collection as its data source will not have to provide its own version of this method.

 1 // Model View
 2 // ----------
 3 MyView = BBPlug.BaseView.extend({
 4   template: "..."
 5 });
 6
 7 myView = new MyView({
 8   model: myModel
 9 });
10
11 myView.render();
12
13
14 // Collection View
15 // ---------------
16
17 MyCollectionView = BBPlug.BaseView.extend({
18   template: "..."
19 });
20
21 myCollectionView = new MyCollectionView({
22   collection: myCollection
23 });
24
25 myCollectionView.render();

Of course any view that needs any custom data can still provide an implementation, but it is not strictly necessary.

Extracting ModelView And CollectionView

There is one potential problem that this solution creates. If a view happens to have both a model and a collection set when the serializeData function is executed, then the collection will always win. If the view intends to render the model as the data source for the template and only needs the collection as a supporting object for some other purpose, then there’s a problem. The view has rendered the collection data instead of the model data. To fix this, the view would have to either override the serializeData method to only use the model, or provide the collection to the view in a different manner. While either of these options would work, they are not the most elegant solution.

A better solution - one that creates more flexibility, more capabilities and less ambiguous use - would be to separate the ideas of a ModelView and a CollectionView. Each of these view types would provide the specific serializeData method that it needs, and open up the potential for other features to be added to a specific view type.

The extraction of these two view types does not negate the need for the BaseView, though. Instead, it solidifies the usefulness of this base view type. The ModelView and CollectionView can extend directly from it, keeping the core rendering logic in one place. But the BaseView will no longer need a default implementation of serializeData, so this method can be removed.

 1 BBPlug.BaseView = Backbone.View.extend({
 2   render: function(){
 3     var data;
 4     if (this.serializeData){
 5       data = this.serializeData();
 6     };
 7
 8     var renderedHtml = _.template(this.template, data);
 9     this.$el.html(renderedHtml);
10
11     // Call the `onRender` method if it exists
12     if (this.onRender){
13       this.onRender();
14     }
15   }
16 });
17
18 // Create a `ModelView` view type, to render a model in to the template
19 BBPlug.ModelView = BBPlug.BaseView.extend({
20
21   serializeData: function(){
22     var data;
23
24     if (this.model){
25       data = this.model.toJSON();
26     }
27
28     return data;
29   }
30
31 });
32
33 // Create a `CollectionView` view type, to render a collection in to the template
34 BBPlug.CollectionView = BBPlug.BaseView.extend({
35
36   serializeData: function(){
37     var data;
38
39     if (this.collection){
40       data = this.collection.toJSON();
41     }
42
43     return data;
44   }
45
46 });

In both of these new view types, the render method from the base view will be used, but the serializeData method from the specific view type will be used.

With these new view types in place, the blog post with comments example could be updated so that the blog post itself renders as a ModelView while the comments are rendered as a CollectionView.

 1 BlogPostView = BBPlug.ModelView.extend({
 2   template: "..."
 3 });
 4
 5 CommentsView = BBPlug.CollectionView.extend({
 6   template: "..."
 7 });
 8
 9 var blogPostView = new BlogPostView({
10   model: blogPost
11 });
12
13 var commentsView = new CommentsView({
14   collection: blogPost.comments
15 });

The view definitions for a blog post and the related comments view are now very small. They each only have one line of code, specifying the template that the view needs to use. The remaining code to serialize the data and render the template with that data has been abstracted in to various view types in the BBPlug framework. This is a significant reduction in the amount of code that was required even to render a “Hello World” example.

Lessons Learned

This chapter has provided a much more in-depth exploration of what can be included in a framework of View types that sit on top of Backbone. Starting with the basic BBPlug.BaseView, the need to cleanly separate a ModelView and CollectionView was identified and codified. Additional reasons for providing abstractions and reusable code were also identified, resulting in several new lessons that can be taken and applied to other view types as well as other object types in general.

Remove Boilerplate. Don’t Just Move It.

The initial implementation of BBPlug.BaseView required every view to implement a serializeData function. This was fine at first, when only a few distinct views were being used. But as new views were identified, the realization that each of these views fell in to the same patterns of what the serializeData implementation should look like set in. The BaseView had removed some boilerplate code, but in the process it had also just moved some of it. A simple default implementation of serializeData was created and the amount of code that each view was required to implement was reduced.

If the extraction of common functionality requires a specific function to be implemented, or specific data to be provided, ask whether or not the extracted code can have a default implementation. Does the BaseView’s render method truely require a template, for example? In this case yes. Rendering HTML without a template to render wouldn’t prove to be of much use. But when the question is asked about the serializeData method, the answer was yes, a default implementation could be used.

Specialization Comes From Generalization

In the process of creating the default serializeData method, two separate and specialized use cases became apparent for views: a model view, and a collection view. The initial difference between these two view types was only the way the serializeData method was implemented. The ModelView uses the view’s model for data, while the CollectionView used the view’s collection.

By creating specialized views from the generalized BaseView, though, more flexibility was achieved and more opportunities were opened up. In the future, there may be additional behavioral and implementation changes that are common only to views that render collections. As these specialized needs are discovered, they can be added directly to the CollectionView without affecting the BaseView or ModelView directly.

Don’t Require Calls To The Prototype’s Method

In many cases a simple implementation of a common function will prove to be insufficient. Specific implementations and use cases will have specific needs. In some cases it may be necessary to override a method that a base type implements, and then call the method on that base prototype before providing the specific implementation needs.

Whenever possible, though, this should be avoided. The burden of having to remember to call a prototype’s method can cause mistakes and bugs in systems. Instead, provide calls to optionally implemented methods such as the onRender method to allow custom code in specific view types. This method, when implemented in a view that extends from BaseView, allows a specific view to perform any necessary DOM manipulation or other functions just after the view has been rendered. It allows the code to be encapsulated within the view where it is needed, and it also keeps the implementor from having to remember to call a prototype method to facilitate the actual rendering.

Hide Calls To Prototype Methods When They Are Necessary

There will inevitably be situations where calls to a prototype method are necessary. In these situations, the prototype method calls should be hidden in the implementation of the type that is being extended. The developer that is extending from these types should not be responsible for making the prototype method call, unless they choose to explicitly override a prototype method.

This means that in a view implementation, code that needs to be executed on construction or initialization of the view should not implement an initialize method. It’s common practice for a view to have an initialize method to set up event handlers, etc. Implementing the initialize method on a base class would force all views that need to use this method to call to the prototype’s initialize method. Instead, implement a constructor function in base views so that the need to call the prototype’s method can be hidden in the base view. This allows a specific view to implement an initialize method as needed, while still allows the base view type to run custom code on construction of a new view instance.

Chapter 4: Cache Pre-Compiled Templates

So far the extracting of common implementations in to reusable objects has been focused on the reduction of code duplication. However, there are other reasons to create common objects and components. At times, performance considerations need to be taken in to account. For example, the BaseView view type has a prime candidate for this: pre-compiling the templates.

A Texas 2-Step

Underscore, like most JavaScript template engines, uses a 2-step process to generate the end result:

Compile the specified template in to a function

Execute the function, with an option set of data, to generate the HTML result

The BaseView that we’ve defined happens to compress both of these steps in to a single call - _.template(this.template, data) - but the two step process is still happening.

The problem is that most view definitions will not change the template at runtime. That is, once a template has been defined, the same template will be used over and over again no matter how many instances of that view are created and rendered. This is a performance burden on the view instances, re-doing work that has already been done before, to get the same results. In fact, the performance difference between using a pre-compiled template vs compiling everytime can be quite staggering. Pre-compiled templates can be nearly twice as fast, averaging a little over 1.5 times faster, depending on the browser and version used (see this JSPerf test and this blog post on pre-compiled templates for more information).

If this is the case and a view’s template doesn’t change at runtime, then it doesn’t make sense to re-compile the template every time. The solution, then, is to compile the template once and re-use that pre-compiled and cached template every time a new view instance is created.

Building A Template Cache

View instances should check for and/or build a template cache when they are instantiated. Template caches should also be re-used between view instances, and not re-compiled per instance. For that to happen, the easiest place to store the cached template function will be the the view type’s prototype.

 1 BBPlug.BaseView = Backbone.View.extend({
 2
 3   constructor: function(){
 4     Backbone.View.prototype.constructor.apply(this, arguments);
 5
 6     this.buildTemplateCache();
 7   },
 8
 9   buildTemplateCache: function(){
10     var proto = Object.getPrototypeOf(this);
11
12     if (proto.templateCache) { return; }
13     proto.templateCache = _.template(this.template);
14   },
15
16   render: function(){
17     var data;
18     if (this.serializeData){
19       data = this.serializeData();
20     };
21
22     // use the pre-compiled, cached template function
23     var renderedHtml = this.templateCache(data);
24     this.$el.html(renderedHtml);
25
26     if (this.onRender){
27       this.onRender();
28     }
29   }
30 });

There are several items of interest in this implementation.

First, the use of the constructor function. JavaScript itself doesn’t typically provide a function like this. Rather, this is a function that Backbone provides as the object’s constructor. Its called any time an instance of the object type is created, and it is responsible for the over-all initialization of the type, including the call to the object’s initialize function that is typically seen in a Backbone object. When overriding the constructor function of a Backbone object, it’s important to call the prototype’s constructor function so that the initialize method and other necessary code will be called.

So why use the constructor function when the initialize function could be used instead? Isn’t this causing an undue burden on the developer, overriding it? The answer to that isn’t quite so simple. Yes, the developer writing this base view has to remember to call the prototype’s constructor. However, this is a far better situation than overriding the initialize function. Overriding that function would require every developer that extends from this base view to remember to call back to the prototype’s initialize function if they need to implement their own initialize.

If we override the constructor instead, only the base view that we are defining has to remember to call back to the prototype’s constructor function. Views that extend from this base view don’t have to call back to the prototype at all - for the constructor or for the initialize method. This means the views extending from BaseView have less to remember, reducing the over-all burden of implementation.

Secondly, the use of Object.getPrototypeOf in the buildTemplateCache function is a different way of getting the prototype. The constructor that we are accessing the prototype of Backbone.View directly, but the buildTemplateCache uses this function instead. In the constructor, we know that the prototype is Backbone.View so we can explicitly state that. Now it can be argued that we should just use Object.getPrototypeOf in the constructor function. But the use of it is necessary in the builtTemplateCache function because we don’t directly know the prototype of the object we are dealing with.

When the buildTemplateCache function is called, the context is set to the current instance of whatever view type we have defined. That is, any time you use this within the view’s methods, it will (most likely) be referencing the current view instance. If you set this.templateCache = â€¦ then it will always set the templateCache attribute on the view instance. This would defeat the purpose of a template cache, as each view instance would build it’s own cache. The call to Object.getPrototypeOf, then, gives us the prototype of the object instance. By using “proto.templateCache”, the cache is set on the prototype directly and all instances will be able to retrieve the precompiled template from the cache.

A getPrototypeOf Shim

There is one potential drawback to using Object.getPrototype - not every browser supports it. According to the Mozilla Developer Network, the current support for this method includes FireFix 3.5 and up, Chrome 5 and up, Internet Explorer 9 and up, and Safari 5 and up. Opera is not listed with support at all, and IE 8 and below do not support this. To get support for it, then, a shim has to be put in place. Fortunately, John Resig (the creator of jQuery) has one available via his blog:

 1 if ( typeof Object.getPrototypeOf !== "function" ) {
 2   if ( typeof "test".__proto__ === "object" ) {
 3     Object.getPrototypeOf = function(object){
 4       return object.__proto__;
 5     };
 6   } else {
 7     Object.getPrototypeOf = function(object){
 8      // May break if the constructor has been tampered with
 9       return object.constructor.prototype;
10     };
11   }
12 }

This code needs to be included somewhere in the over-all project, and sent down to the browser before any call to Object.getPrototype can be called. Otherwise Opera and old versions of IE won’t be able to use this method call.

A check is made to see if the object’s prototype has a cached version of the template or not. If it is found, the function exits immediately. If it is not found, a compiled version of the template is created and stored. And lastly, the render function is updated to use the cached template instead of the raw template string.

With this in place, the view definitions that we have for blog posts, comments, or any other view that extends from BaseView, ModelView, or CollectionView, will receive the performance benefit of pre-compiled and cached templates. The big win, though, is that views extending from BaseView do not need to know anything about this optimization or handle it explicitly. They only need to specify a template in the view definition, as they have already been doing. The performance benefit was added to the base view and therefore immediately available to all other views.

For more information on prototypal inheritance and the this keyword in JavaScript, check out my screencasts at WatchMeCode.net. Episode #4 covers JavaScript’s context (this) keyword while Episode #5 covers prototypal inheritance.

Lessons Learned

Reducing boilerplate code is an important and common reason for creating abstractions and extracting common code. However, performance improvements, encapsulation and other reasons exist to create abstractions and re-usable components. Look for opportunities to simplify the overall framework and the use of it, and opportunities for performance improvements in the framework or plugin.

Performance: Do You Speak It?

Pre-compiled templates are a great example of a place that performance concerns create a need for more abstraction. Rather than having each view implementation be responsible for caching the template that it uses, having a base type implement the caching mechanism makes the cache and pre-compilation transparent.

Cross-Browser Compatibility And Shims

Of course, this isn’t just a plugin and add-on concern. JavaScript application development in general needs to be aware of cross-browser compatibility. Fortunately, there are several frameworks, guidelines and other resources for managing these issues. Using a framework like jQuery, for example, creates a higher likelihood that the functionality you need will be available in all of the browsers that you are supporting. Even still, there are times when additional shims and backward-compatibility implementations must be provided. Tools like Modernizr provide a lot of backward compatibility for modern features, but a quick search for specific methods such as Object.getPrototypeOf or Object.create will often surface individual implementations, reducing the need for something as large as Modernizr.

Chapter 5: Overriding Backbone.View’s ‘constructor’

When overriding the base Backbone.View to create your own view types from the base views, there are some issues that you may run in to with inheritance. The inheritance of constructor functions can be broken in strange ways, and code that you override in the constructor or other base ModelView or CollectionView functions may not be called when you expect it to be. This can be a tremendously frustrating problem, as the code you write looks correct, but it does not fire like you expect.

Fortunately, the fix is simple. Unfortunately, it’s not obvious. Worse, though, is that the simple but not obvious nature of the fix often makes it look like the solution is unnecessary.

Understanding the solution, then, is great - but it is not enough to know the solution. If you don’t understand the problem and the cause, it’s likely that you’ll allow the solution to be removed at a later point. Before seeing the solution, then, you need to understand the problem and the cause. It’s also a good idea to mark the solution with comments that explain why it’s there, so that others won’t accidentally remove the solution in the future.

Setting An Automation ID On All Views

Say you have an application that always needs to set a specific data-attribute on view instances. You may need to supply an attribute like data-automation-id with a unique yet repeatable id for test automation. This id should only be available for test automation, though, and not in the production environment.

To facilitate this, you can add a new JavaScript file to a project and include code such as the following in it.

 1 // automationid.js
 2 (function(){
 3
 4   // store a reference to the original constructor function
 5   var originalConstructor = Backbone.View.prototype.constructor;
 6
 7   // create a function that can return a unique, repeatable id
 8   function getAutomationId(view){
 9
10     // do something here to get a unique, yet repeatable id
11     // based on the view instance that is passed in. send it
12     // back as a return value
13     var id = â€¦;
14
15     return id;
16   }
17
18   // override the View's constructor
19   Backbone.View.prototype.constructor = function(options){
20
21     // call the original constructor function with
22     // the options provided to this instance
23     originalConstructor.call(this, options);
24
25     // set the automation id on the
26     var automationId = getAutomationId(this);
27     this.$el.data("automation-id", automationId);
28
29     // log a message, saying the automation-id is set
30     console.log("Automation ID set: ", automationId, view);
31   };
32
33 })();

That’s A Bit If-y

The automation ID code is wrapped in an Immediately Invoking Function Expression (“IIFE”, pronounced “if-e”) so that the reference variable and view definition can be hidden from global scope. You may or may not need this wrapper for private scope. You can learn more about IIFEs from Ben Alman’s blog post on the subject.

In your project’s HTML, include this file immediately after the backbone.js file. Putting it here will ensure that your automation id function is attached to the Backbone objects before anything like BBPlug is loaded.

1 <script src="/js/backbone.js"></script>
2 <script src="/js/automationid.js"></script>
3 <script src="/js/bbplug.js"></script>

Now to test this and see the automation id.

Testing The AutomationID Plugin

To test this, you only need to run an application after the automationid.js file has been included.

 1 (function(){
 2
 3   var V = BBPlug.ModelView.extend({
 4     template: "#model-template"
 5   });
 6
 7   $(function(){
 8     var v = new V();
 9     v.render();
10     $("#main").html(v.$el);
11   });
12
13 })();

Every view instance should log a message stating the automation id with the view instance. Only instead of seeing the message you expect, you will see nothing at all in the console logs.

This is definitely not what you wanted or expected. It should be showing the automation ids for each view, after all, and it isn’t.

So why isn’t it showing the automation id?

The Problem Of Taxidermy

The short version of the problem is that replacing the constructor method on Backbone.View.prototype doesn’t work. The prototype.constructor attribute is part of the JavaScript prototypal inheritance system, and isn’t something you should replace at all. Doing so is essentially trying to replace the type itself, but only replacing a specific reference to the type. Backbone provides the ability to specify a constructor in it’s type definitions, and it uses that function as the constructor function for the type that is returned. But this is only a convenience if not a coincidental naming of a method.

Unfortunately, this creates a larger problem. There are times when you will want to override the constructor of a type, but you shouldn’t try to do so the way that the automation id plugin was working.

Taxidermy On Prototypes

Replacing the prototype.constructor is a bit like taxidermy - the end result of “stuffing” a dead bear may still look like a bear on the outside, but it’s not really a bear anymore. It just looks like one. In the case of prototype.constructor though, this is especially dangerous because you can break code that relies on type checking or prototypal inheritance features that look at the prototype.constructor.

Visualize this through code, again:

1 function MyObject(){}
2
3 MyObject.prototype.constructor = function(){};
4
5 console.log(MyObject.prototype.constructor);
6 console.log(MyObject.prototype.constructor === MyObject);

The prototype.constructor is no longer pointing to MyObject, so the original MyObject “constructor function” is not being applied to the new object instance.

Correctly Overriding The Constructor Function

All of the problems associated with the prototype.constructor replacement may be a bit disheartening. But there is hope, and a fairly simple solution.

There are two things you will need, to solve the problem of overriding a Backbone object’s constructor function without any other code having to extend from it directly.

A new type with the “super-constructor” pattern (where a type calls back to the prototype.constructor manually)

A complete replacement of the base view who’s constructor you want to replace.

By creating a new type that calls back to the original type’s constructor, you can ensure the correct chain of inheritance and constructors is handled. Then to get your new type in place without forcing others to extend from your type, you will need to replace the type from which your plugin extends, prior to any other code using it.

The Super-Method Pattern

The “super-method” pattern is where you call the parent type’s method from your own method. Most other languages make it easy to call the “super” function when you override method - to call the original method that you are overriding. JavaScript, unfortunately, doesn’t have a “super” or “base” or anything like that. There are ways around this, though, all of which involve getting a reference to the prototype of your type, and calling the method directly.

For example, overriding the toJSON method of a model:

 1 var MyModel = Backbone.Model.extend({
 2
 3   // a super-method
 4   toJSON: function(){
 5     // call the "super" method -
 6     // the original, being overriden
 7     var json = Backbone.Model.prototype.toJSON();
 8     // manipulate the json here
 9     return json;
10   }
11 });

This will call the toJSON method of the type from which the new type was extended. It’s a little more code than other languages, but it still gets the job done.

More Than One Way To Call Prototype

There are a lot of different ways to get to and call the methods of a prototype object. If you’d like to learn more, check out my triple pack of screencasts covering Scope, Context and Objects & Prototypes

The Super-Constructor Pattern

The constructor function of a Backbone object looks like it would be even easier to replace than a normal method. If you extend from Backbone.View, you don’t need to access the prototype. You only need to apply Backbone.View as a function, to the current object instance.

Once you have your type set up, you will need to replace the original type with your new type. By doing this, any new type that tries to extend from the original named type, will get yours instead of the original. But you can’t just replace Backbone.View directly.

 1 // define the new type
 2 var MyBaseView = Backbone.View.extend({
 3   constructor: function(){
 4     var args = Array.prototype.slice.apply(arguments);
 5     Backbone.View.apply(this, args);
 6   }
 7 });
 8
 9 // replace Backbone.View with the new type
10 Backbone.View = MyBaseView;

Args And Old Browsers

The args line is in the super-constructor example to ensure compatibility with older browsers. Some versions of IE, for example, will throw an error if the arguments object is null or undefined, and you pass it in to the apply method of another function. To work around this, you can slice the arguments object in to a proper array. This will return an empty array if the arguments is null or undefined, allowing older versions of IE to work properly.

Unfortunately, this setup will fail horribly. When the call to Backbone.View.apply is made, it will find your new type’s constructor sitting in Backbone.View, causing an infinite loop.

To fix this, you need to store a reference to the original Backbone.View separately from the new view type. Then you will need to call this reference from your constructor function, and not the Backbone.View named function, directly.

 1 (function(){
 2   // store a reference to the original view
 3   var Original = Backbone.View;
 4
 5   var MyView = Original.extend({
 6     // override the constructor, and all the original
 7     constructor: function(){
 8       var args = Array.prototype.slice.call(arguments);
 9       Original.apply(this, args);
10     }
11   });
12
13   // Replace Backbone.View with the new one
14   Backbone.View = MyView;
15 })();

The end result of this is Backbone.View having been replaced with your view type, while still maintaining a reference to the original so that it can be called when needed. Provided the file that includes this code is loaded prior to any other code extending from Backbone.View, all views will receive any functionality defined in MyView - which is exactly what you wanted in the Automation ID view.

Putting The Pieces Together

With the “super-constructor” pattern, the problem of replacing Backbone.View without any other code knowing it has been replaced, can be solved. The Automation ID plugin can be salvaged and it can be used, with relatively minor modifications.

 1 // automationid.js
 2 (function(){
 3
 4   // store a reference to the
 5   // original constructor function
 6   var Original = Backbone.View;
 7
 8   // create a function that can return
 9   // a unique, repeatable id
10   function getAutomationId(view){
11
12     // do something here to get a unique, yet repeatable id
13     // based on the view instance that is passed in. send it
14     // back as a return value
15     var id = â€¦;
16
17     return id;
18   }
19
20   // override the View's constructor
21   AutomationIDView = Bacbone.View.extend({
22
23     constructor: function(options){
24       // call the original constructor function with
25       // the options provided to this instance
26       Original.call(this, options);
27
28       // set the automation id on the
29       var automationId = getAutomationId(this);
30       this.$el.data("automation-id", automationId);
31
32       // log a message, saying the automation-id is set
33       console.log("Automation ID set: ", automationId, view);
34     }
35   });
36
37   // replace Backbone.View
38   Backbone.View = AutomationIDView;
39
40 })();

Now you have a plugin that replaces Backbone.View with your AutomationIDView, and no other code in the app knows about it. You only need to ensure this file is loaded before any other file with code that extends from Backbone.View.

Not Just Backbone.View

This problem and solution applies to any Backbone type, not just View. If you replace the Backbone.Model.prototype.constructor or Backbone.Router.prototype.constructor, you will run in to the same problem and have the same options for a solution.

 1 (function(){
 2
 3   var origConst = Backbone.Model.prototype.constructor;
 4
 5   Backbone.Model.prototype.constructor = function(){
 6     // do custom code here
 7
 8     var args = Array.prototype.slice.apply(arguments);
 9     origConst.apply(this, args);
10
11     // do custom code here
12   }
13
14 })();

Not Every Type You Define

Fortunately, you don’t need to apply the super-constructor pattern of calling back to the parent’s constructor function, every time you define a new type. You only need to do this when you are defining a base type from which you will be extending.

 1 var MyBaseView = Backbone.View.extend({
 2
 3   // apply the super-constructor pattern
 4   // because this is a base view type from which
 5   // other views will extend
 6   constructor: function(){
 7     var args = Array.prototype.slice.apply(arguments);
 8     Backbone.View.prototype.constructor.apply(this, args);
 9   }
10 });
11
12 var CreateUserForm = MyBaseView.extend({
13   // no need to apply the super-constructor pattern
14   // because this view type is not meant to be extended
15   // in to a new view type
16 });

Lessons Learned

A picture may be worth 1,000 words, but a single line of code to be changed is worth at least 2,0000 if this chapter’s length is to be a judgement.

JavaScript Can Be Complex. Simplify It.

JavaScript’s inheritance, prototypes, method invocation patterns, and other aspects all have rather simple rules on the out-set. But the combination of seemingly simple rules can have some very dramatic effects. Understanding each aspect of the rules and how they all combine can be an overwhelming task, at times. Frameworks like Backbone help us to avoid common mistakes and hide a lot of the complexities. But even great frameworks with thousands of users have edge cases.

Don’t be surprised when your own applications run in to edge cases and complexities. Do your best to hide the complexity from the developers writing day to day code. Create meaningful abstractions that are easy to modify, so that simple fixes can have a meaningful impact on your application.

Constructor Functions vs prototype.constructor Functions

JavaScript’s prototypal inheritance system sets up a default prototype for every function. Each prototype has a constructor function that points to the original function that defined the type, by default. The prototype.constructor should not be touched, in spite of Backbone allowing us to define constructor functions. This is akin to taxidermy where something looks like one thing, but is really something else entirely.

The Super-Constructor Pattern

When creating base types for other types to extend from, you may need to apply the super-constructor pattern. This allows your type to ensure the correct constructor function of the parent type is called.

Code Injection As A Form Of Plugin

Plugins that are provided as base types can be useful. Specialization of view types, for example, creates an easy way to get functionality in to a system, quickly. But this isn’t always the best way to create a plugin. There are times when you need to inject code without any other code knowing.

In the original example for this chapter, there was a need to add an automation id to every view instance. One option for doing this would have been to create an AutomationIdView from which every view could extend from. But that would cause the automation id to be in your production environment, as well. Instead, a plugin to replace the Backbone.View.prototype.constructor function was created. This allows the automation id to be inserted for a test environment, by including the automationid.js file, while leaving the functionality out of the app when in production or other environment that don’t need it.

Part 2: Managing The DOM

With the ability to quickly and easily create new view types, the process of managing where and when the views are displayed now seems quite cumbersome. Having jQuery selectors riddled throughout the code makes it difficult to change the DOM structure without breaking a lot of the app. It also requires a lot of duplication of selectors.

Managing widgets and controls, and figuring out a consistent and simple way to place views in the DOM and remove them from the DOM is as important as the ability to define views. Part 2, then, will show you how to create a few simple objects to manage DOM references, and show and swap out views. Along the way, you will update your views with some new options, as well. You will also combine the ability to define views and manage the DOM, in to a single view type called a Layout.

Chapter 6: Managing DOM Widgets And Controls

Most Backbone applications either use jQuery or Zepto as their DOM manipulation of choice. I tend to use jQuery as it’s supported across more browsers and has more features – though it is a little heavier in terms of download size (and maybe performance). I also use a lot of jQuery plugins for various widgets and controls, to create specific effects, etc. It’s generally easy to do, as Backbone’s views provide direct access to a jQuery element as this.$el. From there, I can call standard jQuery code and plugins.

There are some common patterns I’ve noticed for doing this, too. Specifically, when to call a particular jQuery function or plugin largely depends on the purpose of that function and sometimes depends on how that function or plugin is built.

DOM Dependent/Independent

At a very basic level, jQuery manipulations of the DOM can fall in to one of two categories:

DOM-dependent

DOM-independent

Many of the things I do with jQuery code depend on the HTML that I’m manipulating being in the DOM already. For example, it doesn’t make much sense to call “.slideUp” if the HTML we’re manipulating isn’t currently displayed. The animation that this method causes would still run, but we wouldn’t see anything. The end result would not be visible and we would have wasted the browser’s execution time on this animation. I generally lump visual changes and animations in to the DOM-dependent category because it doesn’t make sense to use these methods if the HTML is not in the DOM yet.

On the other hand, some of the calls I make don’t need the HTML to be part of the DOM. In those cases, I can work with document fragments or even raw strings. I often call .hide() on HTML fragments before they are attached to the DOM, for example. I do this so that when the HTML fragments are finally added to the DOM, they won’t be visible to the user. Then, after I’ve ttached the HTML to the DOM, I can call .slideUp() or any of a number of other animation methods to cause the content to be displayed. I call these methods DOM-independent because they can be called whether we are working with a document fragment that only exists in memory, or working with an element that is already part of the visible DOM.

Of course there are a lot of methods in jQuery that don’t deal with HTML elements or the DOM at all. These would clearly fall in to the DOM-independent category, but I’m not going to address those right now. But even if these two categories are a simplified way to view jQuery, it is generally useful. It helps me understand when I should call certain methods vs others, and gives me a better idea of where to integrate jQuery calls with my Backbone applications.

Simple Manipulations And Events

Most of the simple manipulations that I perform with jQuery are DOM-independent. I can call them and manipulate a document fragment or a DOM element directly, whenever I want to. This includes not only showing / hiding HTML elements, but also adding and removing them, attaching events, and more.

Consider this example:

 1 Backbone.View.extend({
 2   // this is the default for backbone views
 3   // tagName: "div"
 4
 5   render: function(){
 6     var html = $("<ul>");
 7
 8     html.append("<li>foo</li>");
 9     html.hide();
10
11     this.$el.html(html);
12   }
13 });

With Backbone.View, an HTML element is often created with a view instance. This elements becomes the this.$el attribute on the view. In the render method, then, I am using jQuery to create additional document fragments. For performance reasons (since it’s possible that the view’s $el was attached to the DOM without the view knowing it), I’m populating the document fragment with content entirely in memory. This includes the addition of some data and calling .hide() on the fragment. I can manipulate the fragment with DOM-independent functions as much as I want at this point.

Once I’ve completed the rendering of the HTML content, I stuff it all in to the view’s $el. The $el is then attached to the DOM and I can begin using DOM-dependent methods.

I can also attach DOM level events to the fragments that I’ve generated. Since jQuery is turning our strings in to proper document fragments for me, DOM events are available. That means I can call methods like .click() and .blur() on the view’s $el.

 1 Backbone.View.extend({
 2   render: function(){
 3     // ... build the $el here
 4
 5     this.$el.click(function(e){
 6       // handle the click event here
 7     });
 8
 9   }
10 });

But I generally consider this to be an anti-pattern. There may be some cases where I need to manually attach events, and it can be done here in the render method. For the most part, though, I should be using Backbone’s declarative events on my views.

DOM Events And Simple Animations

Backbone’s View object abstracts a little bit of jQuery’s event system for me through the use of the declarative events.

 1 Backbone.View.extend({
 2   events: {
 3     "click": "showHide"
 4   },
 5
 6   showHide: function(){
 7     this.$("ul").slideToggle();
 8   },
 9
10   // render: function ...
11 });

Surprisingly, DOM events are partially DOM-independent. As I said above, I can add the events to the document fragments before they become part of the DOM. I can even trigger them manually without them being part of the DOM. In general, though, the DOM fires the events for me when the user interacts with the DOM in the manner that I’ve specified.

Having the user to fire DOM events through DOM interactions (clicks, blurs, changes, etc) is DOM-dependent, of course. The view must attach any HTML structure that it needs to the DOM before the user can interact with them, to fire these events. This is why I said that the events are partially DOM-independent. They can be attached to a document fragment, but they generally need to be in the real DOM for user interactions to occur.

Often when a user clicks or changes a DOM element, I want to respond to this by manipulating the DOM in a visual manner. For example, I might want to call .hide(‘slow’) on a portion of the view’s $el in order to hide some items on the screen with a simple animation. The above example shows this. When I click on the top level div, the child ul is shown or hidden using the “slideToggle” animation.

jQuery Plugins And UI Controls

There are a large number of jQuery UI controls available, including the popular jQueryUI suite, commercial products such as Kendo UI, and many open source projects that take advantage of jQuery’s infrastructure. I’ve used many different control suites and plugins with Backbone, and I have found that they generally integrate the same way.

Most jQuery based controls are partially DOM-independent. I can call the plugin method to get it started before the document fragment is attached to the DOM. Once the document fragment has been configured with the plugin’s code and additional structure, though, the plugin often becomes DOM-dependent. In addition to events, as discussed above, control suites and widgets are often visual in nature and an initialized plugin that is not attached to the DOM won’t be visible.

As an example of a control / plugin, I can convert a ul list in to a menu structure using Kendo UI. To do this, I can call .kendoMenu() during the render method of a view. Or, if I’m using a view layer such as the one developed in the previous chapters, in the onRender callback.

Given an HTML template like this:

1 <script type="text/html" id="menu-template">
2   <li>foo</li>
3   <li>bar</li>
4   <li>baz</li>
5 </script>

I can add the .kendoMenu() call like this:

 1 var MyView = Backbone.View.extend({
 2   tagName: "ul",
 3   template: "#menu-template",
 4
 5   onRender: function(){
 6     this.$el.kendoMenu();
 7   }
 8 });
 9
10 // ... somewhere else in the app
11 var view = new MyView();
12 view.render();
13 $("#someDiv").html(view.el);

Once the Kendo menu is configured, the view’s $el has to be attached to the DOM (if it isn’t already). When that happens, I’ll see the menu structure on screen.

DOM-Dependent UI Controls

There are plenty of jQuery controls and plugins that are entirely DOM-dependent, as well. With these controls, I could not initialize the plugin prior to the view’s $el being added to the DOM.

The “easy” solution to this is to have the view attach it’s “el” directly to the DOM in some fashion. But as I’ve talked about before, this can be a bad idea. Instead, it only takes a few extra lines of code to allow a callback method that be called after the view has been added to the DOM.

1 var AnotherView = Backbone.View.extend({
2   onShow: function(){
3     this.$el.kendoSplitter({
4       // splitter options go here
5     });
6   }
7 });

In this example, I’ve added a method to the view called onShow. This method contains the call to the Kendo UI Splitter, which is DOM-dependent. It’s important to note that the onShow method doesn’t get called from within the view, directly. This is because it’s not the view’s responsibility for adding itself to the DOM. This is the responsibility of the code that needs the view. For example:

1 var view = new AnotherView();
2 view.render();
3 $("#someDiv").html(view.$el);
4
5 if (_.isFunction(view.onShow)){
6   view.onShow();
7 }

The code that needs the view will instantiate it, call render and attach the resulting view.$el to the DOM. Next, it checks for the existence of an onShow method in the view. If that method does exist, it gets called. Since the code that is using the view knows that it has already added the view to the DOM, it knows when to call the onShow method. This allows me to write code that relies on DOM-dependent functionality without the view having to know if it has been added to the DOM or not.

Extracting The onShow Method Call

I’ve written this onShow method and the code to call it more times than I can count. It has become such a ubiquitous part of my code that I added the check for and call to the function to the Region object in MarionetteJS. Adding it here allows me to take advantage of the onShow semantics while making it easy for me to know when and where this method will be called.

Lessons Learned

Working with jQuery plugins can be simple and it can be frustrating at times. There are some tricks that can be used to generally keep it on the simple side, though. A method such as onShow and proper timing of this method being called can reduce the amount of complexity in an application by standardizing when and where jQuery plugins are initialized.

Understand Interactions And Timing

The DOM in an odd beast at times, and working with it at the right or wrong moment can spell the difference between success and failure for an app. It is important to understand when to do certain things in apps, based on the needs of the DOM and interactions with it.

Context Is King

The patterns and implementations that I’ve shown here are entirely contextual. There will be scenarios where some DOM-independent code should not be called until after the view’s “el” is part of the DOM, for example. Use your judgement, experience and trial-and-error with the various methods and functions that you have to call to get your behavior correct.

The use of a Backbone.View with jQuery code that manipulates the DOM creates a situation where a line of code may work in one spot for one view but need to be moved to another spot for another view. There are no silver bullets in software development. The context of the code being written must be accounted for at all times.

Use Existing Abstractions When Possible

Backbone has a lot of great abstractions and helpers built in to it. Taking advantage of these will help to reduce the amount of code that is needed without having to write additional abstractions. Take the time to read and understand the Backbone source code, so that the existing abstractions can be used to their full capabilities.

Chapter 7: Swapping Views In The DOM

Most small Backbone applications can get away with very small, simple methods of managing the DOM. Backbone.View implementations typically contain the majority of what is needed, so why not use them exclusively? As an application grows in size and complexity, though, a more modular application design become necessary. Different areas of functionality within an application should not be directly coupled to other, unrelated areas of functionality. When an application begins to move down this path, it becomes more difficult for Backbone.View to be the sole manager of the DOM content. Having hard coded references to page level DOM elements becomes unmaintainable. Every place in the application that has the DOM element reference is yet another place that has to be changed, if / when the DOM is changed. Fortunately, it is easy to create an object that can manage a DOM element and it’s displayed Backbone.View.

A Need To Change Out A View

I was working on a location management application for a client at one point. It started out with three distinct regions on the screen:

Navigation (a tree view)

Main content

An add/edit form

Once this was in place a new requirement came along: a complex search with search results. To implement this, I needed to modify the application’s user interface to swap out the grid and add/edit form out and put in a search results screen instead. The idea being that when the user does a search, the main content area will show the search results. The user can then go back to the location management aspect of the app whenever they need to, as well.

After a bit of searching and experimenting, I found a high level pattern that made this easy. I also realized that I had previously worked with, and implemented the core of this pattern without knowing it.

Microsoft Prism: Regions

Several years ago, Microsoft released a framework for it’s WPF and Silverlight runtimes, called Prism. This was a large scale composite application framework that people used to build well structured and decoupled apps in XAML. I never had a chance to use this framework directly, but I worked with a team of developers that did use it.

One of the things that I liked about what I saw in Prism was the way it used the idea of “regions” to compose the user interface. The gist of it is that you could define a visible area of the screen and build a layout for it without knowing what content was going to be displayed in it at runtime. Then at runtime, the application modules could register themselves to have content displayed in the various regions of the screen.

This pattern fits perfectly with the direction that my Backbone app were heading, so I decided to borrow the names and build my own version in JavaScript.

A Simple Region For Backbone

In Prism, a region is defined in the XAML markup. In web applications, we have HTML. Similarly, in XAML a region manager is code that you write in C# or other .NET languages. In a web app, though, a region manager is going to be JavaScript. Backbone.js provides a good separation between the markup and the code to run that markup through it’s Views, so I initially thought about going down this path for my regions. After a bit of thinking, though, I realized that I didn’t necessarily need a Backbone view. What I really need is a JavaScript object that do the following:

Represent an existing DOM node

Change out the contents of that DOM node

Call any required rendering and initialization for content views that will be displayed

Call any required cleanup for content views when they are removed

What I came up with as an initial pass at handling these needs, was the following (hard coded specifically to use a “#mainregion” element from the DOM):

 1 // Define a "Region" object that is hard coded
 2 // to manage the "#mainregion" DOM element
 3 Region = (function (Backbone, $) {
 4   var el = "#mainregion";
 5   var currentView;
 6   var region = {};
 7
 8   // A method to close the current view
 9   var closeView = function (view) {
10     if (view && view.remove) {
11       view.remove();
12     }
13   };
14
15   // A method to render and show a new view
16   var openView = function (view) {
17     view.render();
18     $(el).html(view.el);
19   };
20
21   // Export the API to show a view and
22   // close an existing view, if one is
23   // already in this DOM element
24   region.show = function (view) {
25     closeView(currentView);
26     currentView = view;
27     openView(currentView);
28   };
29
30   return region;
31 })(Backbone, jQuery);

Having this Region object allowed me to swap out the contents of the #mainregion DOM element without any of my views having to know about the DOM element that they were being displayed within. It also prevented the views from having to know about each other. There is now an intermediate object that knows about the view it is currently displaying, and can remove it when a new view needs to be displayed.

Extracting A Reusable Region Type

From the initial Region object, it was easy to extract a re-usable type that can be instantiated and have an el assigned to it as the element to manage.

 1 // Define a re-usable "Region" object
 2 var Region = (function (Backbone, $) {
 3
 4   // Define the Region constructor function
 5   // accept an object parameter with an `el`
 6   // to define the element to manage
 7   function R(options){
 8     this.el = options.el;
 9     this.currentView = undefined;
10   }
11
12   // extend the Region with the correct methods
13   _.extend(R.prototype, {
14
15     // A method to close the current view
16     closeView: function (view) {
17       if (view && view.remove) {
18         view.remove();
19       }
20     },
21
22     // A method to render and show a new view
23     openView: function (view) {
24       this.ensureEl();
25       view.render();
26       this.$el.html(view.el);
27     },
28
29     // ensure the element is available the
30     // first time it is used. cache it after that
31     ensureEl: function(){
32       if (this.$el){ return; }
33       this.$el = $(this.el);
34     },
35
36     // show a view and close an existing view,
37     // if one is already in this DOM element
38     show: function (view) {
39       this.closeView(this.currentView);
40       this.currentView = view;
41       this.openView(view);
42     }
43   });
44
45   // export the Region type so it can be used
46   return R;
47 })(Backbone, jQuery);

The Region can be used by creating instances with the new keyword, passing an object literal with an el specified:

1 var mainRegion = new Region({
2   el: "#mainregion"
3 });

Once I had this in place and started working with it more, I realized that there were a few other things that the Region could do for me.

Handing onShow Calls

In Chapter 3, I showed how to handle jQuery plugins that rely on the DOM, using an onShow method to know that the view is in the DOM. With the Region object in control of placing a View in the DOM, it makes sense for it to also be responsible for calling the onShow method.

 1 // show a view and close an existing view,
 2 // if one is already in this DOM element
 3 show: function (view) {
 4   this.closeView(this.currentView);
 5   this.currentView = view;
 6   this.openView(view);
 7
 8   // run the onShow method if it is found
 9   if (_.isFunction(view.onShow)){
10     view.onShow();
11   }
12 }

Adding this to the Region was easy and made the region that much more valuable. Now any time I need to work with a DOM-dependent plugin, I can add an onShow method and if I’m displaying the view with a Region object, it will be called at the appropriate time.

Lessons Learned

Building objects that encapsulate common processes can reduce the amount of code needed and provide opportunity to consolidate features in many cases. Looking outside of JavaScript and Backbone can provide insight and opportunity to solve problems in common ways, as well.

Beg, Borrow and Steal

JavaScript isn’t doing anything new with scalable, stateful application development. The vast majority of the patterns and practices that are being used to build Single Page Apps have been around for 20 or 30 years, in fact. It is important to understand the history of stateful application development, not just to avoid repeating the mistakes of the past. Understanding the past and even the current state and future of other languages and platforms allows us to properly beg, borrow and steal patterns and concepts.

In this case, I decided to borrow an idea from Microsoft’s Prism framework when it came time to manage swapping view instances in and out of the DOM. Having an existing codebase, documentation, example apps and other resources available made it easy for me to see how this worked and why. I was able to adapt the core concepts from a C#/XAML/Windows world in to the JavaScript world, with great success.

DRYing Up DOM References

The “Don’t Repeat Yourself” principle says that we should reduce duplication in code. This makes life as a developer easier by reducing the number of place that I have to change something. DOM references are no different in this regard - and may even be subject to more frequent change, creating a greater need to reduce the number of references to a given DOM element.

By introducing a Region object to manage the content of a specific DOM element, I was able to reduce the number of references to the “#mainregion” in my application. When (and I truly mean “when” - it happened, multiple times) the DOM element in question changed and I needed to update the selector that my application used, I only had to do it in one location instead throughout every file that needed to display content in that element.

Consolidating Needs

The Region object initially provided a way to manage the contents of a DOM element, but it quickly became apparent that it could do more than that. Since this was the object that knew precisely when a Backbone.View was being inserted in to the DOM, it made sense to have the Region check for and call the onShow method of a View instance. Similarly, the need to manage View cleanup became the responsibility of the Region because the Region was already handling showing and removing the views. It was a natural progression for the close and/or remove method of a Backbone.View to be called from the Region, when it was closing a view.

Make Assumptions, But Provide Fallbacks

Building a plugin or abstraction that takes advantage of another is usually very beneficial. Assumptions can be made about how certain objects will behave, allowing the combination of existing ideas building new ideas faster. But if the Backbone way of providing a flexible library where pieces can be used independently is to be maintained, fallback mechanisms should be provided when possible.

In the case of a Region, I can facilitate DOM dependent jQuery plugins by having the region call an onShow method of a view. Not every view is going to need this method, though, so I check to ensure the method is available before calling it.

Similarly, I can make assumptions about a close method being available on my view if I am using Regions and my own View layer. But if I want other developers to be able to take advantage of Regions without forcing them to use my View layer, I need to provide a fallback. Backbone.View has a built-in remove method and is a suitable fallback in this case. If a view instance does have a close method, I call that. If not, I call the remove method instead.

Chapter 8: Layout

COMING SOON! A chapter to outline how to combine a basic View definition with regions, to create a Layout - a view that is able to contain other views.

Part 3: Data And Meta-data

While views are often the first place that developers see boilerplate code, they are certainly not the last. Nearly every type that Backbone provides will have some form of boilerplate applied to it.

For example, many applications have a model or list of models that can be “selected” from a user interface. The app may need need to show a list of items - often in a table or grid layout - with a checkbox next to each item and have the app user select as many or as few of the items as needed, by checking the boxes. With at least one items selected, they can then perform some action on the selected items. This may be as simple as a bulk-delete, or may be more complex and specific to the application being created.

Part 2 will cover the creation of a plugin that allows models to be select, or “picked”. Collections will also be able to track the models that have been picked, as well. Finally, a method of mixing the functionality in to models and collections that doesn’t cause issues with method or attribute name collisions will be shown.

Theme And Variation

Naming things can be difficult and cause problems far beyond the actual name. Names often set a theme or set of expectations around the language used with the thing being named. In the first version of Part 2 of this book, a theme of “select” was chosen. This proved by be a bad idea for reasons described in Appendix E: Theme And Variation. In the end, the theme of “pick” was chosen to correct this set of problems.

Chapter 9: Pickable Models

A model should know whether or not it has been picked. The model should also provide methods for picking itself, and unpicking. Having this knowledge and these methods directly on the model reduces the amount of code in the views that are displaying the models. It also properly encapsulates the logic of picking / unpicking on to the objects that are being modified. Rather than keeping all of the data and logic surrounding the selection in the view instance, the view only needs to react to changes in the model’s state. The view can also call the appropriate method on the model based on user interaction with the checkbox on the view.

Options For Storing Picked State

There are a few options for storing the state of selection on a model: as part of the model’s attributes, as data attached directly to the model (outside of the attributes), or in a third party object with no data stores on the model directly.

The first option involves using the model’s get and set methods to store and retrieve the state of selection. The advantage of this is the existing storage mechanism for the selection state. Changing this state will also trigger “change” events that can be used by views or any other objects. The result is a reduction in the amount of code that needs to be written because the model is using existing functionality to facilitate the “picked” state. The downside to this is the data being stored with the model’s attributes. This might not be a problem if this state can be ignored by anything reading the data. However, the data is still there in the attributes. It will be sent to a back-end server when the model is saved, and it will be part of the model’s attributes for as long as the model is in memory.

The second option involves a little more code: store the state directly on the model and not in the attributes. The benefit is that the events can be customized to a higher degree, and the extra data is not found in the model’s attributes or .toJSON() call. The selection state is not sent to the server because its not part of the attributes. The model is not restricted to using “change” events, either. It can trigger “picked” and “unpicked” events, or any other event name desired. The downside is that there is more code to write. Methods to manage picking the models, triggering events, and storing the state will have to be added to the model.

The third option is a variation of the second, but requires more code, still. Creating a separate object to house the state of model selection can provide some benefit, though. It keeps the model clean of the selection state. It also allows any model to be selected or “picked”, whether or not it was originally designed for this purpose. The major downside is two-fold: the state is not stored in the model, and the methods to manipulate the state are not found on the model.

The choice between less code + attribute pollution, or more code without attribute pollution is not always clear. For this example, the idea of polluting the attributes seems to be the worse of the two, though. Having extra data hanging around the model’s attributes, is generally a bad idea. It pollutes the models with information specific to a single user experience or UI feature. The allure of being able to select any model - whether or not it was set up for this purpose - is great, as well. The creation of a plugin to manage the selection state is an option to reduce the overall boilerplate code for managing model selection. The problem of allowing a model to manage that state is solvable as well, and will be examined in chapter 10.

Backbone.Picky Namespace

To add the selection ability to a model or collection - or, in other words, to allow a user to pick which items they want - a new plugin will be created, and called “Backbone.Picky”. Naming the plugin with “Backbone.” is quite common. This convention gives any others developers using the plugin a clear understanding that this plugin is meant to be used with Backbone.

To get started, a namespace will be created for the new plugin.

1 Backbone.Picky = {};

This will serve as the namespace that all of the selectable model and collection objects and functionality will hang from.

The assumption is Backbone being an available object is fairly safe at this point. It does add a requirement of Backbone being loaded prior to this plugin, but that again is a safe assumption.

Picky.PickableModel

Rather than extending from Backbone.Model directly, a separate object will be added to the Picky namespace. This object will contain all of the functionality and data for the selectable models.

1 Backbone.Picky.PickableModel = function(model){
2   this.model = model;
3 };

This constructor function will create instances of the PickableModel object, with each instance managing the the model instance that is passed to it.

1 var myModel = new MyModel();
2 var pickable = new Backbone.Picky.PickableModel(myModel);

The PickableModel needs methods to pick and unpick the model, as well. As a simple first implementation, these methods only need to set a picked attribute on the model.

 1 _.extend(Backbone.Picky.PickableModel.prototype, {
 2
 3   pick: function(){
 4     this.model.picked = true;
 5   },
 6
 7   unpick: function(){
 8     this.model.picked = false;
 9   }
10
11 });

_.extend

The use of _.extend is a shortcut to add multiple methods and/or attributes to an existing object. It takes the first parameter as the target object and copies all of the methods and attributes from the remaining parameters to it.

When dealing with prototypes, this will make the method available to every instance of the type.

But these method implementations are very naive. There is more behavior that needs to be accounted for when picking or unpicking a model.

Picking a model not only needs to set the correct state, but also trigger an event from the model that says the model has been picked. To prevent infinite loops from multiple events from being triggered, this method should also check to see if the model is currently picked. If it is, don’t set the state or trigger the event again.

 1 _.extend(Backbone.Picky.PickableModel.prototype, {
 2
 3   pick: function(){
 4     if (this.model.picked){ return; }
 5
 6     this.model.picked = true;
 7     this.model.trigger("picked", this.model);
 8   },
 9
10   // ...
11 });

Unpicking a model should run the same basic logic, but in reverse. It should trigger an “unpicked” event, but only if the model is currently picked.

 1 _.extend(Backbone.Picky.PickableModel.prototype, {
 2   // ...
 3
 4   unpick: function(){
 5     if (!this.model.picked){ return; }
 6
 7     this.model.picked = false;
 8     this.model.trigger("unpicked", this.model);
 9   }
10 });

In both functions, JavaScript’s “truthiness” - or coercive nature of evaluation - is being taken advantage of in the guard clauses. If a model has just been created, calling pick will check for a picked attribute which won’t exist. The attribute evaluation will return undefined, which gets coerced in to a false value for the if statement. Similarly, the guard clause in the picked method will negate the coerced value if unpick is called on a model that does not have a picked attribute. Once the model has been picked, though, the attribute will exist and the guard clauses will no longer coerce the value.

Also note that the picked attribute is not being stored directly on the model. Rather, the instance of the SelectableModel is keeping track of this, which will provide more flexibility and options in how the SelectableModel instance is used.

With the basic implementation of a SelectableModel in place, it can be used in simple scenarios that do not require any interaction with other selected models or collections. (A more complex scenario covering collections and multiple selections will be covered shortly.)

Using A SelectableModel

The SelectableModel implementation cannot be used as a model directly. It does not extend from Backbone.Model and it does not provide the same API as a Model. Instead, it needs to be created as an object instance of its own.

1 var model = new Backbone.Model();
2 var pickable = new Backbone.Picky.PickableModel(model);

The pickable object can be managed on its own, with no requirement for the model to know anything about whether or not it is pickable. Passing the selectable object to a view allows the view to pick and unpick the model. The events that are triggered would have to be bound from the selectable.model or a reference to the original model, though. This would look a little odd if the selectable is passed in as the model for a view. It would be better to pass it in as a separate option. But it would be best to have the view encapsulate the knowledge of needing the model to be pickable entirely.

 1 // Build a PickableView that wraps a model
 2 // in a PickableModel instance
 3 var PickableView = BBPlug.ModelView.extend({
 4
 5   events: {
 6     "change .pick": "togglePick",
 7   },
 8
 9   initialize: function(options){
10     // wrap the view's model in a pickable
11     this.pickable = new Backbone.Picky.PickableModel(this.model);
12   },
13
14   togglePick: function(e){
15     // toggle picking the model, based on
16     // the current state of the pickable
17     if (this.pickable.picked){
18       this.pickable.unpick();
19 		} else {
20       this.pickable.pick();
21     }
22   }
23 });

With the PickableView definition in place, a new instance can be created, passing in the model without having to do anything particularly special to it. The view itself has encapsulated the code that is needed to make the model pickable. The DOM event configuration looks for a ‘.pick’ element - a checkbox, most likely. Changing this checkbox (checking or un-checking it) will toggle the PickableModel’s state.

The end result is that any model of any type can be used, and that model will be pickable from the view.

1 // define a new model, but don't do anything to it
2 var MyModel = Backbone.Model.extend({});
3
4 // create a model and view instance
5 var myModel = new MyModel();
6 var view = new SelectableView({
7   model: myModel
8 });

The model that is passed in to this view is now pickable. This is not because the model had any changes applied to it, but because the view wrapped it in a PickableModel instance.

The “toggle” Boilerplate

You may have noticed that the PickableView provides a method to toggle the model being picked or not. This is exactly the kind of boilerplate code that should be avoided in projects, as it will be copy & pasted from view to view, project to project. I’ve left a .toggle() function out of the PickableModel implementation, though, to keep this chapter short. But it would be a good idea for you, dear reader, to add this method to your implementation.

Lessons Learned

There are several things that the Backbone.Picky plugin did differently than the previous BBPlug add-on. Most notably is the namespace, but also the ability to create a selectable object on its own instead of having to extend from a base model or collection. Several of these lessons may apply to models and collection specifically, but many of them can be more broadly applicable to creating plugins and writing well structure Backbone applications.

Build Add-Ons As Separate Objects

It’s often tempting to create specialized versions of objects that can be extended from directly. Backbone provides a .extend method on every one of it’s types, after all. In the first part of this book, specialized view types were extended from Backbone.View, as well. But this can be problematic. With models, it is generally a bad idea to extend from Backbone.Model to create a specialized type. There are far too many possibilities for extensions and add-ons, and forcing a developer to extend from your model type prevents them from using any other model type as the base.

Using The Backbone Namespace

Using a custom namespace for an object helps to keep the global object space of the JavaScript runtime clean. However, having a handful of plugins that each create their own global object can still pollute more than is desired. Its common for Backbone plugins to use the Backbone namespace to help reduce this pollution and also to give the developer using the plugin more of a direct sense that this plugin is meant to be used exclusively with Backbone.

When using the Backbone namespace for a plugin, though, be sure to create a child namespace that hangs off of it instead of placing the plugin’s objects directly on the Backbone namespace. Backbone.Picky is a good example of this, as it creates a child namespace called Picky, which contains all of the objects for the plugin.

The Principle Of Least Surprise

The principle of least surprise says that the code being used should look and work in a manner that is least surprising. That is, a method’s name should be consistent with the behavior of the method. In the case of Backbone.Picky, the use of the SelectableModel can either enforce or violate this principle. In the case of using the selectable object directly in a view, as either the model or a separate object passed in as the options, the use of the functionality provided may be somewhat odd or “surprising”. By mixing the functionality directly in to a model instance, though, access to the selectable functionality is more consistent with the expectations of developers writing views.

Encapsulate Features And Wrappers

It is generally reasonable to ask another developer to send a specific type of object to a method parameter. This is how software development and method calls work, after all. Passing the wrong type to the wrong parameter usually causes bad things to happen. But there are situations where this becomes an undue burden to developers - when a feature’s method needs a type that is specific to the feature, asking a developer to wrap their object in this type can be problematic. Encapsulating features and feature-specific wrappers in to method calls allows for flexibility and eases the burden on developers using the feature.

Chapter 10: Pickable Collections

Adding support for picking multiple models is needed for “select all” and “deselect all” Scenarios. Knowing which models have been picked allows action to be taken on the them, or prevented if some criteria is not met for an action. A user interface can enable and disable various actions based on zero, one or multiple items having been picked.

Multi-Pick Collections

To get rolling, add a MultiPickCollection object to Backbone.Picky. This one is be responsible for tracking models that have been picked and handling pick all / unpick all functionality.

The basic object definition looks similar to that of the PickableModel - a constructor function and an extension of the prototype to provide the methods needed.

1 // Constructor function to create MultiPickCollections
2 Backbone.Picky.MultiPickCollection = function(collection){
3   this.collection = collection;
4   this.picked = {};
5 };

In addition to the storage of the collection from which models will be selected, the instance has a picked attribute to hold the list of picked models. This is an object literal attribute, used like a hash - a key/value pair - to make addition and removal of items easier.

The methods on the MultiPickCollection can be assigned to the prototype. Methods don’t need to be assigned to each instance because they work with the state of the instance they are called from. With prototypal inheritance and the way that JavaScript manages the context in which methods are called (the dreaded this operator), calling a prototype method on an instance will in the method working with the instance’ data.

1 _.extend(Backbone.Picky.MultiPickCollection.prototype, {
2
3   pickAll: function(){},
4
5   unpickAll: function(){},
6
7   togglePickAll: function(){}
8
9 });

Each of these method names and parameter lists should provide insight in to what the method does with the collection. Once again, these method names are following the theme of “picking” models with methods for picking all, none or toggling all models in the collection.

So, why not add picked to the list of methods and attributes that are extended on to the prototype? Why add it in the constructor, instead of on the prototype?

Adding picked to the prototype would cause unexpected and unwanted behavior due to the way _.extend works. When an object is extended, the methods and attributes from the extension are copied on to the target. That is, the name of the attribute is assigned to the value of the same attribute, but the assignment is done on the target.

Since the value of each attribute is assigned to the target, assigning the picked attribute to the prototype would result in every instance sharing the same list. In this case, the list shouldn’t be shared. Each instance should have its own list of models. Assigning the attribute in the constructor function instead of on the prototype means every instance gets its own list.

Listening For Model Picks

Picking models can happen one of two ways - through the PickableModel, or through the MultiPickCollection. In either case, the MultiPickCollection needs to be notified so it can keep track of the models that have been picked. The easiest way to handle this is to listen to the “picked” event on the Collection instance. This works because every time a model triggers an event the collection it belongs to also triggers the same event. The collection’s version of the event also includes the model, which means the MultiPickCollection will be able to track the picked models, easily.

In the constructor function for the MultiPickCollection, then, you will need to add an event handler for the collection’s “picked” event. The MultiPickCollection doesn’t know how to listen to events, though. To fix this, use _.extend to add Backbone.Events in to the MultiPickCollection, first.

1 _.extend(Backbone.Picky.MultiPickCollection.prototype, Backbone.Events, {
2   // ... existing methods here
3
4 });

Backbone.Events is a simple object literal in the Backbone code base. It is meant to be used as a mix-in in this manner. By extending the prototype of MultiPickCollection, all instances will be able to the event handler and event triggering methods, as needed.

With that in place, set up the collection’s “picked” event handler to store a reference to the picked model.

 1 Backbone.Picky.MultiPickCollection = function(collection){
 2   this.collection = collection;
 3   this.picked = {};
 4
 5   // When a model is picked, it triggers a "picked" event.
 6   // The owner collection forwards model events, so listen
 7   // to the collection's events and capture all picked models
 8   this.listenTo(this.collection, "picked", function(model){
 9     this.picked[model.cid] = model;
10   });
11 };

The models are stored in the picked list by cid - the “client id” of the model. This id is guaranteed to be unique amongst all model instances. Unfortunately, though, it will be different between two model instances that have the same data - including the same “id” field. A more robust storage mechanism may want to account for this, but this simple “hash” usage of an object literal is good enough for now.

An Object Is Not A Hash

There are some limitations to using an object as a hash. Guillermo Rausch has written about why an object is not a hash and makes some compelling arguments. You should take the time to read this article and understand the limitations that you may run in to, and decide whether or not this technique is right for your application.

Similarly, when a model is “unpicked”, it should be removed from the picked list. Add this event handler directly underneath of the “picked” handler.

1   this.listenTo(this.collection, "unpicked", function(model){
2     delete this.picked[model.cid];
3   });

This will remove the model from the picked list by deleting the reference. Note that this only deletes the reference, and does not do any kind of “delete” API call or anything like that.

The Dangers Of “delete”

You should be aware that using the “delete” keyword tends to put browsers in to “slow mode” for objects. That is, the browser will treat the object differently than normal, as it has to re-examine the ever-changing landscape of the object that is having attributes added and deleted.

In all honesty, though, I wouldn’t worry about this too much. I have never seen this have a noticeable affect on performance, personally. You should, however, measure the performance difference between deleting an attribute and just setting it to null or undefined, in your own applications.

Cleaning Up Event Listeners

In the first part of this book, you wrote View code that used the listenTo method to listen to events. The event handlers in the MultiPickCollection constructor also use this method of listening. Unlike views, though, the MultiPickCollection does not automatically clean up the event handlers for you.

Backbone.View has a remove method that calls stopListening and unbinds the events. To get the same memory management and event cleanup in the MultiPickCollection, then, you’ll want to add a similar method. And once again, naming becomes important.

It’s common among JavaScript frameworks and objects to use destroy or close for these end-of-life method names. The choice often comes down to personal preference and past experience. Developers coming from a .NET and C# background, for example, tend to choose close. Other developers - especially those grounded in JavaScript patterns and idioms - tend to choose destroy. The choice is easier than looking at your own background or preferences, though. Use the semantics and common patterns to pick.

A method name of “destroy” already exists on Backbone.Model. It has the behavioral and semantic meaning of “destroy this model from the data store”. Choosing this name would imply the same behavior and semantics for the MultiPickCollection. This is bad since this object and method will not destroy any data in any backing data store. The choice is clear, then: close.

Add a close method to the MultiPickCollection’s prototype, along side the other instance methods. In this method, call the stopListening method of the instance. This will clean up all of the event listeners that were set up using the listenTo method.

1 _.extend(Backbone.Picky.MultiPickCollection, {
2   // … existing methods
3
4   close: function(){
5     this.stopListening();
6     this.trigger("close");
7   }
8
9 });

In addition to the stopListening call, the close method is triggering a “close” event. This one extra line of code offers a lot of flexibility for applications that are using a MultiPickCollection. Knowing when an object is being closed can often make life easier for memory management, app shut down, and other needs.

listenTo vs on

It should be noted that the listenTo method is not a panacea of solutions for memory management related to events. There are times when it makes more sense to use the on method instead. For more information on when to use which method, see Appendix A: Managing Events As Relationships.

The “pickAll” and “unpickAll” Methods

The pickAll and unpickAll methods loop through the list of models in the collection, and trigger a “picked” or “unpicked” event respectively.

 1 pickAll: function(){
 2   this.collection.each(function(model){
 3     model.trigger("picked");
 4   });
 5 },
 6
 7 unpickAll: function(){
 8   this.collection.each(function(model){
 9     model.trigger("unpicked");
10   });
11 },

Each of these methods iterates the collection and picks or unpicked the model as needed. But wait… notice that these methods trigger the “picked” and “unpicked” events for the models - the same as the PickableModel from Chapter 8. Why duplicate this? Why not use a PickableModel here and not have to duplicate code?

Necessary Duplication… For Now

Let’s say you want to have the MultiPickCollection call the “pick” method for each model instead. How are you going to do that? PickableModel is the object that contains this method, and you don’t have a PickableModel for these models. Sure, you could create one for each of the models as you’re iterating over them. But where would you store them? Or would you just toss them out after they’ve done their job? Or, you could try to find the existing PickableModel instance for each of the models… but where would this come from? You would need some sort of global registry or locator for them. That would likely be more code and trouble than it’s worth.

This is a real problem, honestly. You don’t want to duplicate the code of triggering these events in both the PickableModel and MultiPickCollection. But you also don’t want to have to write crazy-glue-code to make things work properly.

For now, the best answer is to to duplicate the events, unfortunately. Having this duplication (at least for the time being) allows the PickableModel and MultiPickCollection to work independently, but still allows the MultiPickCollection to respond to PickableModel triggered events.

You can create a MultiPickCollection without worrying about whether or not the models in the collection have a PickableModel associated.

1 var myCollection = new MyCollection([/* ... model data ... */]);
2
3 var mpc = new MultiPickCollection(myCollection);
4 mpc.pickAll();

The MultiPickCollection works just fine on its own. If you happen to have a PickableModel for a given model, though, and this PickableModel has its .pick() method called, then the MultiPickCollection instance will still receive the “picked” event and still capture the model as being picked.

 1 var m1 = new MyModel();
 2 var pm1 = new PickableModel(m1);
 3 // ...
 4 var mN = new MyModel();
 5 var pmN = new PickableModel(mN);
 6
 7 var myCollection = new MyCollection([m1, /* ... */, mN]);
 8 var mpc = new MultiPickCollection(myCollection);
 9
10 m1.pick();

In this example, the PickableModel and MultiPickCollection are interacting through the use of the events.

Still, this isn’t the greatest use of code in that it is causing a couple of lines of duplication. In the next chapter, though, methods of integrating the PickableModel and MultiPickCollection will be discussed. This will offer at least one possible solution to this problem - though the cost vs benefit ratio may not be entirely stable.

The “togglePickAll” Method

The togglePickAll method uses a combination of selectAll and deselectAll, based on the current count of picked models, according to these rules:

If no models are picked, pick all of them

If at least one or more, and less than all models are picked, pick all of them

If all models are picked, unpick all of them

The first two rules could easily be combined in to a single rule, but leaving them separated makes the behavior a little more explicit. The code, however, does not have to be as explicit as long as the documentation and/or behavioral specification (i.e. “unit tests”) for this method is explicit.

 1   togglePickAll: function(){
 2     var pickedLength = _.size(this.picked);
 3     var collectionLength = this.collection.length;
 4
 5     if (pickedLength === collectionLength){
 6       this.unpickAll();
 7     } else {
 8       this.pickAll();
 9     }
10   }

Underscore’s size method is used to get the number of picked items stored in the picked attribute. This is the object literal used as a key/value store, and object literals not provide a length attribute. Underscore compensates for this by counting the number of attributes on the objects.

Once the length of picked models is determined, it is checked against the length of the collection. If the two lengths are the same, then that means all models are currently picked - so, unpick all of them. If the two lengths are not the same, then there are unpicked models and they need to be picked.

Handling Removed Models

There’s a problem in the MultiPickCollection, exposed by the togglePickAll method. If a collection has all models picked and one those models is removed from the collection, the list of picked models will still contain the removed model. This will cause the count to be inaccurate, potentially breaking the togglePickAll behavior.

To fix this, the model remove must be accounted for. Add an event handler for the collection’s “remove” event to do this. The event handler should be set up in the constructor, along with the other events.

1 Backbone.Picky.MultiPickCollection = function(collection){
2   // ... existing code
3
4   this.listenTo(this.collection, "remove", function(model){
5     delete this.picked[model.cid];
6   });
7 };

Yes, this is code duplication from the “unpicked” event - good catch. And, fortunately, this is the kind of duplication that can easily be rectified. Add a “_remove” method to the MultiPickCollection and have it delete the model from the picked list. And while you’re at it, add an “_add” method to add a model to the list.

 1 _.extend(Backbone.Picky.MultiPickCollection, {
 2   // ... existing methods
 3
 4   _add: function(model){
 5     this.picked[model.cid] = model;
 6   },
 7
 8   _remove: function(model){
 9     delete this.picked[model.cid];
10   }
11 });

Now update the constructor function to call these methods instead of having the inline callback functions.

1 Backbone.Picky.MultiPickCollection = function(collection){
2   this.collection = collection;
3   this.picked = {};
4
5   this.listenTo(this.collection, "picked", this._add);
6   this.listenTo(this.collection, "unpicked", this._remove);
7   this.listenTo(this.collection, "remove", this._remove);
8 };

The use of an “_” in front of the method name is not anything technical or syntax specific to JavaScript or Backbone applications. This is common notation within JavaScript idioms, though, signifying a “private” method or attribute. That is, when you see a method or attribute that starts with an “_” name, you should treat it like it is private within the object. Methods and attributes named like this are subject to change without notice, because it is expected that you will not touch them directly… ever.

Using A MultiPickCollection

With the MultiPickCollection implemented, an application can easily provide the ability to pick and unpick models in a list. Similar to the PickableView in Chapter 8, a MultiPickView can be created

 1 var MyItemView = BBPlug.ItemView.extend({/* … */});
 2
 3 var MultiPickCollection = BBPlug.CollectionView.extend({
 4   itemView: MyItemView,
 5
 6   initialize: function(){
 7     // build the MultiPickCollection
 8     this.multiPick = new  Backbone.Picky.MultiPickCollection(this.collection);
 9   },
10
11   // DOM event handlers
12
13   pickNoneClicked: function(e){
14     e.preventDefault();
15     this.multiPick.unpickAll();
16   },
17
18   pickAllClicked: function(e){
19     e.preventDefault();
20     this.multiPick.pickAll();
21   },
22
23   togglePickAllClicked: function(e){
24     e.preventDefault();
25     this.multiPick.togglePickAll();
26   }
27 });

Since the calls to pickAll, unpickAll and togglePickAll each trigger the correct event, the event handlers for these will be fired at the correct time. The view will be updated with the correct buttons being enabled and disabled, or however the view should handle this situation. This makes for a great reduction in the amount of code that an individual view has to write, to facilitate the “select all” and “select none” functionality that it needs.

Homework: “all”, “none” and “some” Events

You may find yourself wanting to receive events from the MultiPickCollection, telling you when all, some or no models have been picked. As homework for this chapter, work on adding events that will tell you this. Trigger a “picked:all”, “picked:none” or “picked:some” event at the appropriate time, and have the MultiPickView listen to these events and update the UI accordingly.

Lessons Learned

Creating a pickable collection introduces a number of interesting challenges. The behavior and semantics introduced with the PickableModel need to be maintained, but the API and implementation are very different at the same time. Working with the “pickable” theme and examining existing methods names on the underlying objects provided a guide to building this extension.

Adding Events To Your Object

Backbone.Events is a simple object literal that is meant to be used as a mixin for other objects. All of Backbone’s objects mix this in, and your objects can as well. Any time you need the ability to trigger or listen to events in an object, just mix the Backbone.Events in to your object.

Listening To Events

Backbone.Events provides two mechanisms for listening to events: the .on and the .listenTo methods. Understanding when to use which can help lead to better memory management and fewer zombie problems. There is no rule or absolute for which to use when, though. Each situation must be evaluated for the needs of the objects that are involved and the lifecycle of those objects.

Extending A Prototype vs Augmenting An Instance

The use of _.extend to add methods to prototypes is powerful. It allows types to quickly and easily be augmented. But this isn’t always what you want. There are times when each object instance needs to be augmented with data or instance-specific configuration. Adding default and empty values to an instance can be done in a constructor function, ensuring the object instance has the basic configuration that it needs in order to work correctly.

Sometimes Duplication Is OK

There will be times when the desire to keep your code DRY - “Don’t Repeat Yourself” - will cause more problems than it’s worth. The DRY principle is important and duplicating code does tend to lead to problems. But this is not a hard and fast rule. Like any other principle, it is more of a guiding light - a direction that needs to be examined in order to determine its appropriateness.

In the case of duplicating the “picked” and “unpicked” events between PickableModel and MultiPickCollection, the DRY principle was out-weighed by the complexity that would have been added to keep it DRY. Adding layers of complexity and obscurity in API or object requirements is a cost that should be paid in this case.

Iterate For Edge Cases

No matter how hard you try to determine the exact functionality of code before we sit down and write it, you will never get it 100% complete until you start writing it. Business logic and application workflow are often subtle in nature, with edge cases hanging around places that are very unexpected. As code is implemented, these edge cases may present themselves. When this happens, iterate - take the time to evaluate the edge case and determine if it needs to be handled.

In the case of togglePickAll, the edge case of a MultiPickModel having a picked size that is inconsistent with the number of models in the collection came up. This wasn’t noticed until the code in the togglePickAll method was written, though. Once the potential problem was identified, though, additional code was written to account for this. The end result is a more robust MultiPickCollection, capable of handling additional scenarios.

Use Callback Functions, Not Inline Functions

While it is easy and tempting to use nested, inline functions for event handlers, this tends to lead to very bad code. It causes duplication and leads toward the dreaded arrow-of-doom code with nesting so deep, you can’t see how the code flow anymore. Instead of writing inline and nested event handler functions, then, use function reference. Call out to another named function and keep the code flat and well organized.

In the case of the MultiPickCollection, a _remove method handles both “unpicked” and “remove” events of the collection. This reduced both the complexity in the constructor function, and removed code duplication between the event handlers.

Use _methodNames For “Private” Members

JavaScript does not have access modifiers built in to the language at this point. It is possible to create privacy by using function scope to hide variables, but this isn’t always reasonable to do. Often times a method that is attached to an object needs to be considered “private” even though it cannot have an access modifier that enforces this. In this situation, use an “_” as the first character of the method name. This is a common practice in JavaScript to say, “This method should be considered private. Do not call it directly.”

Chapter 11: Making The Model And Collection Pickable

Unfinished Chapter

Note: This chapter is incomplete or contains known errors and inconsistencies. Further work is being done to finish this chapter. All feedback is welcome, still.

This chapter will talk about making a Backbone.Model and Backbone.Collection pickable, directly, by using some mixin patterns to add the functionality of a PickableModel or PickableCollection.

See Appendix D for further discussion and description of mixin patterns, beyond the application noted in this chapter.

Lessons Learned

Chapter 12: A LocalStorage Adapter

COMING SOON! A chapter on the backbone.localstorage plugin, written by the plugin author, Jerome Gravel-Niquet!

This chapter will include lessons learned in building a replacement for Backbone.sync, while still allowing the original sync method to work with server APIs when needed.

A Sneak Peak

Lots of real-world apps need to persist data in some form of storage. This is normally achieved by creating a server which acts as an interface between a database and your client. Sadly, this adds a ton of dependencies and complexity. People are less likely to contribute to your project if itâ€™s difficult to setup.

When I built Backbone Todos, I didnâ€™t want to add any dependencies of the sort.

…

Overriding Backbone.sync properly

Taken from the Backbone documentation (emphasis mine): > Backbone.sync is the function that Backbone calls every time it attempts to read or save a model to the server. By default, it uses jQuery.ajax to make a RESTful JSON request and returns a jqXHR. You can override it in order to use a different persistence strategy, such as WebSockets, XML transport, or Local Storage.

People often override Backbone.sync to accommodate custom headers/params needed to use with their server.

Overriding is too destructive for a proper Backbone plugin. In Backbone.localStorage, we check for a property on the model or collection (quite simply localStorage) and then override the Backbone.sync function with a small function which checks for that property and calls either the old Backbone.sync or a new pimped one. Like so:

 1 Backbone.ajaxSync = Backbone.sync;
 2
 3 Backbone.getSyncMethod = function(model) {
 4   if(model.localStorage || (model.collection && model.collection.localStorage)) {
 5     return Backbone.localSync;
 6   }
 7
 8   return Backbone.ajaxSync;
 9 };
10
11 // Override 'Backbone.sync' to default to localSync,
12 // the original 'Backbone.sync' is still available in 'Backbone.ajaxSync'
13 Backbone.sync = function(method, model, options) {
14   return Backbone.getSyncMethod(model).apply(this, [method, model, options]);
15 };

Part 4: Application Infrastructure

Beyond views, past models and collections, and after the rest of Backbone has been used within the boundaries it creates, there is still a lot of room for growth. The building blocks that Backbone provides are essential in building well structured applications, well organized code, and maintainable feature sets. But these building blocks don’t provide everything you need to build scalable JavaScript application.

Scalability in this case is not a discussion of how many users can run the code at any given time. Since this a browser based JavaScript, it is reasonable to expect that an infinite number of users can use the app at the same time. After all, the browser that runs the code is limited to the current user. It doesn’t have to support more than that. Scalability in browser based JavaScript and Backbone apps, then, is the discussion of features. How well can an application be extended to add new features? How much effort does it take to re-organize the features in order to correct the workflow and process? Will all users be given all code for all features, when the log in to the app? Or can the features delivered to the browser be limited to what the user should see?

Part 3 will dive in to these discussions and create the basic infrastructure needed for scaling Backbone applications by feature set. New building blocks will be created to facilitate feature separation and communication between them. An application bootstrap will create the needed organization for application startup. It will also provide the means by which features can be separated and loaded as needed. Finally, a method of segmenting and organizing code within larger features will be created. This will allow features and functional areas of the application to be re-organized a modified as needed, in a much easier manner.

Chapter 13: 3rd Party Events, Commands, And Requests

One of the core tenets of building a Backbone application of any size, is using an event-driven approach. Everything in the Backbone way of writing code and integrating the different object types relies on events. They are used to communicate changes in models and collections, DOM changes and user interaction, and more. But events are not the only communication means that a scalable application needs.

There are times when the code needs to look beyond events - beyond a statement of “something happened” - and start to look at statements like “do this” and “do this, and let me know”. To venture in to these other realms of communication, additional patterns are needed - patterns such as commands and a request/response system.

Event Aggregators

Events are an integral part of Backbone because they provide a simple yet powerful way of connecting application pieces. One object - a listener - can be notified of something happening from another object - a publisher. The listening object can then respond appropriately and get things done.

The vast majority of events in a Backbone application are set up so that the object listening to an event has a direct reference to the object triggering the event. A Model -> View event relationship is a common example:

 1 var SomeView = Backbone.View.extend({
 2   initialize: function(){
 3
 4     // bind to an even from a model, to which
 5     // I have a direct reference
 6     this.listenTo(this.model, "change:foo", function(){
 7       // do stuff
 8     });
 9
10   },
11   // ...
12 })

When it comes down to it, building a solid Backbone application requires a fundamental understanding of events and how events can be used to great advantage. But events must be viewed beyond two objects that have a direct reference or relationship. It is not always possible for the listener to have a reference to the publisher.

3rd Party Events

When an application begins to grow in size and complexity, it is reasonable for every object that handles an event to have a reference to the object that publishes an event. Having every object reference each other for events creates a tangled mess of object dependencies. It very tightly couples implementation details of the application’s features to each other by crossing boundaries that should not be crossed. This creates a bad situation where changing one part of an application will cause ripple effects that require changes in other parts of the app.

To avoid this, a third party object can be used. An Event Aggregator is an intermediate object that allows other objects to publish events, and objects interested those events to subscribe to them without needing a reference to the publishing object.

Backbone has an event aggregator built in to it: the Backbone object itself. This object has Backbone.Events mixed in to it, allowing easy event aggregation without having to write any additional code.

A simple use of an event aggregator is view to view communication.

 1 var FooView = Backbone.View.extend({
 2   events: {
 3     "click .doIt": "doItClicked"
 4   },
 5
 6   doItClicked: function(e){
 7     e.preventDefault();
 8
 9     // trigger an event through the
10     // built-in event aggregator
11     Backbone.trigger("do:it");
12
13   }
14 });
15
16 var BarView = Backbone.View.extend({
17   initialize: function(){
18
19     // subscribe to the "do:it" event from
20     // the built in event aggregator
21     this.listenTo(Backbone, "do:it", this.doIt);
22   },
23
24   doIt: function(){
25     // do stuff here
26   }
27 });

In this case, the two views need to communicate, but they do not have a direct reference to each other already. When that situation arises, an event aggregator can be used to facilitate the communication. As long as both of the views have a reference to the same event aggregator instance, they can communicate via that 3rd party.

DIY Event Aggregators

There are times when an event aggregator other than the one built in to Backbone is needed. For example, there may be a sub-application within a larger application. Allowing components with the sub-application to communicate with each other is important. It may also be important to prevent other parts of the over-all application from listening in on this communication. To handle this situation, context-specific event aggregators can be created with only one line of code:

var eventAgg = _.extend({}, Backbone.Events);

Now I can use the eventAgg object anywhere that has a reference to it. If I keep this object’s use within a sub-application, then I have effectively created an internal communications mechanism for that sub-app.

An EventAggregator Type

Having to re-write this one line of code to create new aggregators does get a little tedious, after a while. And although it is simple, it has very low semantic meaning. The only part of this line that tells me the intent is the variable name that is assigned to the result.

To fix the tedium of copy & paste and the nondescript nature of the code, I can build a simple EventAggregator type that can be instantiated:

1 // define an event aggregator
2 var EventAggregator = function(){
3   _.extend(this, Backbone.Events);
4 };
5
6 // use the event aggregator type
7 var eventAgg = new EventAggregator();

Having a constructor function (an object type) named EventAggregator solves both the copy & paste and ambiguity problem. It allows me to create an instance of an object type that has a clear semantic meaning, and it prevents me from having to remember the slightly odd looking syntax of extending an object literal with Backbone.Events.

No Silver Bullets

Event aggregators are an important concept and are a necessary part of building a scalable Backbone application. However, it doesn’t make sense to replace all event bindings with an event aggregator. The primary use case for them is when the object that needs to handle an event does not have a natural relationship or reference to the object that triggers the event. For example, a view that is binding to a model’s events does not need to use an event aggregator because the view already has a reference to the model. A menu view, though, may want to use an event aggregator to say a menu item was clicked. This would allow other parts of the application to handle the menu click without needing a reference to the menu.

Commands

While events are powerful, and 3rd party events through an Event Aggregator even more so, events have a specific semantic that comes with them: “something happened”. Unfortunately, I see a lot of semantic violations for events. It’s quite common to find code like this, for example:

1 foo.on("save:model", function(model){
2   model.save(/* options ... */);
3 });

If I look at the first line of this code, I might think “oh, good. The model was saved. I can go do…” But on looking at the second line, I see that the model has not yet been saved. Instead, this event is being used to tell another object to go save the model. The semantics of “something happened” have been changed and this code actually says “go do this”.

Building A Command System

Now there isn’t anything wrong with saying “go do this”. The problem with the above code is that the wrong semantics are being used within Backbone’s event system. “Go do this” is the semantic meaning of a command, not an event.

I’m going to build a very simple command system to handle the “go do this” semantic, then.

 1 // Create a Commands type to handle commands
 2 var Commands = function(){
 3   this._handlers = {};
 4 };
 5
 6 _.extend(Commands.prototype, {
 7
 8   // Handle a specific command by calling
 9   // the specified handler function
10   handle: function(command, handler, context){
11     this._handlers[command] = {
12       handler: handler,
13       context: context
14     };
15   },
16
17   // Execute the specified command, passing
18   // the provided parameters to the handler
19   execute: function(command, params){
20     params = Array.prototype.slice.call(arguments, 1);
21     var config = this._handlers[command];
22     if (config){
23       config.handler.call(config.context, params);
24     }
25   }
26 });

With this in place, a command handler can be registered and the command can be properly executed, passing any needed parameters along with the execution call.

1 var cmds = new Commands();
2
3 cmds.handle("save:model", function(model){
4   model.save(/* options ... */);
5 });

To execute the command, the code that was previously triggering an event can now call the cmds.execute method:

1 foo.doSomething = function(){
2   cmds.execute("save:model", someModel);
3 }

ES6 “…params”

Many languages - like Ruby or C#, for example - provide a way to get all parameters passed in to a method, after a certain position. This is often referred to as a “splat” (Ruby) or params list (C#). In the current version of the JavaScript standard - ECMAScript 5 (or ES5) - there is no way of getting an array of all parameters after a current position. ECMAScript 6 is introducing a “rest parameters” parameter that will facilitate this: function(foo, ...bar). Until the majority of browsers and other JavaScript runtimes support this feature, though, the Array.slice method can be used to facilitate the same feature.

Why Have A Command System?

I often get asked why I bother having a command system in my apps. After all, triggering an event works perfectly fine… most of the time… at least, until it doesn’t. But it technically works. I always answer, “semantics”. When it comes down to it, semantics are important. As my friend Sharon Cichelli says,

Semantics will continue to be important until we find a way to communicate in something other than language.

Semantics play a role far beyond spoken words. They touch every part of the software that we write, including the code. And there are several semantically important things to note in the code for commands.

First, the Commands object has introduced a 3rd party to situation, much like an event aggregator. The introduction of a 3rd party provides an additional level of decoupling that is often needed. It allows the command handler to be registered from one area of the application, and the command execution to happen in another area entirely.

Second, the semantics of commands have been maintained in this code. Instead of having an event that is triggered, forcing a developer to look through the code to find a handler that is actually doing what the event said, this code is saying “go do this”. This difference alone can save hours of headache and days of debugging, wondering why an event is causing some such behavior, and why another event handler is getting fired before that behavior.

“Spent the day figuring out busted tests and trying to decipher other peoplesâ€™ intentions in code.” - Chris Hartjes @grmpyprogrammer

Lastly, the same semantics provide a more meaningful and semantically correct API for the Commands objects. Rather than re-use the on and trigger method names from events, the command system provides a handle and execute method. These method names help to maintain the semantics of commands, and provide distinction between events and commands at an API level.

Request/Response

Having a command system in place can be a liberating experience once the “AHA!” moment comes around, regarding the semantic difference between an event and a command. But, sometimes a command isn’t enough. Sometimes I need to do something more than just say “go do this.” Sometimes I need to say, “go do this, and let me know.” In this scenario, I’m dealing with a need to send a request and get a response.

Building A Request/Response System

The basics of a Request/Response system are very similar to that of a Command system. In fact, I’ve often used Commands as the basis for Request/Response. This does tend to lead to some muddy water, though. In spite of the requirement difference between Commands and Request/Response being so small - just the addition of “and let me know” - the semantic difference can be significant. A method name like handle might seem appropriate for requests, but renaming this to respondTo provides an much more rich set of semantics in this situation. Other, similar changes can be made in order to provide a very meaningful API, in spite of the similarities in implementation.

 1 // Create a RequestResponse type to handle requests
 2 var RequestResponse = function(){
 3   this._handlers = {};
 4 };
 5
 6 _.extend(RequestResponse.prototype, {
 7
 8   // Handle a specific request by calling
 9   // the specified handler function, and
10   // returning the result
11   respondTo: function(request, handler, context){
12     this._handlers[request] = {
13       handler: handler,
14       context: context
15     };
16   },
17
18   // Request the specified information, passing
19   // the provided parameters to the responder
20   request: function(request, params){
21     params = Array.prototype.slice.call(arguments, 1);
22     var config = this._handlers[request];
23     if (config){
24       return config.responder.call(config.context, params);
25     }
26   }
27 });

With the RequestResponse type in place, it can be used to facilitate scenarios where one object needs information from another object, and does not need to know which object can respond to the request.

 1 var reqRes = new RequestResponse();
 2
 3 reqRes.respondTo("price:check", function(product){
 4   var currentPrice = someService.lookupPrice(product.id);
 5   return currentPrice;
 6 });
 7
 8 var ProductView = BBPlug.ItemView.extend({
 9   template: "#product-template",
10
11   serializeData: function(){
12     var json = this.model.toJSON();
13     json.price = reqRes.request("price:check", this);
14     return json;
15   }
16 });

In this case, I’m using the BBPlug.ItemView from earlier chapters to build a view for a product. The data from the product is not quite complete when the view is created, though. I need to reach out and get the latest price for the product and I do so using the request/response system. Once the data is returned, the view can be rendered.

Why Build A Request/Response System?

The same core reasons for building a Command system also apply to a Request/Response system. The additional requirement of “and let me know”, however, adds a new dynamic: return values.

When it comes to the implementation, the only real difference between a Command system and a Request/Response system is that the Request/Response system has a return statement for the handler execution. But this one single return statement is part of a larger semantic understanding. When I say request("price:check"), there is value in understanding that a request has a response. I expect to receive a response because the semantics of “request” include a response. By comparison, execute("price:check") doesn’t have the same semantics. It just says “go do a price check” but doesn’t say anything about a response.

Lessons Learned

Scaling Backbone applications introduces a new set of problems, including that of naming things and creating proper semantics in those names. These problems exist within even the smallest of applications, of course, but they become more pronounced as an application grows.

Create Your Own Types

Backbone provides a foundation of building blocks, but it does not provide every type of object and every piece of functionality needed to build scalable applications. Understanding this, and recognizing the need to build additional object types on top of Backbone is important. Creating additional, specialized object types allows an application’s infrastructure to provide much needed functionality, reducing the amount of code the application has, over-all.

The view types that were created in the first two chapters extended directly from Backbone.View. This was the right thing to do because these specialized view types were providing implementations for common functionality within Backbone views. In the case of the EventAggregator, the functionality was there but it wasn’t available in the needed form for all the desired scenarios. Creating a custom object type and mixing in a little bit of Backbone’s provided functionality gives applications new building blocks - more specialized, and more capable.

Not Every Type Has To Build Off Backbone

The Commands and RequestResponse types were natural extensions that came from recognizing the semantics of an event vs command, etc. But in building these add-ons, none of Backbone’s building blocks were used. This creates a scenario where the code written may be useful outside of Backbone applications. It also shows that we have the freedom to move beyond the core pieces of Backbone and create our own building blocks for our systems’ needs.

Isolate Sub-Systems

As applications begin to grow in size and complexity, it becomes more likely that communication mechanisms will repeat names of events, commands and requests. To avoid potential problems with two independent sub-systems using the same names, create sub-system specific instances of event aggregators, command and request/response systems. This allows each sub-system to have it’s own communications bus, freely choosing what names it wants to use.

Semantics Are Important

With more code and more functionality to keep track of in growing applications, it is important to reduce the amount of overhead in a developer’s mind. Proper naming and semantic meaning are important for achieving this goal.

Being able to look at code that was written by someone else - or even written by the person reading it again 3 weeks later - and having an immediate understanding through the semantics of intention revealing names is an easy way to improve developer productivity. By creating an EventAggregator type, the intended use of the code becomes clear without having to read the fine details and usage.

Small Semantic Change, Big API Change

Seemingly unimportant or minuscule differences in requirements or semantics can have very significant effects on a system. It’s these subtleties that separate a generalized, high level difference

The requirements differences between a command and a request may be small, but they have created a large semantic and API difference. Instead of just copying the API for Commands in to the Request/Response system, new method names were chosen to reflect the semantics. This allowed the proper semantic meaning to be carried throughout the entire Request/Response system. It would also allow for the Commands and Request/Response systems to vary independently of each other. That is, the Request/Response system would not be forced to take an API change when the command system changes, or vice-versa.

Similarities Can Be Deceiving

The number of similarities between two sets of requirements can often be deceiving. Our desire, as humans, to see congruence and conformity often leads to a poor understanding of what we are actually looking at. It’s important, therefore, to look at the underlying intent and meaning - the semantics of the two things that are similar. It may just be that the similarities are only skin-deep, and that the semantics are pointing the code in two different directions.

Chapter 14: Boot-strapping A Backbone Application

Languages like C/C++, C#, Java and others typically have a main method or similar, as the entry point for an application’s code. This is the method that gets called when the application is boot-strapped for execution (however that is done - an executable from a shell, running a GUI application in windows, starting a web service, etc). In JavaScript, there isn’t a single defined entry point for code. You write code in a .js file, reference it from the HTML file, and the code gets evaluated and executed in the order that it is included in the page. Evaluation and execution happens in the same order: top-down, first-loaded is first-executed. For small applications this may be fine. But when a Backbone application starts to grow beyond a few simple views and models, something more robust is needed.

An Application Object

The typical starting point for a JavaScript app is an ‘Application’ object, which acts as a boot-strapper for the code execution. The first version of this is often an object literal that has an “init” method or “start” method - a single method to call to start the app.

 1 // <app.js>
 2
 3 var app = {
 4   someFeature: {
 5     views: {},
 6     models: {},
 7     controllers: {}
 8   },
 9   anotherFeature: {},
10
11   start: function(){
12     someFeature.init();
13     anotherFeature.init();
14     Backbone.history.start();
15   }
16 };
17
18 // <someFeature.js>
19
20 app.someFeature.init = function(){
21   // do things to start up this feature, here
22 };

The object literal may set up some initial namespaces for various parts of the app by including nested object literals. The “start” method would run initialization for data, collections, and views, and set up a router, for example. This path, a simple object literal with a “start” method, is useful for small application. But for anything substantial, it becomes constraining and problematic, quickly.

Having one “start” method means that it must know about every part of the application that needs to be initialized. This leads to a monolithic method, at best. Worse, though, is that it often leads to large amount of complicated and convoluted logic to try and figure out which parts of the app need to be initialized, when.

To solve the boot-strapping and initialization problem, an application object should allow multiple initialization methods to be registered, and have them run from a single call to a start method.

An Extensible Application

An object literal is a simple way to start, but it would be more flexible if this were an object that could be extended and instantiated as needed. To do that, you’ll define a constructor function to create new object instances. But you don’t want to throw away any investment that you have in your object literal’s structure, either. Fortunately, it’s easy to handle both needs. Allow the object literal to be passed in to the Application’s constructor function. Then extend the Application instance with the object literal.

1 // An Application object constructor function.
2 function Application(options){
3   _.extend(this, options);
4 }

Now you can pass the original object literal in to the constructor of the new Application type.

 1 // <app.js>
 2 var app = new Application({
 3   someFeature: {
 4     views: {},
 5     models: {},
 6     controllers: {}
 7   },
 8   anotherFeature: {},
 9
10   start: function(){
11     someFeature.init();
12     anotherFeature.init();
13     Backbone.history.start();
14   }
15 });

All of the methods and values from the object literal will be copied to the app instance, making them available as if the app object has not been changed. The result is that any existing code that relied on the structure of the object literal will still work. With a new type in place, though, you can create instances that have more behavior than an object literal. The Application type can be extended to include additional features, such as the ability to register initializer methods.

Adding Initializers

Initializers are functions that get called to initialize - or start up - other areas and feature sets of an application. They allow the Application object to be in control of when the features start, but allow each feature to be in control of how they start.

Before you get to the initializers, extend the Application prototype with Backbone.Events. This will come in handy when you get to the point where the Application is being started, allowing additional flexibility in the use of the Application object.

1 _.extend(Application.prototype, Backbone.Events, {
2   // Application instance methods go here
3 });

Next, create an addInitializer method and have it accept a callback function as a parameter. You’ll need a place to store the callback functions, so add an _initializers array to the Application instance, inside of the constructor function.

 1 // An Application object constructor function.
 2 function Application(options){
 3   // extend this instance with all the options provided
 4   _.extend(this, options);
 5
 6   // a place to store initializer functions
 7   this._initializers = [];
 8 }
 9
10 // Application instance methods go here
11 _.extend(Application.prototype, Backbone.Events, {
12
13   // Add an initializer, which will be run when the start
14   // method is called on the Application instance. The order
15   // of execution is not guaranteed.
16   addInitializer: function(initializer){
17     this._initializers.push(initializer);
18   }
19 });

This code isn’t much to look at, but it provides a lot of flexibility in use. It also brings up a couple of questions, though.

Why Add The _initializers In The Constructor?

The _initializers are added in the constructor function and not extended on to the Application.prototype due to the way JavaScript passed objects around by reference.

If the initializers array were defined on the Application prototype, each instance of an Application would reference the same array. In a project where only one Application instance is used, this wouldn’t be a big deal. But this would cause serious problems in unit testing or in applications that have multiple Application instances. You don’t want the email app running the initializers for the to-do list, for example.

By adding the _initializers array in the constructor function, you will have a unique array for each Application instance.

Why Not Expose initializers Directly?

Why should you write a function called addInitializer when you could expose the array directly and just call app.initializers.push(…) directly?

The short answer is encapsulation.

Exposing the internal data structures of an object can lead to bad situations. Developers using the object and data structure may try to do things that would cause problems with the intended use.

Exposing the array would force developers to know about the API and semantics of arrays. It would also force them to jump outside of their current mode of thinking when working with the array vs the Application API. This breaks concentration and flow every time they have to switch between the semantics of “I’m working on an Application object” to “I’m working with an array”, and back.

Lastly, exposing the internal data structure will cause problems when you need to change that data structure. If someone is using the array in their code and you change it to an object literal with key: value pairs, the behavior and semantics will change dramatically. This leads to broken code and frustrated developers.

Keeping the _initializers wrapped up in an API method helps to prevent these problems. It encapsulates the internal structure, providing an API that is consistent with the semantics of the object being used. It allows you to change the data structure as needed, and helps to reduce bugs by creating an intention revealing API.

Executing The Initializers

With the initializers stored in the Application instance, you need a way to execute them. Add a start method to the Application and have it loop through the initializers, calling them.

 1 _.extend(Application.prototype, Backbone.Events, {
 2   // … existing methods
 3
 4   start: function(args){
 5     var init, i;
 6
 7     // get the arguments passed to the start method
 8     // and slice them in to an array so they can
 9     // be passed to the initializers
10     args = Array.prototype.slice.call(arguments);
11
12     // get the # of initializers
13     var length = this._initializers.length;
14
15     // loop and execute
16     for (i=0, i<length, i++){
17       init = this._initializers[i];
18
19       // execute the initializer with the
20       // context set to the application,
21       // passing args along for the ride
22       init.apply(this, args);
23
24     }
25
26   }
27 });

It’s useful to provide arguments for the initializer functions that have been added. The easiest way to do this is to pass those arguments to the start function directly, forwarding them to each of the initializer functions. The start method above does exactly this by slicing the arguments object in to a proper array and then passing the args to the init function in the loop.

Each of the initializer functions will be executed in the loop, with the context (the this argument) of the initializer function set to the Application instance.

Context And Prototypes

For more information about manage context (this) in JavaScript, see my screencast on Context In JavaScript.

In addition to context, though, be aware that mixing the tools to manipulate context with prototypal inheritance in JavaScript can result is unexpected bugs. For an introduction to the problem and a description of one or two ways to manage this, see my screencast on When Context And Prototypes Collide.

Using Initializers And Starting The App

Now that the Application object can have initializers added, and they can be started, it’s time to finish the conversion from the old application object literal.

Adding Initializers

The original object literal had it’s own start method. When the Application instance is wrapped around that object literal, the start method of the object literal overrides the one on the Application prototype. Initializers set up with the addInitializer function will never get run if this method is left on the object literal. Fortunately, the new initializer setup is intended to be a replacement for the existing start method. The Application instance, and the other feature files, can be re-written like this:

1 // <app.js>
2 var app = new Application({
3   someFeature: {
4     views: {},
5     models: {},
6     controllers: {}
7   },
8   anotherFeature: {}
9 };

1 // <someFeature.js>
2 app.addInitializer(function(){
3   // do things to start up this feature, here
4 });

1 // <anotherFeature.js>
2 app.addInitializer(function(){
3   // init and run this feature, from here
4 });

Each of the individual feature files now has the initialization code completely contained within itself. Better yet, the “app.js” file is no longer tied directly to each feature’s init method. This means you can add as many files as you need in your application - each with its own initializer - without touching the Application’s start method again.

Starting The Application

The last thing to do is start the application. This can be done from anywhere in the code. Just call app.start() and all of the registered initializers will run. It’s common to use a jQuery DOMReady callback function to start the app, for example. And this is often done from within the DOM, at the very bottom of the HTML - that way the rest of the scripts have a chance to be loaded before the app starts.

 1 <html>
 2   <head>
 3     <!-- … head stuff, here, including script tags as needed -->
 4     <script src="/js/app.js"></script>
 5     <script src="/js/someFeature.js"></script>
 6     <script src="/js/anotherFeature.js"></script>
 7   </head>
 8   <body>
 9     <!-- … the rest of the page … -->
10
11     <script>
12     // start the app when the DOM is ready
13     $(function(){
14       app.start();
15     });
16     </script>
17   </body>
18 </html>

There is one potential problem left in the initializers, though. Initializers that are added after app.start() has been called won’t be executed. This can happen if you are lazy-loading JavaScript files when a user starts new features in the app (think “GMail” where switching from mail to contacts loads new scripts and data from the server). To make this work, you would have to call the start method again, which would be another problem - all of the initializers would be run again, duplicating any work that was done previously. You might try to work around this by .pop()ing the initializers from the array in the start method. This would work to a point, but you would still have to call the .start method multiple times.

A better solution to this problem is to use jQuery’s deferred objects, which are a variant of JavaScript Promises.

Promising To Run Initializers

According to the CommonJS wiki, promises “provide a well-defined interface for interacting with an object that represents the result of an action that is performed asynchronously, and may or may not be finished at any given point in time.”

That is, a promise is an object that “promises” to run some functionality at some point in the future. The exact point in time is not known, but as long as the promise is “resolved”, then all of the registered functions will be executed.

You can add a callback function to a promise at any time, and know that the callback will be executed. Even if the callback function is added after the promise has been resolved, the callback will still be executed. This is where the “promise” name comes from - the promise to execute on or after resolution.

The initializers that you set up in the Application object are very close in purpose to the way a promise works. They are a set of callback functions that execute when the application is started. This set up seems to fit the intent of promises perfectly. Adding an initializer will add a the callback to a promise, and starting the Application will resolve the promise.

Converting Initializers To Promises

Now is the time that having encapsulated the initializers storage behind an addInitializer method pays off. Converting the Application’s initializer storage from an array to a promise object requires no change in the public API of the Application. It only requires a few changes in the implementation.

Start by replacing the _initializers array with a jQuery Deferred instance (jQuery Deferred objects are a variant of Promises, providing the same core features and intent).

1 // An Application object constructor function.
2 function Application(options){
3   // extend this instance with all the options provided
4   _.extend(this, options);
5
6   // a place to store initializer functions
7   this._initializers = $.Deferred();
8 }

Now change the addInitializer method to store the callback function inside of the new _initializers object.

1 addInitializer: function(initializer){
2   this._initializers.done(initializer);
3 }

The last change to make is to resolve the deferred object when the application starts.

 1 start: function(args){
 2   // get the complete args list as an array
 3   args = Array.prototype.slice.call(arguments);
 4
 5   // resolve the initializers promise
 6   this._initializers.resolveWith(this, args);
 7
 8   // trigger the start event
 9   this.trigger("start", args);
10 }

The promise handles all of the callback execution for you - no more loops, and a lot less code! The start function has gone from not quite ten lines of code plus a dozen lines of comments, down to three lines of code and comments each. But most beneficial aspect of this change is that an initializer can now be added after the application is started, and it will still be executed.

 1 var app = new Application();
 2
 3 app.addInitializer(function(){
 4   console.log("I was added before the app was started.");
 5 });
 6
 7 app.start();
 8
 9 app.addInitializer(function(){
10   console.log("I was added after the app started!");
11 });

The output of both log statements will be shown, because the promise has been resolved in the start method. With the promise already resolved, any additional callbacks that are added will be executed relatively quickly (if not immediately). This lets you lazy-load JavaScript files as needed - each with their own call to app.addInitializer - and have a guarantee that they will be initialized.

Starting Routers

The Application’s initializers provide a powerful and flexible way to organize the initialization code for an app. The ability to load scripts that add initializers at a later time is also very powerful. But this isn’t all that a boot-strapper object needs to do.

For example, it’s common for large applications to have multiple Backbone.Router instances. But where do you put the call to Backbone.history.start()? You don’t need, or want, to call this after each router instance is created. But if you put it in an Application initializer, there no guarantee that all (or any) routers will be available when the history is started.

One solution is to trigger a “start” event from the Application’s start method. If you trigger this event after all of the initializers have been run, and each of your routers are instantiated in an initializer, you’ll have everything ready to go when Backbone’s history is started.

1 _.extend(Application.prototype, Backbone.Events, {
2   // … existing methods
3
4   start: function(args){
5     // … existing code
6
7     this.trigger("start", args);
8   }
9 });

Pass the same args array along to the “start” event. Then you can run code with the same args available, after all of the initializers have been fired.

Now add an even handler to your Application and start the history, there.

1 var app = new Application({
2   // … existing code
3 });
4
5 app.on("start", function(args){
6   if (Backbone.history){
7     Backbone.history.start();
8   }
9 });

The if checks to see if there is a Backbone.history object available. If no router instances have been created, it won’t exist. If at least one router has been defined, though, it will be available. Since you can’t call the start method if there isn’t a history object, so it’s a good idea to add this check in place.

If you find yourself writing this same “start” event handler in most of your applications, you might consider adding the history start call directly to the Application’s start method.

 1 start: function(args){
 2   // get the complete args list as an array
 3   args = Array.prototype.slice.call(arguments);
 4
 5   // resolve the initializers promise
 6   this._initializers.resolveWith(this, args);
 7
 8   // trigger the start event
 9   this.trigger("start", args);
10
11   // start the routers, if any are defined
12   if (Backbone.history){
13     Backbone.history.start();
14   }
15 }

Now you’ll never have to worry about starting routers again. Just start the app and you’ll know that any router you created in your initializers (or elsewhere, before the app is started) will be started, too.

Lessons Learned

Codifying an object from a concept or loosely implemented feature set can introduce a new world of freedom, flexibility and opportunity. Creating an Application object that can be extended, can migrate an existing object literal, and provide the ability to run initializer functions is an important aspects of scaling Backbone applications (or JavaScript in general). It allows you to have a single point of entry for the application, while allowing each area of the application to initialize itself correctly.

Let The Feature Own Its Initialization

Having a single start method for a simple application works well. Moving beyond small or simple, though, it quickly falls apart. By providing a method of registering initializer functions, the act of starting an application can be decoupled from the functions that run when the application starts. This allows each feature or area of functionality within an application to be in complete control of its initialization. If a feature knows that it should not be available, it does not need to register its initializer with the application.

Promises, Promises

Promises are powerful objects that can add a lot of flexibility when used appropriately. They provide a mechanism for handling return values when the time of return is completely unknown. Taking advantage of this can lead to many new opportunities and problems solved.

In the case of the Application initializers, switching from a simple array based storage to a jQuery Deferred (promise) provided several benefits. In addition to simplified code, this change allowed for initializers to be executed no matter when they were added. If an initializer is added before the application is started, the initializer is held, waiting for the app to start. If an initializer is added after the application is started, the promise executes the initializer immediately because the promise has already been resolved. This allows additional features and functional areas of an application to be loaded as needed, instead of requiring all features and files to be pre-loaded before starting the application.

Create Migration Paths

No one wants to adopt yet another all-or-nothing framework when they are looking at fixing or improving an existing application’s code base. Providing a migration path that does not require a complete rewrite of the system will increase the adoption rate of a new tool or framework significantly. If developers can simply plug in the new tool and start to use it where it adds immediate value, the will. Over time, the framework should show continued areas of added value that can be reached in incremental and non-intrusive manners.

By providing an Application object that accepts an object literal, and extends all of the methods and attributes from that object literal on to the Application itself, developers are given an opportunity to incrementally improve their own code. An existing investment in an object literal can be leveraged in the migration to the new Application object without massive changes. Once the first step is taken, the next step of migrating from a single .start method, out to many initializer methods, becomes apparent. This migration strategy allows applications to grow in to your large-scale framework, instead of requiring a re-write.

Don’t Limit Apps To Backbone’s Constructs

Code, libraries and add-ons that support general JavaScript development can often be very useful in Backbone app. And, in fact, tools and techniques from outside of Backbone should be employed. Limiting an application to only the constructs that Backbone provides will directly limit the usefulness of code and hamper a developer’s ability to create a clean, well structured system. The application initializers are a good example of how an abstraction can be built to work with any type of JavaScript application. There is no requirement in the code or in the intended purpose of these initializers, that says they can only be used with Backbone application. This same code base could be re-used across any number of JavaScript libraries and frameworks.

And remember: a Backbone application is a JavaScript application. Use all of the power, flexibility and capabilities that JavaScript provides.

Encapsulation Is More Than Just Theory

It is often easy to expose data structures as part of a public API. This allows other developers to do what they want with that data structure, and abdicates a lot of responsibility from you, the designer of the API. This is not a good thing, by any stretch of the imagination. Providing a clean and clear API for an object or type provides many benefits found in proper encapsulation. It protects internal data structures from unwanted and abusive use. It allows the data structure to change while the API remains in tact. And it allows a developer that is using the API to keep their thought process on that API. They will not have to do mental context switching between your object’s API and semantics, and the API and semantics of the data structure that your object happens to use.

JavaScript And Object References

JavaScript treats primitive types as by-value references. That is, a primitive will be copied between variables that are assigned to the same value. Non-primitive types, on the other hand, are always treated as by-reference. Assign a non-primitive type to multiple variables, and subsequent modification of any one of those variables will be reflected in all of the variables that are assigned.

When designing a JavaScript type, this is an important distinction to understand. If you assigned the _initializers to the prototype of the Application, then all instances of an Application would have the same initializers. By assigning the _initializers inside of the Application’s constructor function, though, this problem is avoided. The use of this._initializers = ... as the assignment guarantees a unique initializer set for each instance of an Application.

Chapter 15: Application Workflow

Unfinished Chapter

Note: This chapter is incomplete or contains known errors and inconsistencies. Further work is being done to finish this chapter. All feedback is welcome, still.

It is unfortunately common to have very poorly defined and constructed workflow in JavaScript and Backbone applications. A significant amount of time is spent creating new and re-usable View and Model types, and plugins and add-ons for them. But, this critical area of application workflow is typically overlooked. Rather than modeling workflow explicitly, applications tend to have the workflow scattered through other objects within an application. When one the application needs to move from one view to the next, the first view will call the second view directly. This path leads toward a mess of tightly coupled concerns, and a brittle and fragile system that is dependent entirely on the implementation details. Worse yet, to understand the higher level workflow and concept, the implementation details must be examined. This makes it very hard to understand the workflow, as the detail of each part tends to hide the high level flow.

A Poorly Constructed Workflow

For example, you might have a human resources application that allows you to add a new employee and select a manager for the employee. After entering a name and email address, we would show the form to select the manager. When the user clicks save, we create the employee. A crude, but all too common implementation of this workflow might look something like this:

 1 EmployeeInfoForm = Backbone.View.extend({
 2   events: {
 3     "click .next": "nextClicked"
 4   },
 5
 6   nextClicked: function(e){
 7     e.preventDefault();
 8
 9     var data = {
10       name: this.$(".name").val(),
11       email: this.$(".email").val()
12     };
13
14     var employee = new Employee(data);
15
16     this.selectManager(employee);
17   },
18
19   selectManager: function(employee){
20     var view = new SelectManagerForm({
21       model: employee
22     });
23     view.render();
24     $(".wizard").show(view.el);
25   },
26
27   // ...
28   render: function(){ ... }
29   // ... etc
30 });
31
32 SelectManagerForm = Backbone.View.extend({
33   events: {
34     "click .save": "saveClicked"
35   },
36
37   saveClicked: function(e){
38     e.preventDefault();
39
40     var managerId = this.$(".manager").val();
41     this.model.set({managerId: managerId});
42
43     this.model.save();
44     // do something to close the wizard and move on
45   },
46
47   // ...
48   render: function() { ... }
49   // ... etc
50 });

Can you quickly and easily describe the workflow in this example? If you can, it’s likely because you spent time looking at the implementation details of both views in order to see what’s going on and why.

Too Many Concerns

There are at least two different concerns mixed in to each of the objects in the above code. And those concerns have been split apart in some rather un-natural ways at that.

The first concern is the high level workflow:

Enter employee info

Select manager

Create employee

The second concern is the implementation detail of each view, which includes (in aggregate):

Show the EmployeeInfoForm

Allow the user to enter a name and email address

When “next” is clicked, gather the name and email address of the employee.

Then show the SelectManagerForm with a list of possible managers to select from.

When “save” is clicked, grab the selected manager

Then take all of the employee information and create a new employee record on the server

There’s potential for further decision points and branching in this workflow, which have not been accounted for, as well. What happens when the user hits cancel on the first screen? Or on the second? What about invalid email address validation? If you start adding in all of those steps to the list of implementation details, this list of steps to follow is going to get out of hand very quickly.

By implementing both the high level workflow and the implementation detail in the views, thee ability to see the high level workflow at a glance has been destroyed. This will cause problems for developers working with this code.

Imagine coming back to this code after even a few days away. It will be difficult to see what’s going on, to know if the workflow has changed since the last time you worked on it, and to see exactly where the changes were made - in the workflow, or in the implementation details.

Model Explicit Workflow

What we want to do, instead, is get back to that high level workflow with fewer bullet points and very little text in each point. But we don’t want to have to dig through all of the implementation details in order to get to it. We want to see the high level workflow in our code, separated from the implementation details. This makes it easier to change the workflow and to change any specific implementation detail without having to rework the entire workflow.

Wouldn’t it be nice if we could write this code, for example:

 1 var orgChart = {
 2
 3   addNewEmployee: function(){
 4     var employeeDetail = this.getEmployeeDetail();
 5     employeeDetail.on("complete", function(employee){
 6
 7       var managerSelector = this.selectManager(employee);
 8       managerSelector.on("save", function(employee){
 9         employee.save();
10       });
11
12     });
13   },
14
15   // ...
16 }

In this pseudo-code example, we can more clearly see the high level workflow. When we complete the employee info, we move on to the selecting a manager. When that completes, we save the employee with the data that we had entered. It all looks very clean and simple. We could even add in some of the secondary and third level workflow without creating too much mess. And more importantly, we could get rid of some of the nested callbacks with better patterns and function separation.

 1 var orgChart = {
 2
 3   addNewEmployee: function(){
 4     var that = this;
 5
 6     var employeeDetail = this.getEmployeeDetail();
 7     employeeDetail.on("complete", function(employee){
 8
 9       var managerSelector = that.selectManager(employee);
10       managerSelector.on("save", function(employee){
11         employee.save();
12       });
13
14     });
15   },
16
17   getEmployeeDetail: function(){
18     var form = new EmployeeDetailForm();
19     form.render();
20     $("#wizard").html(form.el);
21     return form;
22   },
23
24   selectManager: function(employee){
25     var form = new SelectManagerForm({
26       model: employee
27     });
28     form.render();
29     $("#wizard").html(form.el);
30     return form;
31   }
32 }
33
34
35 // implementation details for EmployeeDetailForm go here
36
37 // implementation details for SelectManagerForm go here
38
39 // implementation details for Employee model go here

I’ve obviously omitted some of the details of the views and model, but you get the idea.

The Challenge Of Workflow Objects

Everything has a price, right? But the price for this is fairly small. You will end up with a few more objects and a few more methods to keep track of. There’s a mild overhead associated with this in the world of browser based JavaScript, but that’s likely to be so small that you won’t notice.

The real cost, though, is that you’re going to have to learn new implementation patterns and styles of development in order to get this working, and that takes time. Sure, looking at an example like this is easy. But it’s a simple example and a simple implementation. When you get down to actually trying to write this style of code for yourself, in your project, with your 20 variations on the flow through the application, it will get more complicated, quickly. And there’s no simple answer for this complication in design, other than to say that you need to learn to break down the larger workflow in to smaller pieces that can look as simple as this one.

In the end, making an effort to explicitly model your workflow in your application is important. It really doesn’t matter what language your writing your code in. I’ve shown these examples in JavaScript and Backbone because that’s what I’m using on a daily basis at this point. But I’ve been applying these same rules to C#/.NET, Ruby and other languages for years. The principles are the same, it’s just the implementation specifics that change.

Lessons Learned

There are a number of benefits to writing code like this. It’s easy to see the high level workflow. We don’t have to worry about all of the implementation details for each of the views or the model when dealing with the workflow. We can change any of the individual view implementations when we need to, without affecting the rest of the workflow (as long as the view conforms to the protocol that the workflow defines). And there’s probably a handful of other benefits, as well.

Workflow Should Be Understandable At A Glance

The largest single benefit of writing code like this, is being able to see the workflow at a glance. 6 months from now – or if you’re like me, 6 hours from now – you won’t remember that you have to trace through 5 different Views and three different custom objects and models, in order to piece together the workflow that you spun together in the sample at the very top of this post. But if you have a workflow as simple as the one that we just saw, where the workflow is more explicit within a higher level method, separated from the implementation details… well, then you’re more likely to pick up the code and understand the workflow quickly.

Learn To Recognize Concerns, So They Can Be Separated

Recognizing different types of concerns in code is not always easy. It takes experience to know when two things are part of the same concern, or are actually two separate concerns. Drawing a line in the sand between the high level workflow and implementation detail for that workflow is a good place to start. Separating these concerns allows you to modify how the work flows vs how the details of each step are implemented.

The Dependency Inversion Principle

Be careful not to fall in to the trap of “some of the implementation details changed, so the workflow has to change now”. This is a dangerous path that leads to the dark side of code - tightly coupled spaghetti mess. Remember the Dependency Inversion Principle which states that details should depend on policy.

In the case of workflow, the workflow itself is the policy. It is the guidance that tells each step what it must look like from an API perspective. The workflow determines the API of each in the process - how to call a given step to run it, how to get any needed response from that step, what to do with that response, etc. Each individual step - the detail of the workflow - is then only responsible for the detail of that one step, and never any other steps.

Chapter 16 - Application Components

Unfinished Chapter

Note: This chapter is incomplete or contains known errors and inconsistencies. Further work is being done to finish this chapter. All feedback is welcome, still.

Workflow is an important concept, as Chapter 13 showed. Managing it as an explicit construct helps to clarify code. But workflow is not a singular thing within an application. It does not exist at only one layer or level of code. Workflow is used to manage the interactions between any number of related objects at any level in an application. Workflow objects even coordinate other workflow objects, when needed.

As applications grow and features need to be loaded and unloaded, the workflow that runs the feature will need to be started and stopped. You don’t want to leave too many workflow objects up and running, after all. Each of them would take up just a little more memory and probably hold on to additional objects such as views, collections and models, etc.

When you start breaking workflow down in to smaller and smaller pieces, you will begin to define individual components within the application and a given workflow. A screen that encapsulates email, for example, may be composed of one larger workflow to manage the process of reading email. But within that one larger workflow that will likely be smaller pieces - components - that are composed in to the larger flow.

What Is A “Component”?

There are a lot of different definitions of “component” floating around these days. For the purposes of this book, a generalized definition will be borrowed from the up-coming W3C standard for Web Components, and from frameworks such as AngularJS which provide a way to build component based applications.

Components are a combination of visual portions of the application and the logic and processing of that visualization. They encapsulate a small feature or sub-set of a feature in a manner that allows the component to be wired together with other components, creating a larger feature set or functional area of an application. They have at least one view with some amount of logic and process (a.k.a. “workflow”).

Web Components

For more information on Web Components, see this work-in-progress document from the W3C. AngularJS can be found at AngularJS.org.

A Email App Example

A typical email app has several distinct areas of the application’s screen. There is a list of categories or labels, a list of email to show for a given mail box, a search or filter box, and an individual email view, for example. Each of these - and likely additional areas of functionality on the screen - can be composed in to small workflow objects as components of the larger email work flow.

The classic example of GMail illustrates all of these basic components, and many more.

GMail App

The primary email screen shows a list of categories or labels to the left, a list of email to the right, a search screen at the top, filters, chat sessions, and much more.

GMail component sections

Each of these areas of functionality can be broken down in to separate components that can then be orchestrated to created a more functional system. This orchestration happens through an API that each of the components exposes, with a higher level workflow (as discussed in the previous chapter) controlling all of the individual components.

Building A Component

Defining a Components start like most other objects - with a constructor function. Components have a visual element to them, so you will need a way to manage where the component is displayed. You could pass a jQuery selector in to the constructor function, and possibly duplicate a lot of code that you wrote in Chapter 6. Or, use the Region object from that chapter and allow a region instance to be passed in to the component’s constructor.

1 var Component = function(options){
2   this.options = options || {};
3   this.region = this.options.region;
4 };

Now when you create a Component, it will look for a region option in the constructor’s object literal parameter. But a Component is meant to be heavily customized with the behavior and needs of the functionality encapsulated. To do that, you’ll want to allow more than just simple Component instances.

An .extend-able Component

You can borrow several of the techniques that Backbone provides when creating a Component definition. This includes both the use of a .extend method, to allow for object extension, and an initialize method to allow for a custom constructor function in the Component. It may be useful to allow a Component’s region to be specified with the object definition, as well.

 1 var Component = function(options){
 2   this.options = options || {};
 3
 4   // pull the region from the definition, or the
 5   // constructor options. precedence goes to the
 6   // constructor options as an override
 7   this.region = this.options.region || this.region;
 8
 9   // execute an `initialize` function if it's there
10   if (_.isFunction(this.initialize)){
11     this.initialize(this.options);
12   }
13 });
14
15 // Borrow Backbone's `extend` method
16 Component.extend = Backbone.Model.extend;

The line that retrieves the region checks to see if one was provided in the options, first. If one was, it uses that. If none was provided in the options, a region on an object definition is used (if provided). That way, if you provide a region on a Component definition, you can still override it in the constructor of a specific instance.

The check for the initialize function ensures that it is a function, if it exists at all. If it does, it calls the initialize function with the options passed through the constructor. By using this.options as the argument, you can ensure the function at least receives an empty object literal. This will help prevent errors and other problems when defining components with an initialize function, later.

Lastly, the extend method from Backbone.Model is attached to the Component function. It doesn’t matter which Backbone object you pull this function from - it’s the same function on all of them. But Backbone does not directly expose this function, so you’ll have to pull it from one of the Backbone objects directly.

Handling Events Within The Component

With Backbone being an event-driven library, and the majority of objects used in Backbone apps able to trigger events, it makes sense for the Component to be able to respond to and handle events. Mixing in Backbone.Events on the Component’s prototype will generally take care of this. But it would also be nice to have the Component clean up any event handler it can, when closing the component.

 1 _.extend(Component.prototype, Backbone.Events, {
 2
 3   // allow a Component to be closed
 4   close: function(){
 5     // unhook any `listenTo` events
 6     this.stopListening();
 7
 8     // close the region
 9     if (this.region){
10       this.region.close();
11     }
12
13     // call an `onClose` method for custom cleanup
14     if (_.isFunction(this.onClose)){
15       this.onClose();
16     }
17   }
18 });

Providing a close method allows any Component instance to be closed. It also gives the Component an opportunity to remove any bound event handlers that were set up with the listenTo method of the Component. It also closes the region that it holds on to, if any (this forces the view displayed in the region to close, as well). Lastly, it calls an onClose method if one exists - just like the custom View types from the first part of this book.

Consistent Is Clean

Consistency is an important aspect in API design. Providing the same method names with the same semantics across multiple objects creates a level of consistency and predictability. It also gives developers an easy way to understand the expected uses of the API. All of this leads toward clean use of the API and better code in general.

For more information on good API design, see Brandon Satrom’s article on Secrets of Awesome JavaScript API Design.

As you can see, there isn’t too much behind the Component type. In this case, the idea is more about the semantics and use case of the object type, than the details of the type implementation. Of course there will be additional bits of functionality that can be encapsulated in the core Component type, over time. But other pieces can be added as needed.

With the core of a Component defined, you can begin to build the application specific components.

Building An Email List Component

In GMail, the email list that shows the list of mail for the currently selected label or category, applying any filters or search criteria, etc. It may sound like it has a lot of responsibilities, but this can be very easily mitigated with good application design.

Assume the email list is built as a component within the larger screen. There are other components on the screen, as well. Many of them will deal with the raw list of email in some way (not the display of the list, but the actual email data list). One will display the list, one will filter the list, one will search within the list, and possibly more. If multiple component are dealing with the data in some way, it does not make sense for any one of them to have sole responsibility for managing that list. Each component, then, will only have responsibility for it’s use of the list and for exposing an API that lets other parts of the app know what manipulation is occurring.

Before getting to the coordination of components, though, take this idea in to account and build a component to display the list of email.

Defining The Component, Top Down

Start by extending from the Component type, and add an initialize method that looks for a mailList attribute on the options. Assume this is a Backbone.Collection instance, representing the email that should be displayed.

1 var MailListComponent = Component.extend({
2
3   initialize: function(options){
4     this.mailList = options.mailList;
5   }
6
7 });

Next, you’ll need a view to display the list of email. Since the data is in a Backbone.Collection, you can use the CollectionView and ItemView from the first part of this book to do that. Just define a template for the items, and create view definitions appropriately.

1 <script type="text/html" id="email-list-item-template">
2   <span class="from"><%= from %></span>
3   <span class="subject"><%= subject %></span>
4   <span class="date"><%= date %></span>
5 </script>

 1 var MailItemView = ItemView.extend({
 2   tagName: "li",
 3   className: "email",
 4   template: "#email-list-item-template"
 5 });
 6
 7 var MailListView = CollectionView.extend({
 8   tagname: "ul",
 9   itemView: MailitemView
10 });

Now within the Component, add a show method that takes the views, renders them, and shows them in the region that the Component is referencing.

 1 var MailListComponent = Component.extend({
 2   initialize: function(options){
 3     this.mailList = options.mailList;
 4   },
 5
 6   show: function(){
 7     var mailView = new MailListView({
 8       collection: this.mailList
 9     });
10
11     this.region.show(mailView);
12   }
13 });

And there you have it - a very basic component with which to show the list of email. Although, this is a rather simple example, it illustrates the basics of creating a component.

Exposing An API For Mail Item Selection

To make the MailListComponent more useful, it would be good for it to expose an API that allows other objects to know when a mail item has been selected. The easiest way to do this with a backbone application is with events, and the MailListComponent can trigger an event stating a mail item was selected.

For it to expose this method appropriately, though, it will need to know when a mail item is selected or clicked in the case of using a mouse. Listening to an event from the collection to know when a single item is selected would be ideal. But you don’t necessarily have control over the collection definition for the email. Wouldn’t it be nice if you could wrap the collection with the additional functionality of selecting an item? And doesn’t that just sound so familiar?

Take the MultiPickCollection from Chapter 9, and set it up inside of the component.

1 var MailListComponent = Component.extend({
2   initialize: function(options){
3     // build the MultiPickCollection
4     this.mailList = options.mailList;
5     this.pickable = new Backbone.Picky.MultiPickCollection(this.mailList);
6   },
7
8   // â€¦
9 });

The MailListView can assume it is using a pickable collection with pickable model instances in the item view, as well.

 1 var MailItemView = ItemView.extend({
 2   tagName: "li",
 3   className: "email",
 4   template: "#email-list-item-template",
 5
 6   events: {
 7     "click": "pickEmail"
 8   },
 9
10   initialize: function(){
11     this.pickable = new Backbone.Picky.PickableModel(this.model);
12   },
13
14   pickEmail: function(e){
15     this.pickable.pick();
16   }
17 });
18
19 var MailListView = CollectionView.extend({
20   tagname: "ul",
21   itemView: MailitemView
22 });

Now the MailListComponent can listen to the “picked” event on the MultiPickCollection and when it sees an item picked, it can forward that event out through the component instance. This creates an API that another object can use to coordinate behavior with other parts of the app.

 1 var MailListComponent = Component.extend({
 2
 3   initialize: function(options){
 4     // build the MultiPickCollection
 5     this.mailList = options.mailList;
 6     this.pickable = new Backbone.Picky.MultiPickCollection(this.mailList);
 7     this.listenTo(this.collection, "picked", this.emailSelected);
 8   },
 9
10   // when an email is selected through any means, fire this
11   // method. it will forward an event out of the component,
12   // allowing another part of the app to take care of what
13   // needs to happen when an email has been selected.
14   emailSelected: function(email){
15     this.trigger("email:selected", email);
16   },
17
18
19   show: function(){
20     var mailView = new MailListView({
21       collection: this.mailList
22     });
23     this.region.show(mailView);
24   }
25 });

Lessons Learned

Object literals are tremendously useful in JavaScript, as you’ve seen already, with managing workflow one of the uses. There are limitations to this, though. You can’t create new instances of object literals (even if you can inherit from them), for example. This may not be an issue in some simple cases, but it doesn’t allow for scalability in application features.

Appendices

Appendix A: Managing Events As Relationships

In my Scaling Backbone Apps With Marionette talk, I have some slides that deal with JavaScript zombies in Backbone apps. This isn’t a new subject by any means. It is one that I talk about a lot, and spend a lot of time explaining to others. But there is one aspect of this talk and the related material that I have only recently started using: the idea of managing event handlers as relationship and not simply object references. More importantly, though, correctly modeling the relationship between the observer (event handler) and the subject (event broadcaster) can give us insight in to our code and create a more natural representation of how we think about, understand, and observe the real world.

The Observer Pattern

Event systems in the object oriented world are almost always based on the classic Observer Pattern from the “Gang of Four” design patterns book (if you don’t own this book, go buy it right now). According to Wikipedia, the observer pattern

is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.

To put that a little more plainly: something triggers an event and other things listen to and respond to the event.

The basic structural set up for this pattern includes three things:

Event: the thing that happened; the action or outcome that has already occured

Subject: an object that triggers or broadcasts the occurance of an event

Observer: an object (or function) that listens for, and responds to an event

Backbone.Events is an implementation of the observer pattern at some level. We could argue about whether or not Backbone implements a “pure” observer pattern, but the important point is that this pattern is the basis for what Backbone and most other event systems implement. It informs us of the design and implementation of Backbone.Events and the object references and relationships involved.

But what is an event? What are the “subjects” and “observers”?

An Event: Moving A Ball Through A Round Metal Hoop

Think about basketball for a moment. When a player scores, the team’s points are increased, everyone adjusts their position to start the next play, fans cheer or complain, and the game goes on.

In this case, the “Subject” is the player – the person that scored the points. When the player is able to move the ball through the round metal hoop at the end of the court in an appropriate manner, a “points scored” event is triggered. The “observers”, then, are comprised of a number of people: the other players, the fans, the score keeper, the ref, and many more people that are paying attention to the game. They go about their business of cheering, updating the scoreboard, and doing anything else that they are responsible for doing in response to the points being scored.

Keep this analogy in mind as I’ll be coming back around to it in a bit. For now, though, this should give you a good idea of the various players involved in an Observer pattern.

Backbone.Events And References

When we set up an observer in Backbone, we typically use the .on method to tell the Subject about the Observer. In other words, the object that triggers the event will hold a reference to the object or function that handles the event.In the case of an in-line callback function, the reference that we hand to the Subject is a simple function:

1 // a subject triggers an event
2 subject.on("some:event", function(){
3   // the callback function is the observer
4   // of the event in this case. do stuff
5   // here because the "some:event" event was
6   // triggered
7 });

This is a simple reference, and we have no other direct references to the function. When myObject goes out of scope, then, this function reference will be garbage collected.

A common example of this in a Backbone.Collection would be the use of the “reset” event to process a collection being reset

1 myCollection.on("reset", function(){
2   // re-render the entire collection, or
3   // do something else with the collection
4   // knowing that it was reset with new models
5 });

When using a method reference (that is, a function attached to another object) as the callback function, though, we are only handing the function reference to the Subject.

1 subject.on("some:event", anObserver.someHandlerMethod);

In this case, the Subject is only directly handed a reference to anObserver.someHandlerMethod. This method does not bring along a reference to the anObserver object, though. Passing a method like this is passing a method pointer and the method happens to be attached to the anObserver object.

There’s also a potential problem in this code: the someHandlerMethod does not get cleaned up when the anObserver goes out of scope. Because subject has a reference to someHandlerMethod, it can’t be cleaned up. This - an event handler that is not cleaned up - is one of the most common causes of zombie objects in JavaScript and Backbone.js apps. There are simple ways to solve this problems, though. We just need to remove the observer reference from the Subject when we’re done:

1 subject.off("some:event", anObserver.someHandlerMethod);

This removes the Observer method reference and allows the objects to be properly garbage collected. It effectively double-taps the zombie before the zombie has a chance to re-animate.

While this code does handle the zombie problem, it doesn’t always do it in the best way. The relationship between the Subject and the Observer is wrong for many of the cases that JavaScript and Backbone apps run in to.

Events And Relationships

When we call the .on and .off methods of a Backbone object, we are doing more than just setting up object references for an observer pattern implementation. We are setting up relationships and perspectives on those relationships in the mind of the developers reading and writing the code.

It’s natural for us to think about event relationships in when/then, cause and effect logic. This is what we are taught in early education: “when this, then that,” or in this case, “When this event fires, go do that.” Statements like this tells us that the action is the primary actor and the reaction is secondary. This is great when looking at cause and effect in natural language, because it’s true. Without the cause the effect would not be there. That’s how cause and effect works. But the cause and effect relationship falls apart when looking at events and reactions to events – both in code and in the real world.

How we see objects and their relationships can make or break the maintainability and flexibility of a design and implementation for a software system. It’s important to think through the relationships, then, and not just think about raw object references.

Scoring Points And Notifying Everyone

Think back to the basketball analogy and what happens when a basketball player scores. What did the player do? How do they react? If it was an amazing shot they may have celebrated. But, chances are they just moved on to the next play.

Now think about what the player didn’t do. They didn’t walk around to every other player on the court and tell them that they scored. The didn’t walk over to the ref and tell him that points were scored. They didn’t walk over to the score keeper and tell that person that points were scored. They didn’t go tell … you get the idea.

The basketball player didn’t tell anyone about the points being scored, because that is not the responsibility of the player. The ref, the score keeper, the other players, the fans – everyone involved in this sporting event observed the points being scored and reacted appropriately. The player that scored the points was not responsible for telling all of the observers that the event occurred.

Why, then, do we model events in code as if the basketball player, or perhaps the basket itself, is responsible for telling everyone when points are scored? Why do we write code like this?

1 basket.on("points:scored", function(team, player, points){
2   team.updateScore(points);
3   scoreboard.updateScore(team, points);
4   player.updatePointsScored(points);
5   // etc
6 });

The answer is object references. The Subject that triggers the event needs references to the Observer objects so that the observers can be notified. Developers typically look at this need for references and design an API around that. The observer pattern pretty much tells us to do that, too. But this relationship is backward and it needs to be fixed if we are going to write maintainable software systems.

The Relationship Problem: Who Owns It?

In the above basketball example, and in Backbone events in general, it’s the Subject that owns the reference and therefore, the relationship. By calling basket.on we are telling the basket object to wait for it’s own event to be triggered. When the event is triggered, it call the function that was supplied.

It it necessary for the basket object to hold a reference to the callback function because of the way object references work. If the Subject (basket) does not have a reference to the function that needs to be called… well… there’s nothing to call when the event is triggered.

The real problem, then, is not object references. The real problem is how we create the references and who controls the relationship facilitated by those references.

Backbone.Events And Relationships

Calling basket.on("points:scored", function(){…}) clearly sets up a relationship that is owned by the basket object. The basket is responsible for maintaining the reference, so it owns the relationship right? If we’re thinking in terms of references then this makes sense. But if we think in terms of relationships and how a basketball game actually operates, this doesn’t make any sense. We don’t want the Subject to own the relationships. We want the Observer to own the relationships.

A typical Backbone.View implementation illustrates why we want the Observer to own the relationship:

 1 Backbone.View.extend({
 2
 3   initialize: function(){
 4     this.model.on("change:foo", this.doStuff, this);
 5   },
 6
 7   doStuff: function(foo){
 8     // do stuff in response to "foo" changing
 9   },
10
11   remove: function(){
12     this.model.off("change:foo", this.doStuff, this);
13
14     // call the base type's method, since we are overriding it
15     Backbone.View.prototype.remove.call(this);
16   }
17
18 });

A typical Backbone.Model lives much longer than a view that works with it. The model will be displayed, edited and used for other parts of the application many times while a single view instance that works with it is stood up and torn down relatively quickly.

The zombie problem is also illustrated here. In order to prevent this view from becoming a zombie, we have to unbind the event handler that is set up in the initialize function. This is typically done by overriding the remove method and calling the necessary off event, as shown above.

From a functional perspective, this works perfectly fine. It might be a little annoying to type all of those off method calls, but this will clean up the references just fine. It doesn’t model the relationship correctly, though. It still tells us that the model is in control of the references and relationship. The view has to ask the model to create the reference, and ask it to drop the reference. What we want instead, is a way for our view to say “I’m in control of this relationship. When I’m done, I’ll sever the relationship. You don’t have to worry about it, Model.”

Inverting The Observer Relationship For Backbone.View

To invert the code structure and begin thinking about relationships, we need to have the view be in control. We need the view to say “I care about this event, and I will respond to it when it happens”. Fortunately, Backbone provides the means to do this: the listenTo and stopListening methods from Backbone.Events.

The view from above can be re-written with .listenTo and .stopListening instead of .on and .off, very easily.

 1 Backbone.View.extend({
 2
 3   initialize: function(){
 4     this.listenTo(this.model, "change:foo", this.doStuff);
 5   },
 6
 7   doStuff: function(foo){
 8     // do stuff in response to "foo" changing
 9   }
10
11   // we don't need this. the default `remove` method calls `stopListening` for us
12   // remove: function(){
13     // this.stopListening();
14     // ...
15   //}
16 });

There are a few things of note, from a code perspective, here:

We are calling the listenTo method of the view

We are passing this.model as an argument to the listenTo method

We are no longer passing this as the context variable for the last argument of listenTo

We no longer need to override the remove method, since the default implementation calls stopListening for us

But far more important than the code difference is the shift in perspective. Instead of having code that says “Hey model, I’d like to register a callback method with you,” we now have code that says, “I, the view, need to know when the model triggers this event and I, the view, will response appropriately.” We also have have the view saying, “I, the view, am ending all relationships that I have previously set up.” It’s a subtle difference in how the relationship is managed, but it’s a very important one as it more correctly models the relationships between the Subject and Observer.

Behind the scenes, the model is still being handed a reference to the view using the on method. There’s simply no way around this technical detail. But we can (and should) hide this technical detail behind the veil of abstraction, allowing our code to tell us what relationship matters and who is in control of the references.

Zombie Killing Is My Business

There’s another benefit, as well. That one call to .stopListening() inside of the remove method will sever all relationships that have been set up with the .listenTo method of the view. This cleans up all of the references that the model has to the view, preventing zombie views from having a chance to infect our apps.

This little detail alone is worth it’s 100x its weight in the extra few characters that you have to type when using .listenTo.

No Silver Bullet For Modeling Relationships

It’s tempting for me to say something like “stop using .on and .off” at this point, but that would be a bad idea. I think it would be safe to say that within the context of a Backbone.View, but there are other scenarios where this doesn’t make sense.

In my post about modeling explicit workflow in JavaScript apps before, I talk about using a higher level object to coordinate the workflow of an application. This is a scenario where it might not make sense to use .listenTo and .stopListening.

 1 MyApp.someWorkflow = {
 2
 3   show: function(){
 4     var layout = new MyApp.LayoutView();
 5
 6     layout.on("render", this.showDetail, this);
 7
 8     this.showView(layout);
 9   },
10
11   // ... showDetail, showView, etc
12 };

In this code, the layout will likely be closed relatively quickly, and the someWorkflow object will likely remain alive forever, as it has been attached to the global app object. This would be a bad place to tie the event reference cleanup to the higher level object. It would never get cleaned up. Instead, you would need to tie the lifecycle of the event handlers to the layout. The above code would be correct in using .on to set up the event, then The layout being closed will remove the reference to the event handler and things will be cleaned up nicely.

There are likely other scenarios where using .on and/or .off would make more sense for the relationship management and reference management, still. Instead of blindly applying a pattern for handling zombies and relationship management, we need to understand the actual relationship between the objects in question.

Thinking In, And Modeling Relationships vs References

When we start working with relationships instead of just references, our code becomes easier to understand. We can model and code application and system designs that better express the way we think and the way we understand relationships in the real world. Under the hood, we still have to deal with references, but that doesn’t mean our API has to expose these raw object references as the relationship we are creating.

More than an API difference, though, the idea of thinking about relationships instead of just references is just that – an idea. It’s a shift in our mindset and in how we look at the code we are writing. It’s a change in perspective to give us better insight in to how the things we are modeling actually interact and relate to each other. It informs our system design, our API implementation, how we look for and create abstractions, and how we organize our system in to smaller sub-sets that can be composed in to the larger whole.

Appendix B: 3 Stages of App Initialization

There are three different stages in the initialization of a Backbone application. Each of these stages has it’s own responsibilities that should be kept separate if an application is to scale properly. Smaller applications may be able to ignore this. Moving beyond anything trivial without accounting for these stages will lead toward more complexity than is necessary in an application.

The three stages of an application’s initialization include:

Download And Parse

Application Initialization

State Restoration (optional)

This could break this down in to a significantly larger number of stages if a much more fine-grained and detailed analysis is done. But as a general place to start, identifying 3 stages works well.

Stage 1: Download And Parse

Consider this the stage where the browser is simply grabbing all of the specified resources from the server and running through the first pass of parsing the HTML, laying out what the static HTML has provided, styling it with the basic CSS definitions, displaying any images and text from the static HTML, and parsing the JavaScript files so it can get ready to run them. Every app does this because without it, your browser doesn’t have anything to do or show.

Stage 2: Application Initialization

Every application has an initialization stage. Some are more elaborate than others. At times you can get away with the default top-down, parse what is found first method of ad-hoc code. Anything more than a few functions, though, and you’ll need application object of some sort - whether it’s an object literal with an “init” method on it, or a complete Application type with initializers as described in chapter 12. Whatever form this application object takes, your app will need a series of initializers - functions that start up a given area of an application.

What goes in the initializers?

Initializers are the bits of code, functionality, data and display that are absolutely required for your app to do it’s job, no matter what part of the application the user is trying to load up and use. They are the bits that must be initialized before the user can do anything meaningful with your application.

If your app has a menu structure generated by Backbone code, and it must always be present in the application, this should be in an initializer. If you’re building a multi-room chat application and you need to list the rooms that the user has favorited in a small block on the screen that is always visible to the user, this should be an initializer. If you’re building an image gallery and you need to load a thumb-nail list of images to show, no matter which image the user is trying to view, this is an initializer.

Other parts of your application code that the user doesn’t directly see may also be contenders for initializers, too. For example, if you have a router that needs to be up and running, the router probably needs to be instantiated inside of an initializer. But – and this is an important but – the routes on that router should not be executed during initialization. Instantiate the router and wait until after initialization has completed to call the “Backbone.history.start()” method, kicking off your route handlers.

Stage 3: State Restoration (optional)

This stage is optional because not every application has a context that needs to be restored on start up. Sometimes an application only needs initializers. The classic “todo” application is a great example of this - there is no contextual start up for this app. When the application is loaded, it initializes itself with the list of to do items and then it waits for the user to interact with the list.

When a Backbone application uses a router to respond to url pushState or hash fragment changes, though, it does have a contextual starting point. Each route that a user is allowed to bookmark or copy as a direct link will provide the context that our application needs to use, to get the user back to where they want to be. Even if a Backbone app has a router and contextual start, though, it may not be used. If there user hits the root of the application, there may not be any additional code to run for the empty (“”) route. When the user hits a route, though, that route must server up the context and application state that the user expects to see.

The problem in most routed Backbone applications, though, is that they bundle the application initialization with the contextual start. That is, developers tend to use the router and its callback methods as the sole place to get the application initialized and get the user back to the context of the route that they requested. For trivial applications, this may be fine. The initialization code may be so small that it doesn’t really matter if it’s crammed in to the router. But for any real application with any amount of complexity, this is a bad idea. It couples two very distinct parts of the application startup very tightly, and it can lead to bloated and unmaintainable routers with limited entry points in to the application.

So… what goes in the contextual start, other than just saying route callbacks?

Your route callbacks should be as simple as possible. They shouldn’t initialize your system as a whole. Rather, they should be used to determine the state of the application that the user wishes to see. Therefore, the code that goes in to a route callback should be the smallest amount of code that you can write to get your application from it’s initial state (the state that it was in when the initializers completed) to the desired state.

Contextual Examples

In an image gallery application, a user may hit a bookmark that points to a specific image. For example, “#images/4”. The route callback that executes should load the requested image and display it on the screen:

 1 Backbone.Router.extend({
 2   routes: {
 3     "image/:id": "imageById"
 4   },
 5
 6   imageById: function(id){
 7     var image = imageCollection.get(id);
 8     App.showImage(image);
 9   }
10 });

In a multi-room chat application, a user may hit a bookmark that should take them directly in to a specific chat room. For example, “#backbone”. The route callback that executes should take this room name and call the code that is necessary to enter the chat room.

Chances are this is a fairly involved set of code. You’ll need to load the list of users in the chat room. You’ll need to clear the current chat windows and possibly pre-load recent messages to be displayed. You may also need to change a browser’s websocket event listeners to pick up events for this specific room instead, so that messages for this room can be displayed as they come in.

This is a lot of code to run, and it’s fare more code than should be allowed in a route callback method. It should, then, be encapsulated in an object that is responsible for registering the user as having entered that chat room. This object is then called from the router:

1 Backbone.Router.extend({
2   routes: {
3     ":roomname": "chatroom"
4   },
5
6   chatroom: function(roomname){
7     ChatApp.enterRoom(roomname);
8   }
9 });

Furthermore, there’s a high likelihood that the user will be able to enter chat rooms using some interaction on the web page. They may click on a chat room name in their favorite’s list, or they may type in a command like “/join #backbone” in to the chat application’s command area. For any of the the multiple ways to enter a chatroom, the code that is executed should be the same. Having the route callback be as simple and stupid as possible will promote code re-use and allow these three options to be easily implemented. If you only need to call ChatApp.enterRoom("someRoom") to enter any room that the user specifies, providing options for how the user enters a room becomes trivial.

Lessons Learned

Building a layer of abstraction can often help to identify patterns in applications, as shown with the application initializers. The idea of having two or three distinct phases of an application’s start up can help to identify the boundaries between objects and methods, as well. And there are still more valuable lessons that can be pulled from this code, such as not limiting an application’s codebase to pure Backbone or Backbone-augmenting objects.

Making The Implicit Explicit

One of the largest challenges that developers face is understanding and recognizing the implicit or implied parts of an application or process. And a JavaScript application’s initialization is no different. Developers often write code that ignores the implicit phases of an application’s lifecycle. The code will simply start itself up when it has been loaded, or it will litter a handful of jQuery DOMReady callback methods throughout the application. This can cause maintainability and performance problems in an application.

By making the application start up process more explicit, though, many of these problems can be avoided and new opportunities for organizing code and optimizing the application can be exposed. Having an explicit application definition phase, separated from an explicit initialization phase allows code to know when it will be executed and know what will be available. The third and optional contextual rehydration - using a route or other preserved state to spin up a specific part of the application - allows for even more flexibility, giving the application a solid foundation to run from before moving in to the specific context that the user requested.

Divide And Conquer

In the previous chapters, the principles of Separation of Concerns and Single Responsibility have been applied in the object and methods within the plugins and add-ons. These principles can and should be applied at higher level abstractions, though. The use of modules in JavaScript in a necessary part of creating large-scale, well functioning, maintainable systems. As Justin Meyer says, “The secret to building large apps is never build large apps. Break your applications into small pieces. Then, assemble those testable, bite-sized pieces into your big application.”

Application initializers are not a complete solution for this separation and modularization, of course. Using a module system of some sort - whether it’s a simple Immediately Invoking Function Expression, or a framework like RequireJS - helps to keep code separated and organized correctly. The use of application initializers, then, allows a module to be initialized at the appropriate time.

Appendix C: A Tale Of Two Patterns

Design patterns often differ only in semantics and intent. That is, the language used to describe the pattern is what sets it apart, more than an implementation of that specific pattern. It often comes down to squares vs rectangles vs polygons. You can create the same end result with all three, given the constraints of a square are still met – or you can use polygons to create an infinitely larger and more complex set of things.

When it comes to the Mediator and Event Aggregator patterns, there are some times where it may look like the patterns are interchangeable due to implementation similarities. However, the semantics and intent of these patterns are very different. And even if the implementations both use some of the same core constructs, I believe there is a distinct difference between them. I also believe they should not be interchanged or confused in communication because of the differences.

It’s All About Logic

The TL;DR is this: where does the logic live? An event aggregator has no application logic. It is purely infrastructure, forwarding events from a publisher to a subscriber. A mediator, on the other hand, encapsulates the potentially complex logic of application workflow. It coordinates multiple objects and/or services to accomplish a goal within the application. A mediator contains real application / business / workflow / process logic.

Event Aggregator

The core idea of the Event Aggregator, according to Martin Fowler, is to channel multiple event sources through a single object so that other objects needing to subscribe to the events don’t need to know about every event source.

Backbone’s Event Aggregator

The easiest event aggregator to show is that of Backbone.js – it’s built in to the Backbone object directly.

 1 var View1 = Backbone.View.extend({
 2   // ...
 3
 4   events: {
 5     "click .foo": "doIt"
 6   },
 7
 8   doIt: function(){
 9     // trigger an event through the event aggregator
10     Backbone.trigger("some:event");
11   }
12 });
13
14 var View2 = Backbone.View.extend({
15   // ...
16
17   initialize: function(){
18     // subscribe to the event aggregator's event
19     Backbone.on("some:event", this.doStuff, this);
20   },
21
22   doStuff: function(){
23     // ...
24   }
25 })

In this example, the first view is triggering an event when a DOM element is clicked. The event is triggered through Backbone’s built-in event aggregator – the Backbone object. Of course, it’s trivial to create your own event aggregator in Backbone, and there are some key things that we need to keep in mind when using an event aggregator, to keep our code simple.

jQuery’s Event Aggregator

Did you know that jQuery has a built-in event aggregator? They don’t call it this, but it’s in there and it’s scoped to DOM events. It also happens to look like Backbone’s event aggregator:

1 $("#mainArticle").on("click", function(e){
2
3   // handle the click event from any element
4   // underneath of the #mainArticle
5
6 });

This code sets up an event handler function that waits for an unknown number of event sources to trigger a “click” event, and it allows any number of listeners to attach to the events of those event publishers. jQuery just happens to scope this event aggregator to the DOM.

Mediator

A Mediator is an object that coordinates interactions (logic and behavior) between multiple objects. It makes decisions on when to call which objects, based on the actions (or in-action) of other objects and input.

A Mediator For Backbone

Backbone doesn’t have the idea of a mediator built in to it like a lot of other MV* frameworks do. But that doesn’t mean you can’t write one in 1 line of code:

var mediator = {};

Yes, of course this is just an object literal in JavaScript. Once again, we’re talking about semantics here. The purpose of the mediator is to control the workflow between objects and we really don’t need anything more than an object literal to do this.

 1 var orgChart = {
 2
 3   addNewEmployee: function(){
 4
 5     // getEmployeeDetail provides a view that users interact with
 6     var employeeDetail = this.getEmployeeDetail();
 7
 8     // when the employee detail is complete, the mediator (the 'orgchart' object)
 9     // decides what should happen next
10     employeeDetail.on("complete", function(employee){
11
12       // set up additional objects that have additional events, which are used
13       // by the mediator to do additional things
14       var managerSelector = this.selectManager(employee);
15       managerSelector.on("save", function(employee){
16         employee.save();
17       });
18
19     });
20   },
21
22   // ...
23 }

This example shows a very basic implementation of a mediator object with Backbone based objects that can trigger and subscribe to events. I’ve often referred to this type of object as a “workflow” object in the past, but the truth is that it is a mediator. It is an object that handles the workflow between many other objects, aggregating the responsibility of that workflow knowledge in to a single object. The result is workflow that is easier to understand and maintain.

Mediators And Workflow Components

For more information on building mediators that scale better, and offer more features, see chapters 13 and 14.

Similarities And Differences

There are, without a doubt, similarities between the event aggregator and mediator examples that I’ve shown here. The similarities boil down to two primary items: events and third-party objects. These differences are superficial at best, though. When we dig in to the intent of the pattern and see that the implementations can be dramatically different, the nature of the patterns become more apparent.

Events

Both the event aggregator and mediator use events, in the above examples. An event aggregator obviously deals with events – it’s in the name after all. The mediator only uses events because it makes life easy when dealing with Backbone, though. There is nothing that says a mediator must be built with events. You can build a mediator with callback methods, by handing the mediator reference to the child object, or by any of a number of other means.

The difference, then, is why these two patterns are both using events. The event aggregator, as a pattern, is designed to deal with events. The mediator, though, only uses them because it’s convenient.

Third-Party Objects

Both the event aggregator and mediator, by design, use a third-party object to facilitate things. The event aggregator itself is a third-party to the event publisher and the event subscriber. It acts as a central hub for events to pass through. The mediator is also a third party to other objects, though. So where is the difference? Why don’t we call an event aggregator a mediator? The answer largely comes down to where the application logic and workflow is coded.

In the case of an event aggregator, the third party object is there only to facilitate the pass-through of events from an unknown number of sources to an unknown number of handlers. All workflow and business logic that needs to be kicked off is put directly in to the the object that triggers the events and the objects that handle the events.

In the case of the mediator, though, the business logic and workflow is aggregated in to the mediator itself. The mediator decides when an object should have it’s methods called and attributes updated based on factors that the mediator knows about. It encapsulates the workflow and process, coordinating multiple objects to produce the desired system behavior. The individual objects involved in this workflow each know how to perform their own task. But it’s the mediator that tells the objects when to perform the tasks by making decisions at a higher level than the individual objects.

An event aggregator facilitates a “fire and forget” model of communication. The object triggering the event doesn’t care if there are any subscribers. It just fires the event and moves on. A mediator, though, might use events to make decisions, but it is definitely not “fire and forget”. A mediator pays attention to a known set of input or activities so that it can facilitate and coordinate additional behavior with a known set of actors (objects).

Relationships: When To Use Which

Understanding the similarities and differences between an event aggregator and mediator is important for semantic reasons. It’s equally as important to understand when to use which pattern, though. The basic semantics and intent of the patterns does inform the question of when, but actual experience in using the patterns will help you understand the more subtle points and nuanced decisions that have to be made.

Event Aggregator Use

In general, an event aggregator is uses when you either have too many objects to listen to directly, or you have objects that are unrelated entirely.

When two objects have a direct relationship already – say, a parent view and child view – then there might be little benefit in using an event aggregator. Have the child view trigger an event and the parent view can handle the event. This is most commonly seen in Backbone’s Collection and Model, where all Model events are bubbled up to and through it’s parent Collection. A Collection often uses model events to modify the state of itself or other models. Handling “selected” items in a collection is a good example of this.

jQuery’s on method as an event aggregator is a great example of too many objects to listen to. If you have 10, 20 or 200 DOM elements that can trigger a “click” event, it might be a bad idea to set up a listener on all of them individually. This could quickly deteriorate performance of the application and user experience. Instead, using jQuery’s on method allows us to aggregate all of the events and reduce the overhead of 10, 20, or 200 event handlers down to 1.

Indirect relationships are also a great time to use event aggregators. In Backbone applications, it is very common to have multiple view objects that need to communicate, but have no direct relationship. For example, a menu system might have a view that handles the menu item clicks. But we don’t want the menu to be directly tied to the content views that show all of the details and information when a menu item is clicked. Having the content and menu coupled together would make the code very difficult to maintain, in the long run. Instead, we can use an event aggregator to trigger “menu:click:foo” events, and have a “foo” object handle the click event to show it’s content on the screen.

Mediator Use

A mediator is best applied when two or more objects have an indirect working relationship, and business logic or workflow needs to dictate the interactions and coordination of these objects.

A wizard interface is a good example of this, as shown with the “orgChart” example, above. There are multiple views that facilitate the entire workflow of the wizard. Rather than tightly coupling the view together by having them reference each other directly, we can decouple them and more explicitly model the workflow between them by introducing a mediator.

The mediator extracts the workflow from the implementation details and creates a more natural abstraction at a higher level, showing us at a much faster glance what that workflow is. We no longer have to dig in to the details of each view in the workflow, to see what the workflow actually is.

Event Aggregator And Mediator Together

The crux of the difference between an event aggregator and a mediator, and why these pattern names should not be interchanged with each other, is illustrated best by showing how they can be used together. The menu example for an event aggregator is the perfect place to introduce a mediator as well.

Clicking a menu item may trigger a series of changes throughout an application. Some of these changes will be independent of others, and using an event aggregator for this makes sense. Some of these changes may be internally related to each other, though, and may use a mediator to enact those changes. A mediator, then, could be set up to listen to the event aggregator. It could run it’s logic and process to facilitate and coordinate many objects that are related to each other, but unrelated to the original event source.

 1 var MenuItem = Backbone.View.extend({
 2
 3   events: {
 4     "click .thatThing": "clickedIt"
 5   },
 6
 7   clickedIt: function(e){
 8     e.preventDefault();
 9
10     // assume this triggers "menu:click:foo"
11     Backbone.trigger("menu:click:" + this.model.get("name"));
12   }
13
14 });
15
16 // ... somewhere else in the app
17
18 var MyWorkflow = function(){
19   Backbone.on("menu:click:foo", this.doStuff, this);
20 };
21
22 MyWorkflow.prototype.doStuff = function(){
23   // instantiate multiple objects here.
24   // set up event handlers for those objects.
25   // coordinate all of the objects in to a meaningful workflow.
26 };

In this example, when the MenuItem with the right model is clicked, the “menu:click:foo” event will be triggered. An instance of the “MyWorkflow” object, assuming one is already instantiated, will handle this specific event and will coordinate all of the objects that it knows about, to create the desired user experience and workflow.

An event aggregator and a mediator have been combined to create a much more meaningful experience in both the code and the application itself. We now have a clean separation between the menu and the workflow through an event aggregator. And we are still keeping the workflow itself clean and maintainable through the use of a mediator.

Pattern Language: Semantics

There is one overriding point to make in all of this discussion: semantics. Communicating intent and semantics through the use of named patterns is only viable and only valid when all parties in a communication medium understand the language in the same way.

If I say “apple”, what am I talking about? Am I talking about a fruit? Or am I talking about a technology and consumer products company? As Sharon Cichelli says: “semantics will continue to be important, until we learn how to communicate in something other than language”.

Appendix D: Better JavaScript Mixins

Unfinished Chapter

Note: This chapter is incomplete or contains known errors and inconsistencies. Further work is being done to finish this chapter. All feedback is welcome, still.

Mixins are generally easy in JavaScript, though they are semantically different than what Ruby calls a mixin, which are facilitated through inheritance behind the scenes. The most basic of mixins in JavaScript is done with an “extend” method from a library like underscore.js or jQuery. While this method of copying methods and attributes is powerful, it is also limited.

Object Extension Is A Poor Man’s Mixin

I love the “extend” methods of jQuery and Underscore. I use them a lot. They’re powerful and simple and make it easy to transfer data and behavior from one object to another – the essence of a mixin. But in spite of my love of underscore.js and jQuery’s “extend” methods, there’s a problem with them in that they apply every attribute from one or more source objects to a target objects.

You can see the effect of this in this example from Chris Missal:

 1     var start = {
 2         id: 123,
 3         count: 41,
 4         desc: 'this is information',
 5         title: 'Base Object',
 6         tag: 'uncategorized',
 7         values: [1,1,2,3,5,8,13]
 8     };
 9     var more = {
10         name: 'Los Techies',
11         tag: 'javascript'
12     };
13     var extra = {
14         count: 42,
15         title: null,
16         desc: undefined,
17         values: [1,3,6,10]
18     };
19
20     var extended = _.extend(start, more, extra);
21     console.log(JSON.stringify(extended));

This produces the following output:

1     {
2         "id": 123,
3         "count": 42,
4         "title": null,
5         "tag": "javascript",
6         "values": [1,3,6,10],
7         "name": "Los Techies"
8     }

In this example, the first object contains a key named “values” and the third object also contains a key named “values”. When the extend method is called, the last one in wins. This means that the “values” from the third object end up being the values on the final target object.

So, what happens if we want to mix two behavioral sets in to one target object, but both of those behavior sets use the same underlying “values”, or “config”, or “bindings” (as reported in this Marionette issue)? One or both of them will break, and that’s definitely not a good thing.

A Problem Of Context

The good news is there’s an easy way to solve the mixin problem with JavaScript: only copy the methods you need from the behavior set in to the target.

That is, if the object you want to mix in to another has a method called “doSomething”, you shouldn’t be forced to copy the “config” and “_whatever” and “foo” and all the other methods and attributes off this object just to get access to the “doSomething” method. Instead, you should only have to copy the “doSomething” method from the behavior source to your target.

1     var foo = {
2       doSomething: function(){
3         // ...
4       }
5     }
6
7     var bar = {};
8     bar.doSomething = foo.doSomething;

But this poses it’s own challenge: the source of the behavior likely calls “this.config” and “this._whatever()” and other context-based methods and attributes to do it’s work. Simply copying the “doSomething” function from one object to another won’t work because the context of the function will change and the support methods / data won’t be found.

For more detail on context and how it changes, check out my JavaScript Context screencast.

Solving The Mixin Problem

To fix the mixin problem then, we need to do two things:

Only copy the methods we need to the target

Ensure the copied methods retain their original context when executing

This is easier than it sounds. We’ve already seen how requirement #1 can be solved, and requirement #2 can be handled in a number of ways, including the raw ECMAScript 5 “bind” method, the use of Underscore’s “bind” method, writing our own, or by using one of a number of other shims and plugins.

The way to facilitate a mixin from one object to another, then, looks something like this:

 1     var foo = {
 2       baz: function(){
 3         // ...
 4       },
 5
 6       config: [ ... ]
 7     }
 8
 9     var bar = {
10       config: { ... }
11     };
12
13     // ECMAScript "bind"
14     bar.baz = foo.baz.bind(foo);
15
16     // Undescore "bind"
17     bar.baz = _.bind(foo.baz, foo);
18
19     // ... many more options

In this example, both the source object and the target object have a “config” attribute. Each object needs to use that config attribute to store and retrieve certain bits of data without clobbering each the other one, but I still want the “baz” function to be available directly on the “foo” object. To make this all work, I assign a bound version of the “baz” function to foo where the binding is set to to the bar object. That way whenever the baz function is called from foo, it will always run in the context of the original source – bar.

A Real Example

In this scenario, the model instance is extended with the functionality of the SelectableModel. This provides the select and deselect methods on the model directly, and still triggers the events from the model. Now the model instance can be used within the view with no oddities in accessing the selectable functionality.

 1     SelectableView = BBPlug.ModelView.extend({
 2
 3       initialize: function(){
 4         this.model.on("selected", this.modelSelected, this);
 5         this.model.on("deselected", this.modelDeselected, this);
 6       },
 7
 8       selectModel: function(){
 9         this.model.select();
10       },
11
12       deselectModel: function(){
13         this.model.deselect();
14       }
15
16     });
17
18     var model = new MySelectableModel();
19     new SelectableView({
20       model: model
21     });

The downside to this approach is that the model is now being directly modified by the SelectabelModel in both the extension of the model, and when the select and deselect methods are called. This could have some potential side effects if care is not taken to ensure these methods and attributes are not overridden by other code. The benefit, though, is a more clear use of the selectable methods on the model. With a little planning and possibly some documentation or code comments around the model, the potential side effects can be avoided.

The end result, though, is that the SelectableModel is a very flexible object in terms of it’s use. It can be created on it’s own, with only a reference to a model. It can be mixed in to a model directly. Or it can be used in any of a number of other ways that JavaScript objects can be created, used and destroyed.

Ok, enough “foo, bar, baz” nonsense. Let’s look at a real example of where I’m doing this: Marionette’s use of Backbone.EventBinder. I want to bring the “bindTo”, “unbindFrom” and “unbindAll” methods from the EventBinder in to Marionette’s Application object, as one example. To do this while allowing the EventBinder to manage it’s own internal state and implementation details, I use the above technique of assigning the methods as bound functions:

 1     Marionette.addEventBinder = function(target){
 2
 3       // create the "source" of the functionality i need
 4       var eventBinder = new Marionette.EventBinder();
 5
 6       // add the methods i need to the target object, binding them correctly
 7       target.bindTo = _.bind(eventBinder.bindTo, eventBinder);
 8       target.unbindFrom = _.bind(eventBinder.unbindFrom, eventBinder);
 9       target.unbindAll = _.bind(eventBinder.unbindAll, eventBinder);
10     };
11
12     // use the mixin method
13     var myApp = new Marionette.Application();
14     Marionette.addEventBinder(myApp);

Now when I call any of those three methods from my application instance, they still run in the context of my eventBinder object instance and they can access all of their internal state, configuration and behavior. But at the same time, I can worry less about whether or not the implementation details of the EventBinder are going to clobber the implementation details of the Application object. Since I’m being very explicit about which methods and attributes are brought over from the EventBinder, I can spend the small amount of cognitive energy that I need to determine whether or not the method I’m creating on the Application instance already exists. I don’t have to worry about the internal details like “_eventBindings” and other bits because they are not going to be copied over.

Simplifying Mixins

Given the repetition of creating mixins like this, it should be pretty easy to create a function that can handle the grunt work for you. All you need to supply is a target object, a source object and a list of methods to copy. The mixin function can handle the rest:

 1     // build a mixin function to take a target that receives the mixin,
 2     // a source that is the mixin, and a list of methods / attributes to
 3     // copy over to the target
 4
 5     function mixInto(target, source, methodNames){
 6
 7       // ignore the actual args list and build from arguments so we can
 8       // be sure to get all of the method names
 9       var args = Array.prototype.slice.apply(arguments);
10       target = args.shift();
11       source = args.shift();
12       methodNames = args;
13
14       var method;
15       var length = methodNames.length;
16       for(var i = 0; i < length; i++){
17         method = methodNames[i];
18
19         // bind the function from the source and assign the
20         // bound function to the target
21         target[method] = _.bind(source[method], source);
22       }
23
24     }
25
26     // make use of the mixin function
27     var myApp = new Marionette.Application();
28     mixInto(myApp, Marionette.EventBinder, "bindTo", "unbindFrom", "unbindAll");

This should be functionally equivalent to the previous code that was manually binding and assigning the methods. But keep in mind that this code is not robust at all. Bad things will happen if you get the source’s method names wrong, for example. These little details should be handled in a more complete mixin function.

An Alternate Implementation: Closures

An alternate implementation for this can be facilitated without the use of a “bind” function. Instead, a simple closure can be set up around the source object, with a wrapper function that simply forwards calls to the source:

 1     // build a mixin function to take a target that receives the mixin,
 2     // a source that is the mixin, and a list of methods / attributes to
 3     // copy over to the target
 4
 5     function mixInto(target, source, methodNames){
 6
 7       // ignore the actual args list and build from arguments so we can
 8       // be sure to get all of the method names
 9       var args = Array.prototype.slice.apply(arguments);
10       target = args.shift();
11       source = args.shift();
12       methodNames = args;
13
14       var method;
15       var length = methodNames.length;
16       for(var i = 0; i < length; i++){
17         method = methodNames[i];
18
19         // build a function with a closure around the source
20         // and forward the method call to the source, passing
21         // along the method parameters and setting the context
22         target[method] = function(){
23           var args = Array.prototype.slice(arguments);
24           source[method].apply(source, args);
25         }
26
27       }
28
29     }
30
31     // make use of the mixin function
32     var myApp = new Marionette.Application();
33     mixInto(myApp, Marionette.EventBinder, "bindTo", "unbindFrom", "unbindAll");

I’m not sure if this version is really “better” or not, but it would at least provide more backward compatibility support and fewer requirements. You wouldn’t need to patch ‘Function.prototype.bind’ or use a third party shim or library for older browsers. It should work with any browser that supports JavaScript, though I’m not sure how far back it would go. Chances are, though, that any browser people are still using would be able to handle this, including – dare I say it? – IE6 (maybe… I think… I’m not going to test that, though :P )

Potential Drawbacks

As great as all this looks and sounds, there are some limitations and drawbacks – and probably more than I’m even aware of right now.

We’re directly manipulating the context of the functions with this solution. While this has certainly provided a measured benefit, it can be dangerous. There may be (are likely) times that you just don’t want to mess with context – namely when you aren’t in control of the function context in the first place. Think about a jQuery function callback, for example. Typically, jQuery sets the context of a callback to the DOM element that was being manipulated and you might not want to mess with that.

In the case of my EventBinder with Marionette, I did run in to a small problem with the context binding. The original version of the code would default the context of callback functions to the object that “bindTo” was called from. This meant the callback for “myView.bindTo(…)” would be run with “myView” as the context. When I switched over to the above code that creates the bound functions, the default context changed. Instead of being the view, the context was set to the EventBinder instance itself, just like our code told it to. This had an effect on how my Marionette views were behaving and I had to work around that problem in another way.

There certainly some potential drawbacks to this, as noted. But if you understand that danger and you don’t try to abuse this for absolutely everything, I think this idea could work out pretty well as a way to produce a mixin system that really does favor composition over inheritance, and avoids the pitfalls of simple object extension.

Backbone.Include

There’s a library from Anthony Short that aims to solve the same problem for Backbone, specifically. Check out Backbone.Include for Anthony’s implementation.

Appendix E: Theme And Variation

There are two hard problems in software development:

Naming things

Cache invalidation

Off by one errors

The “off by one” addition is a variation of the a quote by Phil Karlton, which says the two hard things in computer science are cache invalidation and naming things. The variation was popularized by Martin Fowler in a short blog post.

Naming things truly is difficult. Names provide meaning and expectations. Things that are named randomly or by different convention will appear unrelated. It is important to name things properly, then. And naming things with a theme can often help.

The theme of the project often leads to the names of the individual items. Naming the items by this theme makes them easier to remember and understand, if the theme is chosen properly. If a theme is chosen poorly, though, it can cause as many problems as were solved - or more.

Selecting vs Picking

Part 2 of the book is devoted to building a plugin named “Backbone.Picky”. The name comes from the idea of “picking” the models and that are needed. However, the original method names, attributes and other aspects of the code did not follow the theme of being “picked”. Instead, the theme changed to “selection” in the API. Models could be “selected” and “deselected” with a .select() and .deselect() method. This works, technically. Computers don’t care what names are given to things. But from a human perspective - which is the only perspective that matters, honestly - naming is very important. By switching from a “picked” theme to a “selected” theme in the method and attribute names, several problems were created.

A Variation On Theme

The idea of a “theme” isn’t anything new in software development. This practice has been around for a long, long time. It has also undergone many different name changes, including the use of “metaphor” at the height of the eXtreme Programming (XP) days.

Whatever it is called, the theme of a project is something that often needs to be chosen carefully. I’ve heard many a story, for example, of XP teams picking a strong metaphor for a code base and having it bite them in the butt. For example, one person I talked to recounted a metaphor of a “warehouse” for a system. They had objects, services and code centered around equipment and actions that would be found in a warehouse. The problem was that this system had nothing to do with warehousing. Having a forklift.liftAndShelve() method for a system that dealt with customer relations (or whatever it was) may have been fun at first, but it quickly fell apart and became a source of problems.

In the end, themes or metaphors are important because they create continuity. But they can be taken too far if applied incorrectly. Be sure to pick a theme that makes sense for the system at hand.

The first of many problems that can be created by not sticking with the theme is confusion in the API and use. The name of the project creates a sense of expectation in the language used around the project. If a developer is talking about picking items in a collection, then it would make sense the .pick() them. Saying .pick() implies an opposite method of .unpick(). It sounds a little odd to say “pick” and “unpick”, though, so the names were changed to “select” and “deselect”. This lead to a number of questions and issues in the project, as developers that were using it were wondering why the theme for naming was different. It was confusing having to think about the project name and then use method and attribute names that didn’t follow the theme.

So, then change the name of the plugin to “Backbone.Selectable” or something like that, right? Then the names of the methods and attributes can revolve around the more natural language of “selection”: a model can be “selected” and “deselected.” This creates a much more subtle problem, though - one of semantics, expected behavior, and overriding methods.

When it comes time to give a Backbone.Collection the methods that allow it to select models or deselect models, the “select” theme breaks. Backbone.Collection already has a method called .select() - and it has nothing to do with marking models as selected. Rather, it is used to return an array of models that match a certain criteria.

It’s arguable as to whether or not the semantics of “select” are being broken in this case. Is the act of “selecting” a model and merely marking it as selected vs getting a reference to it really any different? The end result is an identification of which models are selected, after all. The real problem is in the behavioral change, then. If this plugin created a method named “select” and added it to the collection instance, it would be replacing the existing select method and it would change the behavior of that method. It would be possible to write this method in a way that preserves the existing behavior of the collection’s “select” method, of course. This may or may not be acceptable, and may or may not be difficult. It does add yet another requirement to the code, though. It also creates an unexpected modification to the behavior in the “select” method of collections. A developer that has become accustomed to the “select” method as defined by Backbone.Collection directly, may find the new behavior to be problematic. At the very least, it would be surprising to see that a method they have been using for however long, suddenly has additional behavior and semantics.

Knowing When To Move On

The solution to all of the problems that were created around the theme of “selection” was not to continue hacking on the code and documenting the changes in bold letters as was originally done. This only served to exacerbate the problems - like putting a band-aid made of sand paper and rubbing alcohol on a large wound. Rather than fixing the actual problem, this creates a worse situation that tends to lead toward other bad things.

The real solution is to change the method names and attributes to match the theme of the plugin. And sometimes, changing the theme of the plugin to start with. Instead having “select” and “deselect” methods, they will be “pick” and “unpick”. The language used around these methods will also be changed. The behavior of the methods can then be focused to the needs and not have to worry about breaking semantics or behavior in existing methods.

Lessons Learned

“Picking” a theme (see what I did there? :P) and sticking with it can spell the difference between success and failure in a project. A well chosen theme can create a sense of cohesiveness and unity. But a poorly chosen theme can have the opposite effect. Even if a theme seems to be well chosen at first - as was the case with Backbone.Picky and the “selection” theme - it can prove to be terrible in the end.

Don’t Mix Themes

One of the easiest mistakes to make in choosing a theme is creating a set of expectations in a project name, and then missing those expectations in the project API. If a theme is chosen for a project, then name should reflect the same thing as the API.

In the case of Backbone.Picky, the project name did not match the API theme. This caused a lot of confusion and questions. It would have been better to name the project something entirely unrelated to “selection” or “picking” than to have a name that came close to the theme, but with different words and names.

Don’t Let A Good Theme Go Bad

Picking a theme for a project is often easy at the outset. It may seem obvious what a project theme should be. But even the best themes can go bad over time. Always be on the look out for the limitations of a theme and be ready to fix the problems when they occur, not just work around them. This may mean a deeper examination of the names used from the theme, or choosing another theme entirely.

Be Wary Of Re-using Existing Function Names

When a plugin or add-on uses the same name for a function that is used by the types that are being augmented, problems can ensue. If the plugin is mixed in to the targeted type or instance of that type, the results can be detrimental causing a number of unknown and difficult to track down bugs. Whenever possible, use method and attribute names that are not typically part of the base types.

About Me

Hello, my name is Derick Bailey.

I’m a software developer, consultant, screencaster, blogger, speaker, trainer and more. I’ve been working professionally in software development since the late 90’s and have been writing code since the late 80’s, and am currently working as a Developer Advocate for Kendo UI.

My career has spanned many different tools, technologies, platforms and languages. I began working with JavaScript in Netscape 2.0, and found it to be both fun and powerful at the time. For the next 10 years, I had a love/hate relationship with the language, until I was introduced to Backbone.js in mid 2011. I almost immediately fell in love with Backbone, as I saw the potential for large scale, event-driven, composite applications being built in JavaScript with it. I’ve spent my time since then working with Backbone, blogging about it, training other developers to work on it, and building many different add-ons and plugins.

You can find those writings, plus much more, at my blog. I also produce screencasts, provide information about my consulting services, and more, through the following websites:

Employer: Telerik.

Position: Developer advocate for Kendo UI

Personal Company: MutedSolutions.com

Technical Blog: DerickBailey.LosTechies.com

Screencasts (free and paid): WatchMeCode.net

Open Source Projects: GitHub.com/DerickBailey

If you have any questions, comments or concerns, you can contact me at the following:

Email: derick@mutedsolutions.com

Twitter: @derickbailey

Or contact me about the book, specifically:

Email: backboneplugins@mutedsolutions.com

Twitter: @BackbonePlugins

About Jerome Gravel-Niquet

Jerome is the author of the Backbone.LocalStorage plugin, and of chapter 12 of this book.