You are currently browsing the Software Engineering archives.

Decoupling Backbone Modules

Wednesday, April 18th, 2012

One of the principle design philosophies I have advocated over the years, especially through various articles on this site, has been the importance of decoupling. And while I could go into significant detail to elaborate on the importance of decoupling, suffice it to say that all designs – from simple APIs to complex applications – can benefit considerably from a decoupled design; namely, with respect to testability, maintainability and reuse.

Decoupling in Backbone

Many of the examples which can be found around the web on Backbone are intentionally simple in that they focus on higher level concepts without diverging into specific implementation or design details. Of course, this makes sense in the context of basic examples and is certainly the right approach to take when explaining or learning something new. Once you get into real-world applications, though, one of the first things you’ll likely want to improve on is how modules communicate with each other; specifically, how modules can communicate without directly referencing one another.

As I have mentioned previously, Backbone is an extremely flexible framework, so there are many approaches one could take to facilitate the decoupling of modules in Backbone; the most common of which, and my preferred approach, is decoupling by way of events.

Basic Decoupling with Events

The simplest way to facilitate communication between discreet modules in Backbone is to have each module reference a shared event broker (a pub /sub implementation). Modules can register themselves to listen for events of interest with the broker, and modules can also communicate with other modules via events as needed. Implementing such an API in Backbone is amazingly simple, in fact, so much so that the documentation provides an example in the following one liner:

Essentially, the dispatcher simply clones (or alternately, extends) the Backbone.Events object. Different modules can reference the same dispatcher to publish and subscribe to events of interest. For example, consider the following:

In the above example, the Users Collection is completely decoupled from the UserEditor View, and vice-versa. Moreover, any module can subscribe to the 'users:add' event without having any knowledge of the module from which the event was published. Such a design is extremely flexible and can be leveraged to support any number of events and use-cases. The above example is rather simple; however, it demonstrates just how easy it is to decouple modules in Backbone with a shared EventBroker.

Namespacing Events

As can be seen in the previous example, the add event is prefixed with a users string followed by a colon. This is a common pattern used to namespace an event in order to ensure events with the same name which are used in different contexts do not conflict with one another. As a best practice, even if an application initially only has a few events, the events should be namespaced accordingly. Doing so will help to ensure that as an application grows in scope, adding additional events will not result in unintended behaviors.

A General Purpose EventBroker API

To help facilitate the decoupling of modules via namespaced events, I implemented a general purpose EventBroker which builds on the default implementation of the Backbone Events API, adding additional support for creating namespace specific EventBrokers and registering multiple events of interest for a given context.

Basic Usage

The EventBroker can be used directly to publish and subscribe to events of interest:

Creating namespaced EventBrokers

The EventBroker API can be used to create and retrieve any number of specific namespaced EventBrokers. A namespaced EventBroker ensures that all events are published and subscribed against a specific namespace.

Namespaced EventBrokers are retrieved via Backbone.EventBroker.get(namespace). If an EventBroker has not been created for the given namespace, it will be created and returned. All subsequent retrievals will return the same EventBroker instance for the specified namespace; i.e. only one unique EventBroker is created per namespace.

Since namespaced EventBrokers ensure events are only piped thru the EventBroker of the given namespace, it is not necessary to prefix event names with the specific namespace to which they belong. While this can simplify implementation code, you can still prefix event names to aid in readability if desired.

Registering Interests

Modules can register events of interest with an EventBroker via the default on method or the register method. The register method allows for registering multiple event/callback mappings for a given context in a manner similar to that of the events hash in a Backbone.View.

Alternately, Modules can simply define an “interests” property containing particular event/callback mappings of interests and register themselves with an EventBroker

For additional examples, see the backbone-eventbroker project on github.

Preprocessing Modules with RequireJS Optimizer

Saturday, March 24th, 2012

RequireJS provides an effective means of bundling an application for production deployment by way of the RequireJS Optimizer; which allows for optimizing, concatenating and minifying modules via Node or Rhino.

The Optimizer is quite powerful insofar that fine-grained control over various aspects of the optimization process can be implemented with relative ease. One such example is the ability to specify a callback function to be invoked for each module in the build prior to optimization. This essentially provides the necessary hooks needed to implement a preprocessor.

The onBuildWrite option

The optimize method of the RequireJS Optimizer accepts an onBuildWrite option which allows for a callback to be specified. The callback will be invoked prior to serialization of each module within the optimized bundle. Callbacks receive the name, path and contents of the module; and, are always expected to return a value.

For example, consider the following build configuration which demonstrates a basic onBuildWrite callback that simply logs the name of each module processed by the build to the console and, returns the module’s content unmodified.

Using the above configuration, when executed against a (contrived) example consisting of just a single module, “ModuleA”, in Node, it would output the following to the console:

If we were to print out the contents of the files we would see something like this:

With this in mind, a basic preprocessor can be implemented quite easily using the onBuildWrite option. Assume the main.js script has a token placeholder for the build version like so:

We can implement a simple preprocessor which replaces the #version token with a build date as follows:

The above onBuildWrite callback logs the original contents, replaces the #version token with the current date, logs the result and returns the processed content. The output of which would be similar to the following:

As can be seen in the above examples, implementing a basic preprocessor is rather simple to accomplish with the RequireJS Optimizer. The ability to do so allows for some interesting possibilities and is certainly something worth checking out if you are leveraging AMD via RequireJS.

You can fork an example implementation at requirejs-preprocessor-example.

Jasmine matchers for Sinon.JS

Wednesday, March 7th, 2012

Lately I have been finding myself writing custom Jasmine matchers which wrap the Sinon.JS API as a convenience. After repeating this process quite a few times I took a step back to see if there was a similar solution already available.

After a brief search, I quickly came across jasmine-sinon which, to my surprise, provides a very similar matcher API to that which I had began implementing. This library really is quite nice as it essentially provides matchers for all common Sinon.JS spies, stubs and mocking use-cases. I am sure jasmine-sinon has saved many developers a lot of time by not having to write their own custom matchers as it has for me.

And so, if you are using both Jasmine and Sinon.JS, and find yourself writing convenience matchers to simplify Sinon.JS integration, jasmine-sinon is an excellent addition which compliments both and is certainly worth considering.

IIFE (Immediately-invoked Function Expressions)

Saturday, February 4th, 2012

When developing Mobile Web Applications, even the seemingly marginal micro-optimizations can result in a noticeable performance improvement over time and, therefore should be implemented where possible. One could also argue (and rightly so) that this same principle applies when developing Web Applications on the Desktop; however, in the context of Mobile Web Experiences, such optimizations are essential, perhaps even obligatory on the developers part.

In a previous post from a few months back I discussed some of the benefits of function overwriting in JavaScript. One similar performance optimization I regularly employee is that of One-time function initializations.

Conceptually, an IIFE/em> is a rather simple pattern which can be broadly described as follows:

  1. An Immediate Function / Self-executing Function performs some initial test conditions.
  2. The Immediate Function returns an anonymous function which, in turn, returns the results of the test conditions. Alternately, the Immediate Function can just return the test condition results.
  3. The anonymous function returned is assigned to a function expression or, the test condition results are assigned directly.

An example in code illustrates just how simple this pattern is:

Practical implementation example:

Implementing Immediately-invoked Function Expressions are quite useful in many situations. Specifically, they are of most value when implemented for use-cases where conditions are too complex to assign to a variable directly and, when the conditions tested only need to be evaluated once, after which re-evaluating the condition would be redundant and unnecessary – such as certain feature detections.

As a general rule of thumb, if a condition or set of conditions can be tested once; that is, they are guaranteed to not change during the execution of the application and, the tests are too complex to maintain if directly assign to a variable, then implementing One-time function initializations are a small, yet simple and practical optimization.

AT&T Best Practices Guide for App Development

Sunday, January 15th, 2012

When considering the various best practices surrounding the design of Mobile Web Experiences and Architectures, such works as the W3C’s Mobile Web Application Best Practices guide, or the excellent Mobile Web Best Practices site, and of course, the seminal text, Mobile First, are likely to come to mind. The concepts and strategies presented in these works are a staple in the design of many modern Mobile Web Experiences and are without question an invaluable resource. In addition to these and other similarly related works, another new and valuable resource has been made available from a very important player in the Mobile Space indeed – an actual Wireless Carrier, AT&T.

Recently, I was contacted by a representative of the AT&T Developer Program informing me of the research conducted by the AT&T Research Labs and, the subsequent resources made available by AT&T as a result of their findings. Since I was unaware of this work, I was very interesting in learning more and, after reading the introductory statements, I was quite eager to apply AT&T’s recommendations as well; to quote specifically:

We quickly saw that a few, simple design approaches could significantly improve application responsiveness.

Having read through the material in it’s entirety (provided below) I must say I am rather impressed. The information provided has very real and practical implications on the design of Mobile Web Applications. Specifically, I found the clear and concise explanation of the underlying implementation of the Radio Resource Control (RRC) protocol to be particularly relevant and useful. RRC is by far one of the most important design factors to consider in terms of battery life and Application responsiveness and, as the research suggests, this may not have been common knowledge.

By far, the most interesting and notable aspect of the AT&T Research Lab’s work in this area is the fact that all of the information provided is applicable in the context of all Wireless Carriers, not just AT&T. That is, the recommendations given, such as those regarding the RRC State Machine, for example, are all based on carrier-independent standards and protocols implemented by all Wireless Carriers. As such, understanding the implementation specifics and recommendations provided is certain to prove valuable for all users of your Application, regardless of their Carrier.

If you haven’t all ready, I highly recommend reading and applying the principles provided by AT&T’s research to your current and future Mobile Web Application Designs.

AT&T Research Labs: Mobile Application Resources

Build Efficient Apps
Profiling Resource Usage for Mobile Applications: A Cross-layer Approach

Circumventing Conditional Comparisons

Friday, October 14th, 2011

Often during the course of my day I come across code which evaluates the same conditional comparisons in multiple contexts. Understandably, this is rather typical of most software systems, and while it may only introduce a negligible amount of technical dept (in the form of redundancy) for smaller systems, that dept can grow considerably in more complex, large scale applications. From a design perspective, this issue is applicable to nearly every language.

For example, consider a simple Compass class which defines just one public property, “direction” and, four constants representing each cardinal direction: North, East, South and West, respectively. In JavaScript, this could be defined simply as follows:

Technically, there is nothing problematic with the above class signature; the defined constants certainly provide a much better design than conditional comparisons against literal strings throughout implementation code. That being said, this design does lead to redundancy as every instance of Compass which needs to evaluate the state of direction requires conditional comparisons.

For example, to test for Compass.North, typically, client code must be implemented as follows:

Likewise, simular comparisons would need to be implemented for each cardinal direction. And, while this may seem trivial for a class as simple as the Compass example, it does become a maintenance issue for more complex implementations.

With this in mind, we can simplify client code by defining each state as a specific method of Compass. In doing so, we afford our code the benefit of exercising (unit testing) Compass exclusively. This alone improves maintainability while also simplifying client code which depends on Compass. As such, Compass could be refactored to:

Based on the above implementation of Compass, the previous conditional comparison can be refactored as follows:

Comparator API

To simplify implementing conditional comparisons, I have provided a simple Comparator API that defines a single static method: Comparator.each, which allows for augmenting existing objects with comparison methods. Comparator.each can be invoked with three arguments as follows:

type

The Class to which the comparison methods are to be added.
property
The property against which the comparisons are to be made. If the property has not been defined it, too, will be added.
values
An Array of constants where each value will be used to create a new comparison method (prefixed with “is”). If the constants specified are Strings, typically an Array containing each constant should suffice. For example, passing [Foo.BAR] where BAR equals “Bar” would result in an isBar() method being created. To specify custom comparison method names, an Object of name/value pairs can be used where each name defines the name of the method added and the value is the constant evaluated by the method. This is useful for constants which are not strings. For example, {isIOS421: DeviceVersion.IOS_4_2_1} where IOS_4_2_1 equals 4.2.1 would result in an isIOS421() method being created.

Taking the Compass example, the previous comparison methods could be augmented without the need to explicitly define them via Comparator.each:

The above results in the comparison methods isNorth, isEast, isSouth and isWest being added to the Compass type.

Comparator: source | min | test (run)