Module Pattern : Part 1

In any project we do, modularization helps with keeping everything nice and clean and separate. It’s highly necessary when we want to achieve the important goal of OOP design, Loose coupled and highly cohesive systems. One might say Javascript is not as apparent as a object oriented language, hence not that hospitable to create a modularized environment. But that notion is easily debunked, because there are ways we can have modularization in our JS applications.

  • Module pattern
  • Object literal notation

There are more non-trivial methods as well. We’ll hopefully venture into them in a later post.

Before we get in to the pattern, we must pay a visit to a concept which should’ve been better to have discussed in the previous post. It’s about object literals. We did mention that a way to make a new object was:

var newObject = {};

What goes inside the curlies? It’s just a standard concept we use in our generation of programming languages : key value pairs. The keys can be any identifier or a string.

So if we define something as {}, that is the most basic of modules. But we can’t use that at the start of a statement, because the engine might interpret that as a start of a block as well. And also there’s the question of how do we refer to that module later on. So it’s basically understandable why we use the notation above, with a proper variable name for the module. Later on we can refer to that object and add more properties like:

newObject.property =  ‘value’;

Of course we covered that in the previous post.

Let’s look at a more thorough example and see what we can derive from that about modules :


varmyModule = {
    myProperty: "someValue",

    myConfig: {
        useCaching: true,
        language: "en"
    },
    
    // a very basic method
    saySomething: function() {
        console.log( "Where in the world is Paul Irish today?");
    },
    
    // output a value based on the current configuration
    reportMyConfig: function() {
        console.log( "Caching is: "+ ( this.myConfig.useCaching ? "enabled": "disabled") );
    },
    
    // override the current configuration
    updateMyConfig: function( newConfig ) {
        if( typeofnewConfig === "object") {
            this.myConfig = newConfig;
            console.log( this.myConfig.language );
        }
    }
};

// Outputs: Where in the world is Paul Irish today?
myModule.saySomething();
// Outputs: Caching is: enabled
myModule.reportMyConfig();
// Outputs: fr
myModule.updateMyConfig({
    language: "fr",
    useCaching: false
});
// Outputs: Caching is: disabled
myModule.reportMyConfig();

  • Object properties are simple to be defined.
  • We can define new objects as properties of an object.
  • We can have functions defined here too.
    • One important thing to note here is the ‘this’. When we define a function inside an object as a property, the ‘this’ inside that function refers to the parent object. This is in contrast to when we define a function in the global scope. That is technically not a function as what we define here, but a way of defining a class in JS. But as we discussed in the previous post, ‘this’ in a function defined outside refers to the instantiation of that function via the ‘new’ keyword. If you haven’t read that I suggest you go read that already.
    • Now you may realize that we could’ve used a function class like that to define a similar ‘module’. But the key difference is we can create multiple instances of that function class using the new keyword. But not when we define a module like this. This module is a pure module, where it’s just there to be used as is. We define properties inside here not as a prototype.

Let’s look more indepth in to using the object literal notation in creating modules. A thorough analysis of it can be found here.

An object literal is a way to encapsulate a set of related behaviors. Encapsulating behavior, or modularizing if we are sticking to the subject at hand, is quite important as it doesn’t pollute the global namespace. That is pivotal in terms of large scale applications. Here we just encapsulate some methods inside  an object, simple as that :

var myObjectLiteral = {
    myBehavior1 : function() {
        /* do something */
    },

    myBehavior2 : function() {
        /* do something else */
    }
};

One might think, what’s the big fuzz about, we can declare our functions anywhere in a js file and use this, why need a object literal anyway. The need comes, as you might guess already, with the configuration. Let’s have a look through a small example. Now this example goes out of basic JS in to jQuery, as used in the article mentioned above. I’m gonna use the same example as it gets the point across nicely.


$(document).ready(function() {
    $('#myFeature li').append('div').each( function() {
        $(this).find('div').load('foo.php?item='+$(this).attr('id'));
    })
    .click( function() {
        $(this).find('div').show();
        $(this).siblings().find('div').hide();
    });
});

What this does is, for each ‘li’ item in myFeature it appends a ‘div’. For each of them it load the data from the url passed in with the id. It also binds a click function to it, which will trigger the visibility of the divs. That’s a nifty piece of code to get it done. But one thing to note is that this is run once on the document ready event. And if we want to replicate this behavior to different kind of DOM element we need to add another function with all the changing parts replaced how we want again. We all know that’s not how we want to roll in programming. So let’s identify the things we can change in this block, so we can introduce the object literal pattern in creating a configurable and reusable module.

  • The wrapper element, as in the example it’s #myFeature.
  • The container element, as in the example it’s the ‘div’.
  • urlBase, where we get the content. This will only depend on the id that we get from the list items.

I believe It can be made more configurable that that. But let’s focus on these things for now.

So if we modularize this taking the configuration and behavior into consideration, it would look like this :


var myFeature = {
    config : {
        wrapper : '#myFeature',
        container : 'div',
        urlBase : 'foo.php?item='
    },

    init : function(config) {
        //Using jquery builtin extend function we can extend our configurations easily.
        $.extend(myFeature.config, config);
        $(myFeature.config.wrapper).find('li').
            each(function() {
                myFeature.getContent($(this));
            }).
            click(function() {
                myFeature.showContent($(this));
            });
    },

    buildUrl : function($li) {
        return myFeature.config.urlBase + $li.attr('id');
    },

    getContent : function($li) {
        $li.append(myFeature.config.container);
        var url = myFeature.buildUrl($li);
        $li.find(myFeature.config.container).load(url);
    },

    showContent : function($li) {
        $li.find('div').show();
        myFeature.hideContent($li.siblings());
    },

    hideContent : function($elements) {
        $elements.find('div').hide();
    }
};

How convenient is that? For any element we want to show and hide, given that we have the content to show mapped to the urls, we can use this module. Only need to call the init() function with our own modified config object, and we will get the behavior applied to wherever we want.

Summary

  • Modularity is important in any Object Oriented Programming language.
  • The most basic of Modules is an Object : { }
  • Object properties can take various forms.
  • ‘this’ in a function which is defined as a Object property, refers to the parent object itself.
  • An Object literal notation, encapsulates a set of behaviors and properties, hence a module.

So I guess that made evident the use of Object literal notation. We will have an in-depth look in to the Module-pattern in the next post.

 

Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s