2012.09.12

Namespaces are Old School

Let’s start with an overly simplified/generalized and mostly wrong history of the JS community during the past decade.

Let’s go back in time 12 years, to the distant year of 2000. JavaScript is being mostly used for form field validation, analog clocks and mouse trails. Nobody really cared about namespace cluttering, all the code resided on the global scope. This is considered the dark age of JS.

Now let’s fast forward 5 years, to the the first stage of the JavaScript Renaissance (2005-2007); libraries like jQuery, Mootools and Prototype.js are getting extremely popular, AJAX is the buzzword of the moment. Augmenting native prototypes was a very common practice and no caution was taken into consideration, the rule of thumb was easy development and brevity. Larger projects started being developed by more people and best practices started to appear. Sometime around this period closures became a popular way of hiding information and IIFE became the De facto standard. Namespaces also became really popular.

Now back to 2012. Everybody knows that augmenting built-in native objects is a bad thing, specially host objects. Polluting the global namespace is also considered a bad practice and many people avoid it as much as possible. It is not uncommon to see people adding their own application code into objects that they don’t own, proving that they don’t really understand why they shouldn’t have globals to begin with, but at least we are moving towards the right direction. <rant>Polluting any namespace is a BAD thing, not only the global scope, you should NOT put your application code into the $ object…</rant> Script loaders and package managers are becoming more popular each day, node.js is the buzzword of the moment and Harmony might become a reality and provide a native module format.

OK, no more history… Let’s see some code.

Why Namespaces?

Namespaces were created as a way to avoid name collisions and to group code by context. Some variable/function names are very common and it is very easy to get into conflicts. Keeping all your code inside a sandbox reduces this chance, it also improves the code organization.

Namespaces in JavaScript

The language doesn’t provide any special keyword to define a namespace so it’s a common practice to use plain objects as a way to emulate it.

var myNamespace = {};
myNamespace.bar = 'this is dog fort';
myNamespace.doFoo = function(){
    console.log(myNamespace.bar);
};

That is a valid way to group methods by context and to avoid name collisions. And it’s been working for the past 10+ years for the JS community, except when it doesn’t.

Verbosity

After you get neurotic about name collisions and/or the libraries/frameworks grow to a certain size it is inevitable that you have nested namespaces like lorem.ipsum.dolor.doSomething() which isn’t fun, specially if it is a method that you use very often.

Namespace cluttering

To avoid the verbosity many libraries started to put all methods inside a single object, jQuery and Underscore.js are famous examples of this poor practice. The chance of name collisions increases a lot, and naming methods becomes harder. Just imagine 2 jQuery plugins that implements the same method with different behavior (plugins are evil BTW), chaos will ensue.

An object with too many methods probably has very low cohesion and that is an anti-pattern. The code gets harder to browse and inspect since everything is mangled into the same object, the namespace should give context to its properties. A method add() inside a userList object probably means “add a new user to the list”, while a method with the same name inside a FOO object can mean hundreds of different things.

Code sharing

A common practice that I’ve seen is to create a global object named as the company/project name. So if the project is for a client named “Foo” the whole application code would be placed into the FOO object. Now if you want to reuse the same code into multiple projects you will need to replace every reference to the FOO object or keep all the shared code into a separate namespace. This doesn’t scale really well and is error prone…

noConflict()

Everything goes well with the namespaces until 2 libs decide to use the same name, or you need to load 2 versions of the same library into the same page. The solution, create a noConflict() method. Now every library that don’t want to create conflicts with 3rd-party code needs a noConflict() method. That is not ideal and extremely error prone, specially when code is loaded asynchronously or you have a large code base with a complex dependency tree.

var _oldNamespace = window.myNamespace;
// reset global reference to previous state
myNamespace.noConflict = function(){
    window.myNamespace = _oldNamespace;
    return myNamespace;
};

It’s 2012, use a module system!

What is the best way (using current JS) to really solve the global name conflicts? Don’t use globals at all!

With a module system like AMD or CJS you don’t rely on globals, you use IDs to reference other modules.

define(function(require, exports){
    var foo = require('foo');
    var ipsum = require('lorem/ipsum');
    exports.bar = function(){
        foo.doFoo();
        ipsum.log('amet');
    };
});

If for some reason you have conflicting code you can simply map the IDs to point to a different location:

requirejs.config({
    map : {
        '*' : {
            // most modules will load foo.1.0
            'foo' : 'lib/foo.1.0'
         },
         'bar' : {
            // the module "bar" will load a diff version of "foo"
            'foo' : 'lib/foo.2.0'
         }
    }
});

Namespaces becomes obsolete when you are able to require specific modules and/or functions. This also favors smaller modules that consumes fewer dependencies, increasing cohesion and improving the code organization. With a module system, global variables becomes almost unnecessary.

If you still think AMD isn’t useful you are probably writing code like if it was 2005. I moved to AMD almost 2 years ago and it feels great to not have to type awkward namespaces, not have to worry about name collisions, have a smart build system that inlines only the modules that are currently being used, don’t have to worry about the code execution order, being able to load other kinds of resources besides JS, lazy load code if needed, etc… Some of my past projects had more than 500 source files (JS + templates) and I have to say that AMD made the development process infinitely easier. Code sharing increased exponentially and multiple developers could work together without causing conflicts. If you think it’s too much boilerplate to type on each file create a code snippet and assign some shortcut, problem solved. #winning

If you avoid named modules and use relative paths it becomes really easy to share code between projects, no renaming and/or configuration needed. Let your build script name your modules for you (the RequireJS optimizer is great for that).

Namespaces are old school; Welcome to the module era.

Further reading


Comments

Hey Miller! Nicely written.

While I agree with you 100% (even the "[jQuery] plugins are evil" bit, I don't think many JS devs will understand that what they're doing is archaic, problematic, untestable, and downright harder than using small, testable modules. That is, until they've been using modules a while.

I think we need more code examples that show how tiny, reusable, testable modules are HAWT! That was supposed to be one of my goals this summer, but -- you know -- summer happened instead. :)

-- insert shameless plug for the "other" AMD loader curl.js here --

-- John

We typically create a module for each function, rather than create an object with methods -- especially if this object's only purpose is to aggregate functions. That makes no sense at all when you have a module system.

We call these "micro modules", and they are the ultimate in flexibility and testability.

So far, the only downside to micro modules are the added overhead of the UMD boilerplate. (but we're working on a solution for that, too!)

-- J

@John I'm also writing micro modules, a good example of it is the amd-utils project. A good benefit is that I can keep adding new methods without worrying about the file size (since in the end it will only include the methods that are being used). It also encourages smaller/specialized modules since you need to require each helper method explicitly - I find that the amount of dependencies is a good metric to know if your module is doing too much. There is a good discussion about modularity on Google+ as well.

I'm not sure why you listed jQuery and Underscore as the big offenders. jQuery's API never goes more then one property assignment deep, eg. jQuery.noConflict(), jQuery.ajax as "static" functions, or jQuery.prototype.addClass, jQuery.prototype.show as jQuery instance object proto methods. Same is true for Underscore.

Underscore has two patterns it follows, one can be likened the design pattern of the built-in Math object (object with many function properties, non-this-sensitive), the other similar to the Array constructor and it's API (this-sensitive, returns contextual object). jQuery's API follows the design of the built-in Array constructor (this-sensitive, returns contextual object).

These aren't temporary design compromises, they're true to the language's native tongue.

Google Closure Library, YUI or even Backbone are way better examples of what you're discussing.

@rwaldron I used jQuery and underscore to talk about namespace cluttering since they are the big offenders (they have all methods inside the same objects) - Object.keys(_).length === 98, Object.keys(jQuery).length === 108 and Object.keys(jQuery.prototype).length === 105. It's extremely unlikely that all these methods are related to the same concern (low cohesion) and the comment about name collision surely does apply in this case.

In order to keep my entire app out of the global namespace, where it can be accessed by plugins or, potentially, other parts of my app, I use a standard pattern, like this:

(function() { var app = (function(){ return { init: function() {

        }
    }
}());

app.init();

}());

Is that not more robust than using RequireJS where everything you load, as I understand it, is run in the global namespace, and hence, can be accessed/overwritten by plugins or other dodgy programmers working on the project? Please correct me if I'm wrong. Perhaps there is some way of only running required scripts closed within that self-executing anonymous function?

I want to take issue with the objection to plugins. It is not that plugins are some kind of anti-pattern -- it is a case of how they are registered (monkey patching a framework-defined namespace, and in many cases no alternative addressing because of ideological repulsion to namespaces). More specifically, take this namespace collision: $.fn.tooltip is defined by both jQuery Tools and jQueryUI (and other plugins/frameworks too). The IIFE that the former uses offers no alternative namespace to address the tooltip function other than its global plugin name -- more use of namespaces, not less, seem to solve this problem more elegantly (that is, make every "plugin" function available at a unique non-colliding namespaced traversal path instead of the effectively-global $.fn, and then leave it up to applications/callers to wire up "registrations" of components). I want jQueryTools to define $.tools.fn.tooltip, then set $.fn.tooltip = $.tools.fn.tooltip (the plug-point is the alias, not the canonical identifier) -- that seems more graceful, explicit, and succinct than trying to use AMD to solve the same problem? If the objection to namespace is "there is a possibility of collision" -- then more namespaces is just as reasonable of a solution (and sometimes more practical) as less namespaces.

Leave a Comment

Please post only comments that will add value to the content of this page. Please read the about page to understand the objective of this blog and the way I think about it. Thanks.

Comments are parsed as Markdown and you can use basic HTML tags (a, blockquote, cite, code, del, em, strong) but some code may be striped if not escaped (specially PHP and HTML tags that aren't on the list). Line and paragraph breaks automatic. Code blocks should be indented with 4 spaces.