Question

First off, I apologize for the ignorance. I'm pretty baby faced when it comes to JavaScript, mainly coming from a Java background, so quite a bit of this is new to me. I've read a few posts, but honestly, I'm not sure of even a good question to ask.

I've been following "Single Page Web Applications: JavaScript End-To-End" and now I'm going back through the code and trying to reconstruct/refactor it so it makes sense to me.

One thing I'd like to understand is how to properly organize code using the Modular pattern the author references.

spa.model = (function () {
    var people,
        stateMap = { id : 1 };

    people = (function () {
        var methods1, method2;

        method1 = function(){ … }; // do something
        method2 = function(){ … }; // do something 

        return {
            method1 : method1,
            method2 : method2
        };
    }());

    return {
        people : people
    };

}());

This allows me to call something like spa.model.people.method1();

What I'd like to do is somehow move the people var to another file so that it looks something like this

spa.model = (function () {
    var people = spa.model.people,
        stateMap = { id : 1 };

    return {
        people : people
    };

}());

spa.model.people = (function () {
    var method, method2;

    method1 = function() { return stateMap.id; },
    method2 = ... ;

    return {
        method1 : method1,
        method2 : method2
    };

}());

However, when I refactor code out like this I get all kinds of scope errors. For example, I can no longer reference stateMap from spa.model.people.

How are larger files organized when using this pattern? Even with only two objects (people & chat), the authors' spa.model file is getting rather large. Imagine having 20 database objects to model. That'd be a huge file.

Was it helpful?

Solution

IMO, the best way to do this is to create a parent ("model") and subordinate modules like model.people, model.auth, and model.chat. The parent ("model") manages and coordinates shared state and configurations. The subordinate modules (model.people, model.auth, model.chat) should not call each other or otherwise depend on the other's existence.

Here is an example where the model coordinates 3 subordinate modules interface (model.people, model.chat, model.auth) and stores shared state in its stateMap. Recognize that each subordinate module will have its own encapsulated stateMap which will not pollute the parent state. While this example is certainly not complete, hopefully it helps point the way.

model = (function () {
  var 
    __undef,
    configMap = {};
    stateMap  = { 
      user_id   : __undef,
      chatee_id : __undef
    },

    logIn, addPerson, rmPerson, callPerson, hangUp;

  logIn = function ( user_name, passwd_str ) {
    user_id = model.auth( user_name, passwd_str );
    if ( user_id ) {
      model.people.addPerson( user_id ):
      model.chat.announceUser( user_id );
      stateMap.user_id = user_id;
    } 
  };

  // ... and more methods that coordinate subordinate modules

  return { 
    logIn      : logIn,
    addPerson  : addPerson,
    rmPerson   : rmPerson,
    callPerson : callPerson,
    hangUp     : hangUp
  };
}());

This stuff is not always easy. I try not to get too hung up about organization but keep it in mind. It's kind of like project management: the only "perfect" project plan I've ever seen was written after the project was complete. The same is true for code organization. In my first pass, I allow myself to be a little sloppy. For example, I might violate the no-peer-cross-talk rule as a quick hack - but I will add a big fat TODO to ensure it doesn't make it to production code.

Once our code gets settled, I then give it another pass and clean up the loose ends - like the aforementioned big fat TODOs. The result is usually well organized, easy to understand, and maintainable code. If not, I rinse and repeat.

I hope that help!

OTHER TIPS

I like to declare my objects a bit differently. Perhaps you could do something like this:

(function () {

  spa.model = {

    stateMap: {
      id: 1
    },

  };


  var people = {

    method1: function() {
      return stateMap.id;
    },

    method2: function(){},
  };

  spa.model.people = people; 

  // obviously expose spa at the end.
  window.spa = spa;

}());
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top