The module pattern (in a nutshell)

The module pattern (first publicized by the Yahoo! JavaScript team) makes use of closures to bake privacy and state into your objects.

This is the generic form…

function() {
    //private state
    //private functions
    return {
         //public state
         //public variables
    }
}

Now lets put some meat on the bones. Here is a poll manager responsible for tallying yes and no votes:-

var pollManager = function() {
    //private state
    var alreadyVoted = {};
    var yesVotes = 0;
    var noVotes = 0;

    //return public interface
    return {
        vote : function(name, voteYes) {
            if (alreadyVoted[name]) {
                alert(name + ", you can't vote twice");
            } else {
                alreadyVoted[name] = true;
                voteYes ? yesVotes++ : noVotes++;
            }
        },

        reportTally : function() {
            var results = [];
            results.push("Yes = ");results.push(yesVotes);
            results.push(", No = ");results.push(noVotes);
            return results.join("");
        }
    }
}

var doYouLikeBroccoli = pollManager();
doYouLikeBroccoli.vote("Bob",true);
doYouLikeBroccoli.vote("Mary",false);
doYouLikeBroccoli.vote("Bob",true); //Bob, you can't vote twice
doYouLikeBroccoli.reportTally(); //"Yes = 1, No = 1"

We could have written this as an object literal ({}), but by enclosing it in a function instead we created a closure. This has the effect of protecting state (and potentially functionality) from the outside world. We return only the public API, everything else is private – the names of voters cannot be listed, the vote tallies can only be updated by voting.

We can further crank up the privacy by rewriting the reportTally function to show only the percentages. We’ll also create a helper function called asPercentage. Since asPercentage is only useful within this module we won’t return it as part of the public API – which means it becomes a private function – the module now hides function access as well as state.

var pollManager = function() {
    //private state
    //...
    var asPercentage = function(value) {
        return Math.round((100*(value/(yesVotes + noVotes))));
    }

    //return public interface
    return {
        //...
        reportTally : function() {
            return "Yes = " + asPercentage(yesVotes) + "%" +
                ", No = " + asPercentage(noVotes) + "%";
        }
    }
}

//...
doYouLikeBroccoli.reportTally(); //"Yes = 50%, No = 50%"

At the risk of  stating the obvious, in JavaScript when you make a function private, the logic is not hidden.  You won’t keep your encryption function a secret by hiding it in a module.  The concept of privacy is restricted to runtime access. I can only invoke pollManager’s asPercentage function or retrieve the value of the noVotes variable from within the  pollManager closure.

An equally important benefit of modules is tidiness.  Private objects only exist for the lifetime of the module function  call – after which they are available for garbage collection. Similarly, the module returns an API object (e.g.  doYouLikeBroccoli) whose properties are functions (vote and reportTally).  These function objects live and die with the API object.

Sometimes you might want to access part the publicly returned object from within your private methods.  (For sometimes read very occasionally – I couldn’t really think of a convincing example that wouldn’t work better with this behavior factored out) . In that case we can assign the public object to a variable (addressable from anywhere in the function) before returning it.

function() {
    //private state
    //private functions (can refer to publicObj)
    var publicObj = {/*...public API...*/};
    return publicObj;
}

More often than not you will see modules wrapped in parentheses and invoked immediately to provide singletons. Churning out a large number of module instances would be clunky and inefficient but the implication that you would never ever need more than one polling manager or id generator in your app is a bit of a mystery to me.

I’m drawn to the module pattern for its elegance (and genius). You get to keep your code tidy by hiding the one-off grunt work in a box while highlighting the interface you intend others to interact with. Clearly stated intention is the bedrock of good programming.

So why don’t I use it very often? There are some obvious answers: most of the tidiness of this pattern can be replicated with a simple object literal pattern, prototyping is more efficient for multiple instance creation and most grunt work is not one-off…you want to put in a utility file and re-use it.

But there are also more subtle reasons: privacy and form are probably overrated in Javascript where there is no formal concept of interface, class or strong typing. Objects can be effortlessly reshaped and transformed and this is liberating, especially for those brought up on the rigid constructs of Java et al. Hiding and partitioning introduces unfamiliar constraints to JavaScript developers who generally rely on self discipline over enforced discipline.

About these ads

13 thoughts on “The module pattern (in a nutshell)

  1. You said, “So why don’t I use it very often? There are some obvious answers: most of the tidiness of this pattern can be replicated with a simple object literal pattern, prototyping is more efficient for multiple instance creation and most grunt work is not one-off…you want to put in a utility file and re-use it.”

    so how do you replicate private stuff with a simple object literal? You need a closure to do that.

    • Peter, I totally agree – if you want privacy the module pattern is for you. In the next paragraph I talk about why I think privacy might be overrated in JavaScript.

    • Wes, thanks for sharing your code. What you are doing is essentially the same as the module pattern. You are attaching public attributes to a variable and returning it. However there are a few things that are a bit confusing to me:-

      Firstly you assign this to self and self is ultimately the public object that will be returned. You didn’t include any usage examples but I’m assuming you are not using the new Constructor pattern, in which case this will be the invoker of timepick. Having the invoker of the function overwritten by the return value seems risky. It could be that I’m missing something in your use case

      Secondly the module pattern is usually free from process, i.e. it just returns the public API as an object. However your example ends by calling init() which is process rich – and finally returns the public API almost as an afterthought.

      Thirdly public and private attributes are not clearly sectioned off from one another. You start with the public object self and a public attribute, then define a bunch of private variables, followed by public functions, a long and distracting switch statement, an init function that is private but ends up returning the public API, followed by more private functions.

      Apologies if this seems critical, I don’t mean to be – you clearly have a good understanding of the language – I think your example could just use some better organization

      Hope this helps

      • Yup, it’s evolved weirdly over time. I started doing the whole var self = this; just to make sure I had slightly more control over the context of the self|this inside of the object itself. Setting self to be this on instantiation seems to make sure that referring to self means that you’re always referring to the object itself when working with it. To be honest, I used to just use this there and I never noticed a problem, but switching to self seemed to be a little safer.

        This one is a bit of a weird example, but the reason this version has an init and returns self is that it is theoretically an object that can be created multiple times per page. When it’s more of a singleton/namespace there’s no init method and self actually never gets returned in those objects.

        Here’s an example of the older style, as well as it being essentially a singleton:

        http://pastie.org/private/f9c1ynozfrcrrgicvepsaw

        And don’t worry about being critical, I’m quite aware of it being nowhere near perfect. I’ve been using the style for ages, but have not been overly happy with it just yet. Though it has always worked, which counts for something.

        Thanks!

  2. Pingback: Interesting details on IE10's JavaScript performance tweaks » Encosia

  3. Pingback: MDPCHELP.COM | Advances in JavaScript Performance in IE10 and Windows 8

  4. Pingback: 提升IE10速度的JavaScript引擎 | bin's blog前端博客

  5. OK so it is a little late, but sorry Angus, I just don’t get it.
    As I understand it, pollManager and doYouLikeBroccoli are not clones but are the same object. And if you added doYouLikeCabbage = pollManager, it too would be the same, and would mix up Cabbage aficianado’s with those of Broccoli. As implemented it looks decidedly misleading to me. The singleton approach is better as it is obviously a one-off.
    But I don’t get the Module Pattern at all. What does it do that a normal constructor doesn’t do better? Replace “return publicObj” with “this.publicObject = function(){…” and you have the same elegance, genius, you can clone it, and what’s more you are using familiar notation. I am thinking the Module Pattern is like the invention of a square wheel. Where am I going wrong?

      • Oops, my mistake and apologies for my misleading post.
        I had overlooked that doYouLikeBroccoli = pollManager() INVOKES pollManager and returns an Object rather than assign the variable reference, and that makes all the difference.
        Thus doYouLikeBroccoli (and doYouLikeCabbage) would be different objects with independent closures. Here is my simple example that proves the point.

        mp=function(){// module pattern
        var c=0;
        return {
        inc:function(){c++},
        count:function(){return c}
        }
        };

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