Tag Archives: javascript

Javascript Design Patterns: Strategy

For a quick assignment I was asked to write the following program:

In the language of your choosing build an application that, given an English language document as input, builds a data structure capturing the count of each word in the document.

Bonus:
Create an inverted index as well: a mapping of the words to absolute positions in the document.

As context, this is a foundational algorithm for search systems and information retrieval. Be sure to consider accuracy, complexity, and intent in the design of your program.

The last phrase was the one that got me thinking.
This sounded a little vague, so I started thinking what kind of design I can implement that would be flexible enough so I can apply the algorithms later.
This kind of program usually runs on the back end using Java/Python/etc, but obviously, the language of my choice was javascript.

I started by defining a master processor:

var Processor = function(doc) {
    this.doc = doc;
};
Processor.prototype.parse = function(parser, sorter) {
    data = parser.parse(this.doc);
    if (sorter && typeof sorter.sort === 'function') {
        return sorter.sort(data);
    }
    else {
        return data;
    }
};

This processor gets a document (in our simple example, a long string) and has parse method, which accepts a “parser” object that has a parse() method and an optional “sorter” object that has a sort() method.
As the names suggest, the former will parse the document, and the latter will sort the results.
This use of the Strategy Design Pattern will allow the application to be flexible for algorithm changes, in the future.

First, I defined an abstract Parser object.
This object is responsible to convert the input to a standard format, and apply an algorithm

var Parser = function(){};
/**
 * The implementation will return an object literal 
 * with the format {word: num, word: num ...}
 * 
 * @param str {String}
 * @returns {Object}
 */
Parser.prototype.parse = function(str){
    throw 'please extned abstract object';
};

/**
 * Convert an object literal into a sortable array
 * with the format [[word, num], [word, num], ...]
 * 
 * @param data {Object}
 * @returns {Array}
 */
Parser.prototype.convert = function(data) {
    var arr = [],
        data = data || {};
    for(var key in data) {
        if(data.hasOwnProperty(key)) {
            arr.push([key, data[key]]);
        }
    }
    return arr;
};

My next step was defining the parsers I was requested to write:
One for capturing the count of each word in the document:


var CountParser = function(arr) {
this.arr = arr;
};
CountParser.prototype = new Parser; // extend the base parser
CountParser.prototype.parse = function(str) {
var value, i, l, data = {},
arr = str.split(/[\s]+/);
for(i=0, l=arr.length; i

Backbone.js URI Sync Adapter

I am working on a backbone based search page, and was trying to figure out what would be a simple way to have both a state model and a URI that represents that state of the page (the search string, search parameters, user preferences, etc.).

Thinking of mixing backbone routes and the application models seemed like an overkill, and would force me to handle everything through a route or an event.

After a short struggle, I realized that the best case would be to have a model that keeps me in model land, but has the representation in the URI, and came out with Backbone URI Storage.

The concept is very simple, and works like charm – use a standard backbone model, enjoy data binding, and simply hook the model in the URI.

var State = Backbone.Model.extend({
    sync: uriSync
});
var Search = Backbone.Model.extend({
    url: '/rest/v1/search/';
});

And now, I can update the application state when my search changes:

var state = new State({id: 'search-page'});
var search = new Search();
search.on('change', function(){
    state.save(search.toJSON());
});

A working code example can be found here.

Its as simple as that!

Backbone.js computed properties

A simple yet powerful way to create backbone model calculated fields or “macros”

For one of our applications, we needed a way to store “macros” in backbone models, that will return a calculated value, based on values we have in the model fields.

I came up with a quick solution that seems to be good enough so far.
the concept is, the same way you can set anything to a field value, a function in javascript IS a value, so nothing holds you from setting a function in a field:

var myModel = new Backbone.Model();
myModel.set('func', function(){
    return 'hello calculated field!';
}, {silent: true}); // bypass the change event

Later on we can get the value of this function with a call such as:

var value = myModel.get('func').call(myModel);

This works, but it is not very convenient.
I wanted an automated way to use calculated methods without any side effects, which will include the field results in the model signature.
JSON.stringify ignores functions so consider this:

    
var foo = {
    bar: function(){
        return 'bazz';
    }
};
JSON.stringify(foo); // prints "{}"

Based on that, the original backbone toJSON will just work as is, ignoring our macros.
However, if we wanted to have the values our macros returns in our signature, we want to make sure it is being called, returning the resut of the value rather than the function.

I came out with this:

var BaseModel = Backbone.Model.extend({
  get: function(attr) {
    var value = Backbone.Model.prototype.get.call(this, attr);
    return _.isFunction(value) ? value.call(this) : value;
  },
  toJSON: function() {
    var data = {};
    var json = Backbone.Model.prototype.toJSON.call(this);
    _.each(json, function(value, key) {
      data[key] = this.get(key);
    }, this);
    return data;
  }
});

As the code tells us, in our new get method we are returning values of calculated fields, and in our new toJSON method we are including computed properties by values.

This could be great, but we have to remember that model.toJSON() is what Backbone sends back to the server when we perform a save operation, so it may be a good idea, depending on the server implementation, to exclude all computed properties from the model signature:

toJSON: function() {
  var json = Backbone.Model.prototype.toJSON.apply(this, arguments);
  _.each(json, function (value, key) {
    if (typeof value == 'function') {
      delete json[key];
    }
  });
  return json;
}

An implementation could look like:

var MyModel = BaseModel.extend({
    defaults: {
        avg: function(){
            return (this.get('min') + this.get('max')) / 2;
        }
    }
});
var myModel = new MyModel({min: 1, max: 17});
var avg = myModel.get('avg'); // 9

One “drawback” we need to be aware of, is due to the nature of the implementation, you can not bind to change events on this field, since the value stays the function and what changes is the computed value it returns.

Simple? Powerful?

EDIT 3/14/2012:
If you do want to observe changes when a computed property value changes, you will need the system to be aware of which attributes are affecting it state.
This could be done like that:

var avg = function(){
    return (this.get('min') + this.get('max')) / 2;
};
avg.attributes = ['min', 'max'];
myModel.set('avg', avg);

Now we have a way to track which fields are impacting our computed property.
What’s left to do is observe changes on these fields, and fire a change event on our property when these happen.
We could attach the event listener on the “set” method, but that would mean we will need to keep track on when we unset, reset, etc and remove that listener.

A cleaner (yet a little less efficient) approach would be to listen to all change events, and figure out upon it if a related field had changed.
This could be done like this:

myModel.on('change', function(){
  var i, changedAttributes = this.changedAttributes() || [];
  _.each(this.attributes, function(value, key){
    if( _.isFunction(value) && _.isArray(value.attributes) ) {
      for(i in value.attributes) {
        if ( _.has(changedAttributes, value.attributes[i]) ) {
          this.trigger("change:"+key);
          return ;
        }
      }
    }
  }, this);
}, myModel);

We can add this to out initialize method, and get it automated, so our complete model will look like:

var BaseModel = Backbone.Model.extend({
  initialize: function(){
    this.on('change', function(){
      var i, changedAttributes = this.changedAttributes() || [];
      _.each(this.attributes, function(value, key){
        if( _.isFunction(value) && _.isArray(value.attributes) ) {
          for(i in value.attributes) {
            if ( _.has(changedAttributes, value.attributes[i]) ) {
              this.trigger("change:"+key);
              return ;
            }
          }
        }
      }, this);
    }, this);
  },
  get: function(attr) {
    var value = Backbone.Model.prototype.get.call(this, attr);
    return _.isFunction(value) ? value.call(this) : value;
  },
  toJSON: function() {
    var json = Backbone.Model.prototype.toJSON.apply(this, arguments);
    _.each(json, function (value, key) {
      if (typeof value == 'function') {
        delete json[key];
      }
    });
    return json;
  }
});

The question is: since a computed property is a macro/helper and not a “real” part of our data model, and they never do actually change, should we allow then to trigger change event?
I personally believe we shouldn’t use this approach, for it abstracts the true nature of the component. However, it can be useful.