Backbone.js (with Introduction to Testing)
Though some of the concepts in this course are still relevant, overall this course does not reflect our current course standards or industry best practices.
Table of Contents
How We Got Here
Backbone Dependencies: jQueryThe DOM is a mess. Backbone depends on jQuery because jQuery is a DOM library and great for manipulating DOM elements.
jQuery ReviewWhile jQuery gives developers a consistent API for DOM manipulation and routines like AJAX, it's not a tool for organizing and managing applications.
Backbone Dependencies: UnderscoreUnderscore is a utility library. It includes useful utilities for Objects, Arrays, Functions, etc.
Single Page ApplicationsWhen approaching single page applications, developers want to remember the experience should mirror that of a traditional web application. For example, including bookmarkable pages/states. A solid understanding model-view-controller principles helps clarify the process of taking server-side MVC techniques and moving them to the client. This transition introduces the concept of a model-view-presenter architecture.
Philosophy, usage, and conventionWhen using Backbone, there is often more than one way to implement a system. Backbone attempts to remain agnostic leaving many of the patterns up to the implementers to figure out. Sam begins with a some jQuery code that displays a list of comments when a "show comments" button is clicked. Since it's writing with jQuery, it's coupled closely with the DOM. There are a number of other issues as well.
Core Backbone ComponentsBackbone consists of models, collections, custom events, sync operations, and views. It works best with a RESTful architecture and if you're willing to do thing the "Backbone way".
Overview of the Comments Application
Comments Project SetupThe project file can either be view on jsBin or by cloning Sam's GitHub repository. Sam begins by describing the setup and functionality of the application. Sam also gives a quick overview of the code structure.
Comments Model, Collection and ViewThe comments Model will represent the data and help with validation. The Collection represents a list of Model objects. The View will display the collection in the markup.
Comments Application ViewThe overall comments application will have a Backbone View responsible for the entire comments section. The element for this view is going to be the ".comments" class. This allows for a very flexible design and reusability.
Summarizing the functionalityA Backbone collection's add method receives a model object. This triggers the render method for that model's view. All functionality is globally declared inside a single JS file. Later, Sam will demonstrate a better architecture.
Comments Application Audience QuestionsWhile answer a question about model objects, Sam demonstrates some debugging techniques and the debugger keyword.
Comments Project Setup and DependenciesSam prepared a blank starter project tin the project-template branch of his GitHub project. Sam also introduces a few third-party libraries he recommends during development including RequireJS, Bower, and Grunt
Advanced Feature DemonstrationThis, more robust, comments application now has a login system, ability to edit/delete comments, and a "Zen interface" for adding comments. Sam will be diving into these advanced features and how they were implemented with Backbone.
Code WalkthroughThe main.js file is the entry point for the application. From there, RequireJS includes the necessary dependencies and wires up the application. Sam also demonstrates the templating system within the views.
Additional Code FeaturesSam introduces a few additional topics that will be live-coded later in the course. This includes a more robust validation system and an AMD module examples. Sam field a few additional ES6 questions during a brief break as well.
Backbone Models In-Depth
Models In-DepthAs covered earlier, Models represent a single resources from the server and are useful for storing data in-memory within an application. Models can be made flexible with helper methods like parse, toJSON, and sync.
Model.parse & Model.toJSONThe parse method gives developers the opportunity to manipulate data as it's returned from the server. This could be used for simply formatting the returned data or creating additional model objects. The toJSON method does the inverse of the parse method. It allows developers to add omitted model objects back into the prototyped toJSON output.
Defining ModelsWhen defining models, data structures do not need to be predefined. However, predefining attributes allows developers to set default values. The "on" method can be used to add listener events for Model attributes. Models also have methods like "save" which enable persistence on the server.
Using RESTful APIsREST is a way to architect data and a means for traffic to act on that data. Backbone works well with REST APIs for data communication. Sam fields an audience question on why "listenTo" is preferred over "on".
Live Coding: REST APIsUsing Mozilla Persona, Sam begins coding a model object that will communicate with the Persona APIs for managing login information. Setting the URL property within that model is the first step in the communication.
Persona QuestionsSam addresses some audience questions regarding the personal integration including how to set up persona with the course files.
Backbone Views In-Depth
Views & TemplatesIn Backbone, views are really versatile. They are simply an object that represents the presentation of a model so they can adapt to many MV* patterns. Templates are included in view objects. Backbone will work with any templating library because all Backbone requires is an HTML fragment. However, including templates inside a script tag can be expensive.
Rendering TemplatesIncluding templates in individual files moves them from the DOM and into a middle-ware pattern. This is because module loaders like RequireJS can better optimize your templates in production. The primary use of templates to get away from concatenating long strings of HTML. They also make rendering views easier.
Responsible RenderingSolid application design means applying the single responsibility principle and interface segregation. Also, organizing your application around a view allows for more reusability and a more modular approach.
Views Audience QuestionsSam addresses some audience questions on using views versus routers and also on lazy loading data.
Backbone Collections and Routers In-Depth
CollectionsWhen creating collections, you are able to pass a single model or an array of model objects. The models property within a collection give you a number of useful methods for working with the data. Collections also have a number of useful methods for adding, and removing data. These methods have additional parameters that can be useful when manipulating models within a collection
Retrieving Model DataMethods like get, at, where, and pluck help retrieve model data from within collections. When you have access to a model's ID, using the get method is the most efficient method to use. There are a number of other Underscore aliases available within Backbone. This includes iteration methods, transforms, and many others.
Syncing Data with the ServerThe "url" property specifies a RESTful endpoint. The "fetch" method invokes the RESTful data request. Backbone's "sync" method is called every time model data is written or read. Overriding this method helps developers add custom implementation to every service call.
Routing BackgroundRouting is the ability to look at a URL within a web application and recreate a state. Most client-side techniques use a hash(#) to determine a specific state. These routes are called hash fragments. Hash fragments have evolved into the HTML5 history API. This HTML5 history API enabled more advanced routing because full URLs can be used, as opposed to hash fragments.
Backbone RouterBackbone routers are hash-maps that tie a specific URL to a function call. The URLs specified in the router use regular expressions for more complex formations. After all routes have been defined, calling Backbone.history.start will begin using hash-change routing to managing page-to-page navigation.
Router Code WalkthroughSam walks through a routing example for a login scenario. The application contains routes for logging in, logging out and different authentication levels for each user.
Testing Backbone Applications
Backbone API Project IntroductionFor this live-coding session, a jsBin project has been set up. Data will be pulled from the quickleft.com server. Sam gives a little background information on the code setup. Sam fields a few questions from the audience on architectures and managing larger applications.
Writing TestsThe most basic test developers can write is an assertion based on the application existing. Tests are typically much more specific that that, however. Sam demonstrates adding test cases inside the comments application and how to handle side-effects. Using the before identifier can allow variables to be declared and later reused inside individual test cases. The context keyword can be used to isolate a group of tests.
Using Sinon.jsSinon.js can be used to "spy" on methods or watch when they are called. Testing method call often triggers side effects. In that case, Sinon.js can be used to "stub" the method or block it from running.
Testing Event HandlersTesting event handlers can be tricky because they are reliant on the DOM. The best way to test them in isolation would be to either trigger the event or pass the event a mock-object. While debugging some of the testing scripts, Sam discusses a few troubleshooting resources for writing unit test including the Sinon.js documentation. He also discusses some drawbacks to consider when writing tests.
Testing ViewsWhen testing views, one important assertion is to verify the required model object is passed to the view when it initializes.