Thursday, October 27, 2011

Fancy Names for Simple Backbone.js Techniques

‹prev | My Chain | next›

One of the dumber things that I have been doing in my Backbone.js application is hard-coding the element that holds the application:
        var CalendarMonth = new (Backbone.View.extend({
          el: $('#calendar'),
          // ...
That does work. It attaches the calendar to my very simple HTML without a hitch:
  Funky Calendar
  <span class="year-and-month"></span>

<div id="calendar"></div>
The problem is mostly one of maintenance. Re-use is also going to be a problem, but my main problem with the current approach is that my HTML and my Javascript are in separate files. If I want to change the id attribute, I need do it in two files. Two files need changing and I have to dig through the Javascript to find where that change would need to be made (currently line 94).

The solution, of course, is to pass the element to the main application constructor:
    window.calendar = new Cal($('#calendar'));
To support this, my constructor now needs to accept a root_el parameter, which it passes along to the top-level Application view:
    var Cal = function(root_el) {
      var Models = (function() { /* ... */ })();

      var Collections = (function() { /* ... */ })();

      var Views = (function() { /* ... */ })();

      var Routes = Backbone.Router.extend({ /* ... */ });

      var Helpers = (function() { /* ... */ })();

      // Initialize the app
      var year_and_month = Helpers.to_iso8601(new Date()).substr(0,7),
          appointments = new Collections.Appointments({date: year_and_month}),
          application = new Views.Application({
            collection: appointments,
            el: root_el

The Application then uses that element to attach everything else.

Passing the root element along like this is also known as injecting the dependency on the root element into the constructor. Or dependency injection for short.

The main benefit of dependency injection is that I no longer need to touch the Javascript if I change the HTML. If I change the ID to calendar-widget in the HTML, all that has to change is the <script> tag (which is also HTML):
<script type="text/javascript">
  window.calendar = Cal($('#calendar-widget'));
It also makes testing Backbone applications easier if the DOM element is more flexible.

Dependency injection is one of those things that everybody already does, but doesn't realize that it has a fancy name. Still, it is pretty darn useful—especially when coupled with last night's precipitation pattern, but that is a tale best told in Recipes with Backbone!

That's a fine stopping point for tonight. Up tomorrow: I get started with model relations. Should be fun!

Day #187

No comments:

Post a Comment