Twitter: raymondcamden


Address: Lafayette, LA, USA

JavaScript Design Patterns - The Module Pattern

03-22-2013 8,736 views JavaScript 20 Comments

(Edit: I see that the Gists/code samples are displaying extra lines on top/bottom. Please ignore. Will try to fix after lunch.) As I mentioned a few days ago, I'm currently in the process of reading Addy Osmani's JavaScript Design Patterns book. (Note - in my earlier blog entry I linked to the physical copy at Amazon. The link here is to the free online version. I think his book is worth buying personally, but you can try before you buy!) The first pattern described in the book, and the one I'm going to talk about today, is the Module pattern.

Before I begin, I want to be clear. I'm writing this as a means to help me cement my understanding. I am not an expert. I'm learning. I expect to make mistakes, and I expect my readers to call me out on it. If in the end we all learn something together, then I think this process is worth while!

Addy describes the Module pattern like so:

The Module pattern was originally defined as a way to provide both private and public encapsulation for classes in conventional software engineering.

In JavaScript, the Module pattern is used to further emulate the concept of classes in such a way that we're able to include both public/private methods and variables inside a single object, thus shielding particular parts from the global scope. What this results in is a reduction in the likelihood of our function names conflicting with other functions defined in additional scripts on the page.

I think this makes sense by itself, but it may help to back up a bit and consider why encapsulation may be good in general. If you are new to JavaScript, you have probably built web pages that look a bit like this.

You may begin adding interactivity to your page by adding a simple JavaScript function:

And then progressively adding more and more...

Eventually, the amount of JavaScript code you have may get to a point where you realize you probably should be storing it in its own file. But moving all of that code into a separate file doesn't necessarily help. After a while you begin finding yourself having difficulty finding the right functions. You may have code related to feature X next to feature Y followed by something else related to feature X. Maybe then you create multiple JavaScript files. One for X, one for Y. But as Addy alludes to above, you run the risk of function names overwriting each other.

Consider a web application that interfaces with both Facebook and Twitter. You write a function for Twitter called getLatest that fetches the latest Tweets about Paris Hilton. (And why wouldn't you do that?) You then write code to get the latest status updates from your friends on Facebook. What should we call that? Oh yeah - getLatest!

This isn't something you couldn't handle, of course, but the point is, design patterns were built for the sole purpose of helping you solve problems. In this case, the module pattern is one example of a solution that helps you organize your code. Let's look at a full example of this.

I've created a simple web application that lets users keep a diary. For now the functionality is simple - you can see your past entries, write new ones, and view a particular entry. This web application is going to make use of WebSQL, which does not work in Firefox or IE! This is intentional and I plan to address this in a later blog entry. You can demo this (again, please use Chrome, and again, keep in mind there is a reason why I'm not handling multiple browsers) by going here:

http://www.raymondcamden.com/demos/2013/mar/22/v1/

While you can view source yourself, I thought it might be beneficial to share the main JavaScript file here. Warning, this is a big code block. That's kind of the point. Do not read every line here.

What you see is how I typically code. My application begins by waiting for the DOM to load. It then needs to set up a database. Next, it needs to list out entries. And so on. If you read "down" the JavaScript file, you can see functions related to DOM manipulation, functions handling my "single page architecture", and functions doing database crap. When I was working on page one, I focused on lists. When I worked on the add form, I worked on data writing support. Basically, as I moved into the application I just plopped down functions one after another.

This works. But - my gut is telling me that this file is messy. When I see something wrong, I'm not sure where to look since everything is mixed up together. In the paragraph above I described most of my functionality as falling into three main areas. I've decided that I'd like to take database stuff and abstract it into a module.

The basic structure of code using the Module pattern can be defined like so:

Raise your hand if you find that syntax confusing. I know I did. Now it makes sense to me. But for a long time it just felt... weird. I had a mental block accepting the form of this code for a long time. I'm not ashamed to admit it.

For me, it helped if I backed up a bit and looked at it like so:

Ok, that makes sense. I'm basically saying the variable someModule is equal to whatever in the heck gets done inside my parentheses. Ok, so what in the heck is happening there...

Ok, so we're creating a function and running it. Immediately. Ok, so whatever the function returns - that's what will be passed to someModule. Here is where things get interesting. Let's put some code in this module.

The code for this module comes from Addy's example. The variable, counter, is a private variable. Why? Because it isn't actually returned from the function. Instead, we return an object literal that contains two functions. These functions have access to the variable counter, because, at creation, they were in the same scope. (Note: This last sentence may not be precisely describing the situation.) The result of this function is that object literal. My module contains two functions and a private data variable.

What's nice is - I no longer have to worry about function collision. I can name my functions whatever I darn well please. I can also create private functions as well and hide them away from the implementation. There may be utility functions that make sense for my module but don't make sense anywhere else. I can stuff them in there and hide them away!

So, as I said, I wanted to take out the database aspects of my code. I created a new file, diary.js, and created this module.

Now I've got a "package" that my main JavaScript file can use. Let's look at that.

You can see that all of the database functions are now gone. I now access them via diaryModule.whatever. I believe I cut out about 60 or so lines of code, around a third, but what is left is more focused. (I could also take out the functions used to support my single page architecture.)

You can run this version here: http://www.raymondcamden.com/demos/2013/mar/22/v2

So, questions? Opinions? Rants? :)

Related Blog Entries

20 Comments

  • Commented on 03-22-2013 at 1:37 PM
    @Raymond:

    Hopefully this article will help a lot of people. I personally prefer the following module pattern:

    window.someModule = (function(someModule) {
    var privateVar = "cfjedimaster";
    someModule.publicMethod = function (){
    return privateVar;
    }
    return someModule;
    })(window.someModule || {});

    While it's very similar, what it allows you to do is easily extend a module if it already exists on the page, but still allows you to provide that separation in your logic.

    This works really well when you might have parts of JS logic being include dynamically.

    The trick is the "window.someModule || {}" argument being feed to the self executing function. What this does is either pass in the reference to the global variable or it passes in an empty Object. Very clean and effective.
  • Commented on 03-22-2013 at 1:53 PM
    The module pattern is what I use. It really helps clean things up. :-)
  • Dave Anderson #
    Commented on 03-23-2013 at 2:04 PM
    Looks like it's time to start using jQuery promises. Maybe the next post will refactor this code with $.deferred, eh?
  • Commented on 03-23-2013 at 2:06 PM
    Dave, interesting, why do you think this is necessary? To me, promises seem more useful when you may have N items firing async and want to wait for them to complete. For my API, I really don't. I just have a doX(run this on done) type API that seems simple enough. Unless I'm missing your point?
  • Dave Anderson #
    Commented on 03-23-2013 at 2:17 PM
    I'm still working to grasp when $.deferred is most useful myself, but I was under the impression that whenever you see nested callbacks, there's a good chance the code can be refactored for read- and maintainabililty with promises.
    Now I'm reading a tutorial, so if I figure out how to make those function(foo, function(bar, function()))s go away, I will report back.
    (Unless someone who really gets what I'm trying to say can chime in. It's entirely possible I'm totally full of crap.)
  • Commented on 03-23-2013 at 2:21 PM
    I suppose, technically, I have nested callbacks. Ie, this button -> on click -> do a db call -> then X

    But since once call back is the handler for a DOM event and one is the callback for my db call, I wouldn't want to mix em up.

    To me, it seems reasonably simple enough. But I've been looking at JS code for a while now. :)
  • Commented on 03-23-2013 at 2:21 PM
    Btw - this is excellent stuff to discuss of course. Keep it up.
  • Dave Anderson #
    Commented on 03-23-2013 at 2:21 PM
    You know what? My mistake. Scratch all that. I took your advise and didn't read every line of code the first time. I see now that the functions I was thinking of are all db-related, rather than async processes. I suspect promises wouldn't necessary apply here.

    Carry on!
  • Commented on 03-23-2013 at 2:23 PM
    Actually, the DB stuff is async. :) Look at the module.
  • Dave Anderson #
    Commented on 03-23-2013 at 3:13 PM
    Yeah, that's right, but the db.transaction()s don't return a promise like a $.post() or $.get() do.

    Question: where does 't' get defined? Does the transaction pass itself to the initDB() method?
  • Russ #
    Commented on 03-23-2013 at 5:58 PM
    Lately I've been using Require.js, which handles JS dependencies while utilizing the module pattern (it also does a lot of other useful stuff). If you haven't taken a look at it yet, I definitely recommend giving it a shot.
  • Commented on 03-23-2013 at 6:39 PM
    @Dave: Yes, it is a transaction object. Don't focus too much on WebSQL. It is a kick ass technology, easy to use, pretty familiar to those of us with server-side experience, but also a dead technology. :(

    @Russ: I've "used" Require.js, but I wouldn't say I exactly grok it yet.
  • Commented on 03-25-2013 at 9:32 AM
    What is the difference between this and using namespaces?
  • Commented on 03-25-2013 at 9:40 AM
    I don't know. I haven't really thought about that yet.
  • Dawesi #
    Commented on 03-25-2013 at 10:06 AM
    Reminds me of Sencha's frameworks it does ;-) - it's almost ColdFusion and ExtJS where written with the same thought processes... serious synergy there...
  • Commented on 03-25-2013 at 10:14 AM
    @RogerTheGeek:

    I'm assuming when you say "namespaces" you're referring to just using an object to declare your functions. If so, the significant difference is the module pattern allows for private variables/functions that can only be executed by the module.

    For all intents and purposes, the module pattern is just a form of providing a namespace for your variable and method declarations.
  • Justin Treher #
    Commented on 03-27-2013 at 7:03 AM
    Your post goes well with this post for the new ECMAScript shortcut:

    http://ariya.ofilabs.com/2013/03/es6-and-method-de...
  • Commented on 03-27-2013 at 8:33 AM
    Yeah, ECMA6 is looking very sweet.
  • Dennis #
    Commented on 06-05-2013 at 12:49 PM
    Tried running the final version in Chrome 27.0.1453.110. Clicking "Write Entry" button does not load add.html.
  • Commented on 06-06-2013 at 2:28 AM
    Do you see anything in the console?

Post Reply

Please refrain from posting large blocks of code as a comment. Use Pastebin or Gists instead. Text wrapped in asterisks (*) will be bold and text wrapped in underscores (_) will be italicized.

Leave this field empty