First, some JavaScript background.

Skip to the good stuff

Here at Imulus, we like to namespace our JavaScript by wrapping our classes in static modules. We accomplish this by simply creating an object literal with a variety of members: classes (constructors), constants, variables and static methods.

Here is a pared down example of a simple module:

The benefits of this technique are obvious; it allows us to have loosely-coupled, modular code that is nicely organized, available without instantiation and protects the global namespace from pollution.

In reality, however, one mammoth object literal in a single file is a lousy way to structure your code. Instead, what we do is organize module members into separate files in a logical fashion, å la Ruby. The module and all of its static members exist in a single file named after the module, and all of the module’s classes exist in a directory named after the module with each class file named after itself without the namespace. By using this structure, files are much easier to find because the naming convention mirrors the the module namespace.

The directory structure ends up looking like this:

And the module above would be structured like this:

You get the picture. This probably looks familiar to a Rubyist. Here’s the analog:

Snakes on a Train

By now it’s probably evident how much we obsess over code structure, organization and namespacing. While experimenting with CoffeeScript, this has been an ongoing concern.

This is the example from the CoffeeScript demo page:

I love that Coffee has made dealing with prototypes much easier with the ‘class’ and ‘extends’ keywords. This is great, and by itself works like a charm for singular, somewhat global classes. However, for any application with a sizeable codebase this simply isn’t practical without ending up with insane class names.

The ideal solution would be to introduce a ‘module’ keyword similar to Ruby’s.

Other people agree. But there are a number of JS limitations that prevent this from being a viable solution in CoffeeScript.

The Really Good Stuff

By its own golden rule, CoffeeScript is: “It’s just JavaScript”. So, we can namespace our CoffeeScript classes in the same manner we organize our modules in vanilla JS.

Extending on the example above (ha-ha, get it?), I’ll demonstrate how to namespace your Coffee classes in a simple, elegant way.

Focusing only on the snakes for now, lets set up our basic classes.

Now, we want to create ‘Forest’ and ‘Savanna’ modules that have a habitat and snakes of their own.

animal-diagram

Just like JavaScript, we could wrap all of the module members in an object literal:

But we would run into the same problem when the codebase reaches any kind of scale: enormous, single-file object literals. So let’s introduce a new function for creating module members.

(Yes, I am aware that this is attaching the objects to the global namespace. This is what we want. It allows us to add members to the module later.)

Now we can use the ‘module’ function like this:

Pretty elegant, right? Additionally, by using the ‘module’ function we can now organize our code into multiple files:

We can also extend standalone classes with module classes:

  • http://xtargets.com brad phelan

    I came up with a similar idea and documented it on the coffeescript website. The notation is slightly tighter than yours and takes advantage of some coffeescript quirks such that you can define a class as

    class @Foo

    rather than

    class Foo

    which attaches the class to the current object which can be the module.

    Details here https://github.com/jashkenas/coffee-script/wiki/Easy-modules-with-coffeescript

  • http://andrewseddon.com Andrew Seddon

    What’s wrong with using CommonJS for modules? I’m using it server/client side to organise CS

  • http://psionides.eu Jakub Suder

    You can just write “class Forest.Snake” instead of “Forest.Snake = class extends Snake”. The way I’ve done it is that I have one file included at the beginning which defines namespaces, like this:

    window.BD =
    ??Models: {}
    ??Collections: {}
    ??Views: {}

    And then e.g. for a BaseView class I create a views/base.coffee file with a class declared like this:

    class BD.Views.BaseView extends Backbone.View