Introduction To Composite JavaScript Apps

One of the projects I’m working on for a client makes heavy use of Backbone.js to run functionality in the browser. The back end system is built on ASP.NET MVC with an evolving CQRS based architecture. In order to keep the front end as flexible as possible and be able to work with the various back end pieces that are being put in place, I need to follow many of the same patterns and principles in my JavaScript.

Functional Areas Of A JavaScript App

As our applications get larger and larger, it’s important to decouple the various functional areas. Decoupling them – or rather, coupling them correctly – allows much greater flexibility by letting us change how each functional works, without affecting the other areas.

As an example of functional areas, here’s a wireframe of something similar to what I’m currently working on:

Mockup

The application shown here is a very simple item management app. On the left, you have a tree with a hierarchy of items. On the top right, you have a grid view to show the child items of the item that was selected in the tree. On the bottom right, you have an add/edit form.

The important thing to note here is that each of the primary control groups is a functional area of the app and needs it’s own modularized JavaScript code. That is, the treeview, the grid and the add/edit form are all separate areas of functionality within this application. Each of these areas of functionality should be placed in their own file and modularized / decoupled so that none of them knows about the other directly. Doing this will make the over all application easier to manage and maintain, allowing greater flexibility in adding and removing features.

There are likely hundreds of ways that you could build this application, but many of them would lead to large monolithic beasts of unmaintainable code. In recent years though, maintainable and scalable JavaScript has become a hot topic, and there are some good patterns and architectures that have emerged as a result.

I’ve only just begun to explore these patterns and architectures in the last few months, but I wanted to share my perspective and what I’m currently doing.

JavaScript Modules

A JavaScript module isn’t a special construct or keyword in the language itself. Rather, it’s a way to take advantage of functions closures, to create scope. The core of a JavaScript module is usually an “immediate function”:

// an immediate function
(function(){
  // code goes here
})();


// a module with a public API returned
var MyModule = (function(){
  // this variable is private
  var privateVariable = "I'm scoped to the module's internals!";

  // object to return as a public API
  var myAPI = {};

  // a public function on the API
  myAPI.somePublicFunction = function(){
    alert("You called: MyModule.somePublicFunction()");
  };

  // return the public API so it can be accessed
  return myAPI;
})();

The use of the parenthesis around the function definition allows the function to be returned, ready to go (if you forget the parenthesis around the function, you’ll get a syntax error).The second pair of parenthesis immediately execute the returned function. The result can be assigned to a variable, which becomes a reference to the module’s public API (if anything was returned).

There’s been a lot of talk around the web about JavaScript modules already, so I won’t go in to much more detail here. Two of the more recent articles are focused specifically on Backbone, and I highly recommend reading them:

Organizing Your Backbone.js Applications With Modules – This article from Bocoup.com covers the basics of file organization and creating a way to easily reference your modules from other modules, using strings as names.

Organzing your application using Modules (Require.js) – This article from BackboneTutorials covers much of the same ground, but does it using the Require.js framework.

Of course, there’s more than these two methods of modularizing your JavaScript code. You don’t have to stick with the patterns that someone else shows you (include what I’m going to show you) but it’s always a good idea to learn from what others are doing, even if you don’t stick with it.

External / Shared Code

In spite of our desire to separate each of the functional areas of the application, there is a high likelihood that they will need to talk to each other and have access to some of the same code. You’ll also want to have access to some external libraries, such as jQuery, Underscore.js, Backbone.js, or any of a number of other libraries and tools that your code uses.

The usual method of doing this with a plain JavaScript module is to pass the dependencies into the module function. For example, if you need jQuery and Backbone in your module, you might add a $ and Backbone parameters to your module definition. Then you would pass the references to them when you execute the module function:

var MyModule = (function($, Backbone){

  // use $ here. it's scoped locally, now.
  var someEl = $("#someEl");

  // use Backbone here. it's scoped locally, now.
  var MyView = Backbone.View.extend({
    // ...
  });

})(jQuery, Backbone);

The same thing applies to your own modules and libraries. If you have a module defined somewhere else and you know it will be available before the module your currently working on is loaded, you can pass in a reference like this.

(You should also know that once you start heading down this path, you may want to think about using asynchronous module definitions: AMDs. Tools such as RequireJS make AMDs easier to deal with by handling the dependency management, module definition and other common tasks for you.)

Module Initialization

Writing a bunch of modules in a decoupled manner is great, but it introduces another problem: initialization. Most JavaScript applications have some public API that you call when you want to initialize the app and make everything run. If you’re building your app in a modular manner, you don’t want to have to call a separate public API for every module in your system. This would become a nightmare over time by requiring a lot of app initialization code, and worse.

To work around this problem, modules need to have some sort of initialization code in them. Module frameworks like RequireJS have this built in to them. In the app I’m writing, I’m not using RequireJS or any other module frameworks, so I wrote my own registration. It’s pretty simple when it comes down to it. Since every module I write for my app receives an app object, I attached a `addInitializer` function to it. This allows each module to add it’s own initializer code as a callback function, like this:

MyModule = (function(MyApp, Backbone){
  var MyView = Backbone.View.extend({
    // ...
  };

  MyApp.addInitializer(function(){
    new MyView({ 
      // ...
    }).render();
  });
})(MyApp, Backbone);

The application object keeps track of all the callbacks that were passed in to the `addInitializer` function. When the overall application is being initialized, a call to the app object’s `initialize` method will loop through each of the registered module initializers and call them. Each module gets to do it’s own thing and spin itself up.

MyApp = (function(_){
  var myApp = {};
  var initializers = [];

  myApp.addInitializer = function(callback){
    var initializer = {
      obj: this,
      callback: callback
    }
    initializers.push(initializer);
  };

  myApp.initialize(){
    _.each(initializers, function(initializer){
      initializer.callback.call(initializer.obj);
    });
  };
})(_);

Event Driven Architecture

Modules are great for organizing your code, but present a challenge when you realize that you need these modules to communicate with each other. Your code is now separated into different files, encapsulated in different modules, and generally unable to make direct calls in to your other modules and objects like you may be used to. Don’t worry, though. You’re only bumping in to the next steps of decoupling your applications correctly.

There are many different ways that you can solve this problem, of course. One of my favorite ways is the use of an event aggregator. I’ve blogged about the use of an event aggregator with Backbone already. If you need an introduction to the idea, check out that post and some of my many other Winforms / Application Controller posts. The benefit of an event aggregator in this case, is that is gives you a simple, decoupled way to facilitate communication between your modules.

To get started,  you need to have a module or other object that is defined prior to any other modules being defined. This object needs to be passed in to each of the modules that you’re defining, so that these modules can have access to the event aggregator. In my app, I put the event aggregator directly on the top level application namespace, and then pass the namespace object into each of my modules:

MyApp = (function(_, Backbone){
  var myApp = {};

  // the event aggregator
  myApp.vent = _.extend({}, Backbone.Events);

  // the other app initialization code ...

  return myApp;
})(_, Backbone);

MyModule = (function(MyApp, Backbone){
  
  var MyView = Backbone.View.extend({
    initialize: function(){
      MyApp.bind("some:event", this.someCallback, this);
    },
    
    someCallback: function(){
      alert("I'm Doing Stuff!!!");
    }
  });

  // ... other code, including MyApp.addInitializer

})(MyApp, Backbone);

AnotherModule = (function(MyApp){
  var anotherModule = {};

  anotherModule.SomeFunction = function(){
    MyApp.trigger("some:event");
  }

  return anotherModule;
});

// kick it all off and show the alert box
$(function(){
  MyApp.initialize();
  AnotherModule.SomeFunction();
});

Now each of my modules can bind to and trigger events from the event aggregator. This allows one module to send notification of something that happened, without having to know specifically which parts of the application are going to respond to that notification, or how.

One thing you need to think about, in advance, is what events you’re going to be triggering through the event aggregator. It’s a good idea to have thought through this at least a little bit, so that you don’t end up with a giant mess of similar and undocumented events. I made this mistake and paid for it when I couldn’t figure out which events needed to be fired, when. By taking the time to think through which events needed to be fired when, though, I was able to plan the communication between my modules, document the catalog of events, and clean up the number of events that were being used. Having this documented is important so that other developers (or you, a month from now) can see if there’s already an event that has the semantics they need, when writing new code.

Runtime Packaging

Once you have all of these pieces in place, you need to pull them all together and send them down to the browser. You could go ahead and reference each individual JavaScript file from your HTML. This would technically work, but would cause performance problems for the browser and end user. Each file that your reference requires another request to the server, which requires more time to download and potentially blocks another part of the app from loading or running (once you reach the magic limits of how many requests a browser is allowed to make).

To solve this problem, you need to use a packaging system. These systems will take all of the files that you specify, bundle them into a single file, optionally minify the whole thing and then provide that one file as a single resource for the browser. RequireJS has an associated optimizer to handle this. Rails 3.1 has the asset pipeline to do this. There’s the ruby gem “Jammit” which also does this for Ruby / Rails app (and Sinatra, etc). In .NET land, there’s several available including SquishIt. And there are still more in these and in other languages and environments.

If you don’t make use of one of these packaging tools, you’re going to cause problems for you users. Pick one, learn it, use it.

So Much More: Resources

At this point, you should be able to wire together a very simple, composite JavaScript application. This is only the tip of the iceberg, though. There’s so much more to writing well organized, scalable,  modularized and composite JavaScript applications. If you would like to continue down this path, be sure to read the posts I’ve linked to. You’ll also want to check out these resources:

I’m sure there are additional resources as well. If you have any favorite resources for JavaScript architecture and composite application design, please post them in the comments!


Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Derick Bailey

Derick Bailey is an entrepreneur, problem solver (and creator? :P ), software developer, screecaster, writer, blogger, speaker and technology leader in central Texas (north of Austin). He runs SignalLeaf.com - the amazingly awesome podcast audio hosting service that everyone should be using, and WatchMeCode.net where he throws down the JavaScript gauntlets to get you up to speed. He has been a professional software developer since the late 90's, and has been writing code since the late 80's. Find me on twitter: @derickbailey, @mutedsolutions, @backbonejsclass Find me on the web: SignalLeaf, WatchMeCode, Kendo UI blog, MarionetteJS, My Github profile, On Google+.
This entry was posted in Backbone, Composite Apps, Design Patterns, Javascript. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Peter Rust

    Good article, Derick! We’ve been using PrototypeJS’s custom events which fire a real browser event on the document — but your application-specific event aggregator is much cleaner.

    BTW, there’s a typo (“aggretagor”) in the code in one spot.

    • http://mutedsolutions.com Derick Bailey

      thanks! :) 

      There are a handful of other event aggregator / pub-sub tools for JavaScript, too. I tend to use this version with my Bakckbone code ’cause it’s a one-liner to get what I need. But if you’re not using Backbone in a particular app, do a bit of digging and you’ll find plenty available.

      … LOL! “aggretagor” :P Is that an aggressive aligator tiger? :D 

      I updated the gist but it seems to be cached. I think it might take a day or so for the WordPress Gist plugin to refresh it.

  • Jerome

    Great article, I’m going to study it carefully. I wanted to ask you about the example code in 4.js…

    Should this bit: initializers.push(callback); actually be: initializers.push(initializer); ?

    Also, I was wondering what this line does:
    myApp.initialize(){Genuine questions, my javascript skillz aren’t much to write home about! Thanks :)

    • http://mutedsolutions.com Derick Bailey

      D’oh! you are correct. I’ve updated the gist. hopefully wordpress will refresh the cache soon, for the blog post.

  • Justin Wiley

    Awesome article, I’ve been thinking about a similar approach with an existing Rails application that has gone down the CQRS route and now needs “real-time” analytics.

    My biggest challenge so far is rigorous Javascript testing.  Getting our existing Javascript shoe-horned into Jasmine, Coffescript, headless browsers, etc etc etc is difficult, and since there are so many cobbled together systems in play, I’ve found it difficult to troubleshoot errors.

    Would be neat to see a follow up article about how you go about troubleshooting JS, moving an existing application JS towards a testable Jasmine world.

    • http://mutedsolutions.com Derick Bailey

      Hi Justin,

      I have a very basic introduction to Jasmine over at http://watchmecode.net along with a JavaScript Refactoring screencast. I’m not sure if this JS Refactoring would be what you’re looking for. In it, I assume a suite of Jasmine tests exists, and show how to take a monolithic JS object and factor it down into a more cohesive set of simple objects.

      I am planning on doing a screencast on refactoring old / bad JavaScript into something better / testable. I’m not sure when this will be done, though. In the mean time there’s a slide deck I found recently that talks a lot about this type of stuff, at a very simple level: http://www.slideshare.net/fgalassi/refactoring-to-unobtrusive-javascript and I would highly recommend buying Stoyan Stefanov’s “JavaScript Patterns” book for an in-depth, real world look at good JavaScript patterns.

      • Justin Wiley

        Thanks for the heads-up Derick, ill check those out.

  • http://twitter.com/PostHopeLive Paul Barton

    @derickbailey:disqus What is the reason for setting the context of this when executing the callback and not just executing the function?initializer.callback.call(initializer.obj);
    vs
    initializer.callback();

    • http://mutedsolutions.com Derick Bailey

      to set the context of the initialize callback to the module in which the callback was defined. if you just called initializer.callback(), the context would either be the initializer object (which I created in the addInitializer method) or the overall App object where the callback is called from (i’m not sure which off-hand… but it would be one of those two). chances are, you’ll want the initializer callback to fire in the context of the module in which it was defined, so you can access things that may be attached to the module or other objects in the module.

      it’s one of those “just in case” things, really…

  • John Teague

    I use the Module pattern quite a bit, but an import thing to remember is that it creates a singleton and can’t be used in all scenarios and the same care needs to be taken with this Singleton as you would in any other situation.

    • http://mutedsolutions.com Derick Bailey

      it can create a singleton if you have it do that… but it’s just an immediate function, and being a function you can have it return whatever you want, including other functions / constructor functions / object literals (singletons) / or whatever

      • John Teague

        yes it’s an immediate function that returns one thing.  And only one thing, you cannot get more than one instance of that thing during the scope of execution, so it’s a Singleton.  That’s not all bad mind you, just something to be aware of.

        • http://mutedsolutions.com Derick Bailey

          i’m confused… are you calling it a “singleton” because the function can only be executed once? … a singleton function? that’s true… i kept thinking “singleton object” in my head. 

          of course, you could wrap an immediate function in another function … but that would be a memory problem, and would technically be a different function instance every time you executed the outer function. it would have the effect of looking like it’s not a singleton function, though.

          • John Teague

            I think of it more in terms of the classic Singleton object too. I’ve never returned a function from a Module, so I don’t know what that would give you, or what its purpose would be. But you only get one instance of a Module for the screen it was loaded (which in a single page app would mean for the application too), so there are limitations involved with using the pattern and is not appropriate.

          • http://mutedsolutions.com Derick Bailey

            I return functions from modules fairly regularly. it can be used to create private scope for methods and shared variables between object instances. 

            I think I’m still missing the point you’re making… but I don’t think my missing your point is important at this point. It’s likely we’re saying the same or similar things, and I’m just not getting it. :)

  • http://twitter.com/godspeedelbow Eelke Boezeman

    Great article, Derick. I’ve been following you a bit and you provide great insight to Backbone and other javascript stuff. Keep it coming!