Backbone: A view and ownership of it’s element

When writing modern applications using Backbone I often find myself relying on past experience with object oriented architectures to help me structure an application. This is rather natural as the first programs I ever wrote were in an object oriented language (MOO for the curious). While often hailed as one of the primary contributions of the object oriented paradigm to modern software development, encapsulation actually has a much more varied history, and it is encapsulation I want to talk about here.

When writing an application in Backbone one of the primary abstractions is that of the view – I happen to also use AMD in my applications so I’ll leverage that syntax here. Here’s an example of a simple view:

define( ["jquery", "underscore", "backbone"], 
   function( $, _, Backbone ) {
         var myView = Backbone.View.Extend({
            render: function() {
               $( '#content' ).html( "HELLO WORLD!" );
            }
      });
 
      return new myView;
   }
);

I’ve seen dozens of examples and tutorials that take this approach to views. On the outside there is nothing immediately wrong with it – clearly there is encapsulation, we define a function which acts as a closure denoting the ‘module’, and we give it some dependencies. We further have a view object – and in fact we have a single view object, as returning a new instance of myView gives us something very much akin to a typical singleton pattern.

However, when I look at examples like this what I see is a sham of encapsulation – we have split our code, but we have not placed proper boundaries on the actual impact of that code. Namely, this line:

$( '#content' ).html( "HELLO WORLD!" );

breaks what I see as a good structural principle. By making use of jQuery to select an element on the page, the view now has to ‘know’ things about its outside world that it otherwise would not need to be privy to. Additionally, it puts constraints on any application that would use this model – and encourages an almost spaghetti effect of interdependencies (how do I know somebody else isn’t modifying the html of the content element?).

I think views should maintain two major properties to be effective units of encapsulation:

  1. The view should not interact with DOM elements outside of itself
  2. The view should own its element

Taken together, we come up with a paradigm that looks more like this:

define( ["jquery", "underscore", "backbone"], 
   function( $, _, Backbone ) {
      var myView = Backbone.View.Extend({
 
         tagName: 'div',
 
          id: 'MyViewDiv',
 
          className: '',
 
          render: function() {
             $( this.el ).html( "HELLO WORLD!" );
             return this;
          }
      });
 
      return new myView;
   }
);

Some higher level object that owns content might then do something like this:

require( [ "views/myView" ],
   function( myView ) {
      $( "#content" ).html( homeView.render().el );
   }
 );

In such a structure all element lookups could also denote the this.el as a parent element, ensuring that you don’t run into code that modifies similarly named tags written out by some other poor unsuspecting view.

In either case, however you decide to approach it and how you want to express views in a backbone application, it is important that consistency be attained – nothing would be more confusing that to have a mix of views that live independently and views that act as all-knowing modifiers of the page around them.

This entry was posted in backbone.js, encapsulation, Javascript. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *


*

* Copy This Password *

* Type Or Paste Password Here *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>