понеділок, 13 серпня 2012 р.

Backbone.JS Model classes

Intro

In this post I wanted to describe guideline for models' classes that are used in my project at work.

As I have said in my previous post, Backbone gives you a freedom of choice, so you need to pay the price for this. You can find a lot of good tutorials in internet that will point you to a good way of writing backbone-based apps, nevertheless thare are some problems that are left behind and you still need to solve them somehow. I would recommend you to start with this seria of articles. It covers almost all basic steps to build backbone app from scratch and gives clear vision of Backbone fundamentals.

Model class role

Inside your web app you may find four basic roles of modules and classes:

  • Domain model
  • Business logic
  • Various infrastructure classes
  • UI layer
I divided the app classes by responsibility criteria. Standard MVVC pattern defines the anatomy and mechanics of application.

Model class in Backbone app is responsible for domain entity representation and business logic related to I/O operations. It also covers life-cycle states of an entity. The same refers to collection classes but they are meant to be used with the items that belongs to the same model class.

Life cycle of model begins with the instantiation and fetching data. Attributes changes trigger change event that could be used for handling states changes.

Implementation

Let's develop very sample class for the article entity that may react on tagging.

Generic tips

  1. Initialize method is for declaration of handlers and data init. Do not put heavyweight logic there.
  2. Do not mix everyhting in one single method. Parse is for parsingm fetch is for fetching, save is for saving. Keep an eye on that during the code reviews ;)
  3. Url as attribute is good when url is static, but it's a very rare casem better to use url as method 

States handling

So here is a sample model that is built according to the things I described above:


  1. var ArticleModel = Backbone.Model.extend({
  2.         initialize: function() {
  3.                 //Handler for tags changes
  4.                 this.on('change:tags',function(value){
  5.                         var id = this.id;
  6.                         //Iterate over changed tags
  7.                         _.each(value, function(item) {
  8.                                 //Add id of article to them
  9.                                 Tags.getByName(item).add(id);
  10.                         });
  11.                 });
  12.         }
  13. });


  1. Usually, when newcomers start to write application they are trying to put all checks and triggers into model methods, cause it's more obvious to debug. But in this sad case code is getting messy day by day and one morning it will explode.



I/O

Another point is that server side may be designed for native apps that can use CURL library and work with all types of responses without any limitations. HTML5 is different, less powerful and more naughty.

You have two options when developing I/O methods for your model and the server side is not REST+JSON:

  1. To override sync method and implement own Create/Read/Update/Delete calls to server. Good option when the server is still REST but gives different response format. Just override parse method and handle the response there.
  2. To implement own fetch/save/destroy methods. Good when server is not REST at all.
    1. var ArticleModel = Backbone.Model.extend({
    2.         initialize: function() {
    3.                 //Handler for tags changes
    4.                 this.on('change:tags',function(value){
    5.                         var id = this.id;
    6.                         //Iterate over changed tags
    7.                         _.each(value, function(item) {
    8.                                 //Add id of article to them
    9.                                 Tags.getByName(item).add(id);
    10.                         });
    11.                 });
    12.         },
    13.  
    14.         url: function() {
    15.                 return "http://api.com/articles/" + this.id + "?responseFormat=xml";
    16.         },
    17.  
    18.         fetch: function(options) {
    19.                 $.ajax({
    20.                         url:this.url(),
    21.                         success:function(response) {
    22.                                         this.set(this.parse(response));
    23.                                         options.success && options.success.call(options.context || this,this);
    24.                                 },
    25.                         context: this,
    26.                         method: "GET",
    27.                         dataType: "xml"
    28.                 });
    29.         },
    30.  
    31.         parse: function(response) {
    32.                 return {
    33.                         journalist: $(response).find("> journalist").attr("name"),
    34.                         published: $(response).find("> published")
    35.                 }
    36.         }
    37. });

  1. As you can see everything depend on your circumstances and requirements. 

    Outro

    I outlined some aspects of models classes development that may save your nerves in your projects. I add more posts about views and routers classes guidelines soon. 

    Thanks for your attention!

Немає коментарів: