A diabolical herd of pigs stole all of the front-end architecture from an innocent flock of birds and now they want it back!
Check out the series introduction post for a list of all the birds and their attack powers.
Black Bird Attacks
In this post we will take a look at the Black Bird who will use the organized approach of the Backbone.js bomb to fight these porkers. Slowly, one by one, the birds will take back what it theirs to keep!
What Was Stolen by the Pigs?
The birds used to write their jQuery code like it was a tangled smorgasbord of worms. They would mix up their views, models, and presenter logic all together in a big interconnected pile of grubs. After a while one of their ancestors, a Black Bird, introduced the Backbone.js library and showed them a different way to think about developing front-end web applications. However, during a recent invasion the pigs stole Backbone.js from the birds and carried it back to their filthy sty.
One of the black birds has been tasked to reclaim what has been stolen. He will use his explosive power of organization to help destroy the pigs in order to take back what is theirs.
Tangled Smorgasbord of Worms
Let’s take a look again at the following application that the Blue Bird dealt with in a previous attack. Instead of adding messages to untangle the mess we are going to introduce how using Backbone.js can help us out. Here is the running application below…
It appears Plunker is not embedding correctly at the moment. The application is a simple Netflix search interface that will show the results from Netflix. If Plunker doesn't start working soon I will move the demo somewhere else. Sorry for the inconvenience.
And to refresh your memory, here is the supporting code used for the above web application. You should notice that a lot of concerns are all being mixed together (DOM events, Modifying the View, AJAX Communication, etc…)
Do you see the problem? It is so tempting to write code like the above, but I hope you see that it can be a bear to work with and maintain. Don’t worry, we have all written code just like the above. The good news is that we don’t have to continue to write it that way. Let’s take a look at what Backbone.js is and how it can help us out in this situation.
There are many other MV* front-end frameworks (Knockout, or AngularJS, EmberJS, & others) that could also bring structure to the above code. I would encourage you to pick a tool that you can be productive with and get comfortable with it.
Backbone.js has several pieces that can all work together to make a web application. You don’t have to use all of these components, but they are available if you choose to use them.
- Model - Represents data and logic surrounding it
- Collection - Ordered sets of Models
- View - A module backed by a Model with a render method
- Router - Mechanism to provide linkable, sharable URLs
- Event - Observer Eventing module
- History - Provides the ability to maintain history (back button support)
- Sync - Extendable component providing RESTful communication to the server
Refactoring the Tightly Coupled Code
Let’s take a stab at refactoring the above jQuery mess and use Backbone.js to split out some of the various concerns.
I’m not going to dive into all of the above pieces in this post, but will focus on 3 of the main pieces (Models, Collections, and Views). I’ll touch on some of the Sync concerns, but as part of the other topics. I’ll have resources listed at the end if you want to dig deeper into any of these topics.
Before we get into the Models, Collections, and Views I want to show you how we took out all the scripts from the index.html page and used RequireJS to help us out.
If you've never seen RequireJS before then you might want to check out the previous Yellow Angry Bird Post about RequireJS.
The above code is defining the paths for jQuery, Underscore, Backbone, Postal, and Bootstrap. We needed to shim Underscore, Backbone, and Bootstrap since they are not defined as AMD modules.
require function is called to request a set of dependencies before the callback is invoked. At that point, jQuery and all the other views and models will be ready for usage!
We are going to make 2 models (Search and Movie) to represent the above application.
The following Search Model is really simple and its main job is to respond when the
term property has changed. We are using Backbone’s events (Observer Events) to listen to changes on the model and then propagating the message to Postal.js (Mediated Events). For more information about those terms and how they are different you can reference the Blue Angry Bird Post about events.
The following Movie Model doesn’t have a lot going on as well. It’s main purpose is to parse the data returned from the server and map the results to something a little more manageable. In this case we are only concerned with the
As we described above, collections are just a set of models. The following code is just a set of Movie models. The collection is where you define where to get the list of models from the server. The back-end for this application is Netflix and their endpoint is a little complex so we are using a function to dynamically build that URL. We also defined a
parse method to get directly to the array of contents that will be mapped to
Movie models. Since this AJAX call will be using JSONP we also needed to override the
sync method and provide some additional options.
I see the View as more of a Presenter than the typical MVC View you might normally think of. Anyway, We have 2 views in this application that we will briefly look at.
SearchView handles the interactions with the DOM and the Model. The
events property primarily is used to listen to DOM events and in this case is watching for clicks on the button or previous search links. Changes to these elements will be stored in the model as
initialize method sets up some events listening for changes in the
term property. If
term changes, then portions of the UI will change accordingly.
MovieView below is a little different than the above view. The first thing to point out is the weird
text!movie-template.html. I am using the
text.js plugin for RequireJS that let’s us pull text resources as part of the dependency chain. This is really helpful for markup files used when using a templating engine or possibly a CSS file that is associated with a particular widget. Inside of the
initialize method we are subscribing to a change in the term and then asking the collection to
fetch the information from the server. The
render method gets called after the data is retrieved from the server and we use Underscore to template the results to the DOM.
The following is the template file in case you were wondering. I’m using Underscore’s templating engine which is similar to John Resig’s micro-templating implementation that he wrote years ago. There are other templating libraries available, but I used this one because it comes with Underscore which is a prerequisite for Backbone. If I needed something more featured I would have used Handlebars instead, but that is a story for another Angry Bird ;)
I only scratched the surface on all the things you can do with Backbone.js. If you are interesting in learning more about these concepts you may want to look at some of the following resources.
- Backbone.js API
- Annotated Backbone.js Code
- Backbone Extensions, Plugins, & Resources
- Backbone Boilerplate
- Backbone Fundamentals eBook by Addy Osmani (@addyosmani)
- Peep Code: Backbone.js Video Series by Geoffery Grosenbach (@topfunky) and David Goodlad (@dgoodlad)
- The Pragmatic Bookshelf: Hands-on Backbone.js by Derick Bailey (@derickbailey)
- Backbone.js Screencasts by Joey Beninghove
- Pluralsight: Backbone.js Fundamentals by Liam McLennan (@liammclennan)
- The Skinny on BackboneJS by Ben Howdle (@benhowdle)
- Backbone Tutorials
- Backbone.js Tutorials via Nettuts
- Exploring Backbone.js Series by Jack Franklin (@jack_franklin)
space barto launch the Black Bird and you can also use the arrow keys.
Front-end web applications can get complicated quickly. Before you know it you have a pile of interconnected mess if you are not careful. Thankfully Backbone.js provides components to help you split out your application into consumable pieces that each have their own purpose. Thank you Black Bird for returning Backbone back to the birds. They will be able to rest easier knowing things are organized and in their proper place.
There are many other front-end architecture techniques that have been stolen by the pigs. Tune in next time as the next Angry Bird takes its revenge! Dun, dun, daaaaaaa!