Keeping “require” modules DRY in Node

Update: See the follow-up on StackOverflow. I agree with those who rallied against use of global, but no need to throw the baby out with the bathwater; as shown in that thread, we can instead use “eval” to keep it DRY.

You see a lot of NodeJS code like this:

javascript
< view plain text >
  1. connect = require 'connect'
  2. express = require 'express'
  3. redis = require 'redis'
  4. sys = require 'sys'
  5. coffee = require 'coffee-script'
  6. fs = require 'fs'

BTW this is CoffeeScript, not pure JavaScript, but the same logic applies.

The point is, Node’s module system gives you a layer of abstraction you probably don’t need. 9 times out of 10, people just assign a module to a variable by the same name. You would, wouldn’t you?!! You don’t have to think about alternatives, and you can easily cut and paste other people’s code. And it’s now just an industry convention.

So why not practice convention over configuration, and keep things DRY with the following idiom:

javascript
< view plain text >
  1. "underscore,connect,express,redis,sys,coffee-script,fs"
  2.   .split(',').forEach (lib) -> global[lib] = require lib

Thanks to the “global” object, which is like the “window” object in the browser, we can easily require new libraries without unnecessary clutter.

And – as with any decent convention-over-configuration setup – we can still override the convention if we desire:

javascript
< view plain text >
  1. _ = underscore

9 thoughts on Keeping “require” modules DRY in Node

  1. Except global is process global and therefore evil.

    If only we could inject variables into a module programatically (we used to be able to by setting module[var] but that was removed).

    It can’t be done without leaking all your dependencies into global scope and that’s evil and goes against the concept of dependency and modules.

  2. I hope you’re not surprised to hear me say this, but your suggestion seems to completely kill readability. I like being able to clearly see what the requires are.

    DRY has come to mean “type less” which is an abuse of its real, original goal. In any contest between the this new meaning and readability I’ll choose readability every time.

    Code is communication to humans first, computers second.

    • Chris, I value seeing a lot of lines in one screen, or one arc of human vision. It doesn’t mean no whitespace, but I’d much rather have a clear spec of what’s going on in one line than scattered across half of my arc of vision. And especially so with “requiring” standard stuff, which is really read-and-forget code, as long as you’re using standard modules.

      Also, the benefit of this approach, if library-ized, means you can easily chunk things together, like: “sys,fs,io”.require() “connect,express”require() “math,fibonacci,factorial,prime”.require()

      To me, that’s more succinct than three lists separated by whitespace. It chunks all the modules together in a self-documenting way, so the groups can easily be compared. I suspect we’ll differ on this point :) Which comes down to a matter of individual preference/religion.

      (This is leaving aside the possibly valid argument about the evil-ness of globals. I’m on the fence with that argument, because I think NPM already implies a global namespace. But anyway, it’s an orthogonal issue.)

  3. I would probably opt for something more like the following:

    // imports
    [
        "underscore",
        "connect",
        "express",
        "redis",
        "sys",
        "coffee-script",
        "fs"
    ].forEach(function(module) { 
        global[module] = require(module); 
    });
    

    its the same basic idea, but it makes it alot easier to see what modules are being included, something the current var foo = require(foo) style syntax has and is lost slightly in your version.

  4. Pingback: Keeping NodeJS “require” modules DRY | Definitely Not Robots: Tech

  5. Pingback: JavaScript Magazine Blog for JSMag » Blog Archive » News roundup: deck.js, Yahoo Kills off Maps API, Patterns for Large-Scale JavaScript Application Architecture

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>