The Design of Code: Organizing JavaScript

Great design is a product of care and attention applied to areas that matter, resulting in a useful, understandable, and hopefully beautiful user interface. But don’t be fooled into thinking that design is left only for designers.

Article Continues Below

There is a lot of design in code, and I don’t mean code that builds the user interface—I mean the design of code.

Well-designed code is much easier to maintain, optimize, and extend, making for more efficient developers. That means more focus and energy can be spent on building great things, which makes everyone happy—users, developers, and stakeholders.

There are three high-level, language-agnostic aspects to code design that are particularly important.

  1. System architecture—The basic layout of the codebase. Rules that govern how various components, such as models, views, and controllers, interact with each other.
  2. Maintainability—How well can the code be improved and extended?
  3. Reusability—How reusable are the application’s components? How easily can each implementation of a component be customized?

In looser languages, specifically JavaScript, it takes a bit of discipline to write well-designed code. The JavaScript environment is so forgiving that it’s easy to throw bits and pieces everywhere and still have things work. Establishing system architecture early (and sticking to it!) provides constraints to your codebase, ensuring consistency throughout.

One approach I’m fond of consists of a tried-and-true software design pattern, the module pattern, whose extensible structure lends itself to a solid system architecture and a maintainable codebase. I like building modules within a jQuery plugin, which makes for beautiful reusability, provides robust options, and exposes a well-crafted API.

Below, I’ll walk through how to craft your code into well-organized components that can be reused in projects to come.

The module pattern#section1

There are a lot of design patterns out there, and equally as many resources on them. Addy Osmani wrote an amazing (free!) book on design patterns in JavaScript, which I highly recommend to developers of all levels.

The module pattern is a simple structural foundation that can help keep your code clean and organized. A “module” is just a standard object literal containing methods and properties, and that simplicity is the best thing about this pattern: even someone unfamiliar with traditional software design patterns would be able to look at the code and instantly understand how it works.

In applications that use this pattern, each component gets its own distinct module. For example, to build autocomplete functionality, you’d create a module for the textfield and a module for the results list. These two modules would work together, but the textfield code wouldn’t touch the results list code, and vice versa.

That decoupling of components is why the module pattern is great for building solid system architecture. Relationships within the application are well-defined; anything related to the textfield is managed by the textfield module, not strewn throughout the codebase—resulting in clear code.

Another benefit of module-based organization is that it is inherently maintainable. Modules can be improved and optimized independently without affecting any other part of the application.

I used the module pattern for the basic structure of jPanelMenu, the jQuery plugin I built for off-canvas menu systems. I’ll use that as an example to illustrate the process of building a module.

Building a module#section2

To begin, I define three methods and a property that are used to manage the interactions of the menu system.

var jpm = {
    animated: true,
    openMenu: function( ) {
        …
        this.setMenuStyle( );
    },
    closeMenu: function( ) {
        …
        this.setMenuStyle( );
    },
    setMenuStyle: function( ) { … }
};

The idea is to break down code into the smallest, most reusable bits possible. I could have written just one toggleMenu( ) method, but creating distinct openMenu( ) and closeMenu( ) methods provides more control and reusability within the module.

Notice that calls to module methods and properties from within the module itself (such as the calls to setMenuStyle( )) are prefixed with the this keyword—that’s how modules access their own members.

That’s the basic structure of a module. You can continue to add methods and properties as needed, but it doesn’t get any more complex than that. After the structural foundations are in place, the reusability layer—options and an exposed API—can be built on top.

jQuery plugins#section3

The third aspect of well-designed code is probably the most crucial: reusability. This section comes with a caveat. While there are obviously ways to build and implement reusable components in raw JavaScript (we’re about 90 percent of the way there with our module above), I prefer to build jQuery plugins for more complex things, for a few reasons.

Most importantly, it’s a form of unobtrusive communication. If you used jQuery to build a component, you should make that obvious to those implementing it. Building the component as a jQuery plugin is a great way to say that jQuery is required.

In addition, the implementation code will be consistent with the rest of the jQuery-based project code. That’s good for aesthetic reasons, but it also means (to an extent) that developers can predict how to interact with the plugin without too much research. Just one more way to build a better developer interface.

Before you begin building a jQuery plugin, ensure that the plugin does not conflict with other JavaScript libraries using the $ notation. That’s a lot simpler than it sounds—just wrap your plugin code like so:

(function($) {
    // jQuery plugin code here
})(jQuery);

Next, we set up our plugin and drop our previously built module code inside. A plugin is just a method defined on the jQuery ($) object.

(function($) {
    $.jPanelMenu = function( ) {
        var jpm = {
            animated: true,
            openMenu: function( ) {
                …
                this.setMenuStyle( );
            },
            closeMenu: function( ) {
                …
                this.setMenuStyle( );
            },
            setMenuStyle: function( ) { … }
        };
    };
})(jQuery);

All it takes to use the plugin is a call to the function you just created.

var jpm = $.jPanelMenu( );

Options#section4

Options are essential to any truly reusable plugin because they allow for customizations to each implementation. Every project brings with it a slew of design styles, interaction types, and content structures. Customizable options help ensure that you can adapt the plugin to fit within those project constraints.

It’s best practice to provide good default values for your options. The easiest way to do that is to use jQuery’s $.extend( ) method, which accepts (at least) two arguments.

As the first argument of $.extend( ), define an object with all available options and their default values. As the second argument, pass through the passed-in options. This will merge the two objects, overriding the defaults with any passed-in options.

(function($) {
    $.jPanelMenu = function(options) {
        var jpm = {
            options: $.extend({
                'animated': true,
                'duration': 500,
                'direction': 'left'
            }, options),
            openMenu: function( ) {
                …
                this.setMenuStyle( );
            },
            closeMenu: function( ) {
                …
                this.setMenuStyle( );
            },
            setMenuStyle: function( ) { … }
        };
    };
})(jQuery);

Beyond providing good defaults, options become almost self-documenting—someone can look at the code and see all of the available options immediately.

Expose as many options as is feasible. The customization will help in future implementations, and flexibility never hurts.

API#section5

Options are terrific ways to customize how a plugin works. An API, on the other hand, enables extensions to the plugin’s functionality by exposing methods and properties for the implementation code to take advantage of.

While it’s great to expose as much as possible through an API, the outside world shouldn’t have access to all internal methods and properties. Ideally, you should expose only the elements that will be used.

In our example, the exposed API should include calls to open and close the menu, but nothing else. The internal setMenuStyle( ) method runs when the menu opens and closes, but the public doesn’t need access to it.

To expose an API, return an object with any desired methods and properties at the end of the plugin code. You can even map returned methods and properties to those within the module code—this is where the beautiful organization of the module pattern really shines.

(function($) {
    $.jPanelMenu = function(options) {
        var jpm = {
            options: $.extend({
                'animated': true,
                'duration': 500,
                'direction': 'left'
            }, options),
            openMenu: function( ) {
                …
                this.setMenuStyle( );
            },
            closeMenu: function( ) {
                …
                this.setMenuStyle( );
            },
            setMenuStyle: function( ) { … }
        };

        return {
            open: jpm.openMenu,
            close: jpm.closeMenu,
            someComplexMethod: function( ) { … }
        };
    };
})(jQuery);

API methods and properties will be available through the object returned from the plugin initialization.

var jpm = $.jPanelMenu({
    duration: 1000,
    …
});
jpm.open( );

Polishing developer interfaces#section6

With just a few simple constructs and guidelines, we’ve built ourselves a reusable, extensible plugin that will help make our lives easier. Like any part of what we do, experiment with this structure to see if it works for you, your team, and your workflow.

Whenever I find myself building something with a potential for reuse, I break it out into a module-based jQuery plugin. The best part about this approach is that it forces you to use—and test—the code you write. By using something as you build it, you’ll quickly identify strengths, discover shortcomings, and plan changes.

This process leads to battle-tested code ready for open-source contributions, or to be sold and distributed. I’ve released my (mostly) polished plugins as open-source projects on GitHub.

Even if you aren’t building something to be released in the wild, it’s still important to think about the design of your code. Your future self will thank you.

31 Reader Comments

  1. Great article, and very relevant to what I’m doing at the moment. ALA has this amazing knack for posting an article at exactly the right time for me to incorporate its message into my development!

  2. I’m concerned that redefining the “jpm” variable for every invokation of $.jPanelMenu adversely affects the scalability of this approach.

  3. Dan: The jQuery UI widget factory can certainly come in handy, but this approach is more targeted towards things that break the typical bounds of jQuery UI widgets.

  4. Nate: Are you concerned about the local scope within the plugin, or within the implementation code?

  5. What about:
    var jpm = (function () {
    method1 = function() {…}
    method2 = function () {…}
    method3 = function () { //here you can compose a toggle function from method1 and method2 }
    return {method1: method1, method2: method2, method3: method3};
    })();

    Is that a good pattern ?

  6. Hey.
    Great article.

    I have a few points I wanna share with you. First: the ‘this’ scope mess.

    If you have:

    var me = {
    methodA: function() {…},
    methodB: function() {
    this.methodA();
    }
    }

    Sometimes ‘this’ will not be pointing to ‘me’ but ‘window’ or whatever the call starts from. So i use ‘me.methodA()’ instead.

    Thinking like that, i usually write:

    me.methodA = function() {};
    me.methodB = function() {
    me.methodA();
    }

    return me;

    And when i dont wanna use jQuery as a global enviroment, i use a global object like a ‘java package’ of my code, normally the name of my company.

    Something like…

    // begging of my class file:
    if (typeof myCompany == ‘undefined’) {
    myCompany = {};
    }

    myCompany.MyClassName = function() {
    var me = {};
    me.methodA = function() {}
    return me;
    }
    // end of my classfile

    And usage like

    var a = new myCompany.MyClassName();
    a.methodA();

    I dont know if this is the best approach, but helps me a lot.

  7. Thank you for a nice, clearly written article – as a back-end dev slowly picking up the ropes of javascript, I really find simple explanations like this very helpful

  8. It seems that your jpm plugin is initialized only once on a page. Now, what if my jquery plugin could be instantiated multiple times on the same page. How would you modify the above code to accommodate that?
    Thanks for the great article by the way.

  9. Gabriel: That’s a great pattern, and is one of the reasons I love the module pattern so much. Being able to map API functions to those within the module is so nice!

  10. Pedro: Definitely great tips to share there. “This” does get somewhat confusing in more complex modules, so in those cases it’s great to switch over to the more specific usage of variable names. Good stuff to keep in mind!

  11. Oliver: To instantiate it multiple times, I’d just change the variable name that instances are saved to:

    var jpm = $.jPanelMenu( );
    var otherInstance = $.jPanelMenu( );

    And so on from there. Hope that helps!

  12. Obviously modules are the way to go in terms of writing your code, but they don’t solve the issue of having your dependencies managed which is also an important part of your js code management.

  13. Great article indeed. Module pattern is good, but I think that Revealing Module Pattern is even better. It allows defining private variables and methods. You keep your internal module’s logic hidden. Don’t you think so?

  14. Great article. I think the fact that JavaScript is so easy to pick up leads to a lot of bad code which actually kind of works unless you need to maintain it and change it regularly. Such patterns and article will hopefully help people learning that even though it’s easy to write unclean code in JavaScript, it’s easy to write clean code provided you use such patterns.

  15. Great article Anthony! I already used the module pattern to help organize my code, but this really helped with better understanding the implementation of options and creating an API to use. Thanks!

  16. As Nate Whittaker already pointed out, your approach of creating the whole “instance” from scratch every time you use the plugin could be optimized. I’d dismiss it as nitpicking, were it not for the fact, that your article is about code reuse among other things. Any serious discussion about code reusability should IMO include at least a mention of JavaScript’s prototypal inheritance and how to utilize it to create reusable code.

    Coincidentally, your #snippet6 has a scope bug in it. The “function mapping” you specifically mention before that snippet is a broken pattern, because just passing the functions doesn’t preserve their scope (and you use the scope and specifically mention it above). An easy solution (apart from using ‘me’) is to work with real constructors and create instances. Like:

    (function ($) {
    var PanelMenu = function (options) {
    this.options = $.extend({
    /* defaults */
    }, options);
    };
    $.extend(PanelMenu.prototype, {
    open: …

    });
    $.jPanelMenu = function (options) {
    return new PanelMenu(options);
    };
    $.jPanelMenu.klass = PanelMenu;
    )(jQuery);

    As a bonus, I exposed the class constructor for easy extensibility.

  17. I agree with both Lars and hon2a.

    Also I wanted to say that when you keep a private more complex version of a method and only expose a simple API you are using the Facade pattern. I think you could mention it in #snippet 16 (witch as mention above has a scope bug).

  18. Great article, I’ve often turned to the module/revealing module pattern to organise my JS. It’s simple, just works and my colleagues can run with code changes without too much back and forth to me. On thing about your article though, link to your github account doesn’t appear to work?!

  19. Thank you for your nice article. As web developers, we learnt from the API section that we can create the Javascript “Facade pattern” to encapsulate some functions that should not be visible to the caller. This is definitely a good pattern. The structure is clearer, I like that. It is a headache to have many “public” functions in Javascript, and very easy to get them mixed up and confused. This will help us keep the website development code organised and efficient.

  20. If you think Clifford`s story is shocking…, last week my brother’s mom in law also recieved a check for $9648 working 10 hours a week from their apartment and they’re classmate’s step-aunt`s neighbour was doing this for 4 months and recieved a check for over $9648 parttime on their computer. applie the guidelines here, http://m3mi.com/3621CHECK IT OUT

  21. Great article! Two questions:

    1) what is the suggested way to declare private variables when using this pattern?

    2) why did you put openMenu(), closeMenu(), etc methods inside the jpm object? Why not leave them outside (making them accessible through the public methods by using ‘openMenu()’ instead of ‘jpm.openMenu()’, for example)? Does it make a difference?

Got something to say?

We have turned off comments, but you can see what folks had to say before we did so.

More from ALA

Nothing Fails Like Success

Our own @zeldman paints the complicated catch-22 that our free, democratized web has with our money-making capitalist roots. As creators, how do we untangle this web? #LetsFixThis