262588213843476 · Gist

@nackjicholson If you want to tightly couple your modules to your app, by all means, make them depend on a dependency injection container.

Wait. Wat? Yeah. The whole point of dependency injection is to loosen the coupling between modules, but a DI container bypasses the nice dependency system built-in to node (so any dependency static analysis has to be rolled out custom for your app), and your dependencies all end up knowing each other by dependency name.

Granted, it makes it a little more convenient to swap out dependencies (just replace the named dependency with something else), but if you're building wisely, you're exposing facade wrappers to your app, anyway, so that benefit is nullified.

"Sometimes, the elegant implementation is just a function. Not a method. Not a class. Not a framework. Just a function." - John Carmack

The great thing about functions is they can take arguments. The great thing about JavaScript is functions can even take other functions as arguments.

You want the most flexible dependency injection system? For anything that produces objects, export a factory function that takes an options hash.

Do the same for dependencies that need to be shared between modules. Pass in your logger and your app config objects.

If you're worried about DI, this should be your new favorite pattern:

module.exports = function myAwesomeThing(options) {
  var myAwesomeInstance = {};
  // use dependencies passed in on the options object
  return myAwesomeInstance;
};

Want to get really fancy? Throw Stampit into the mix for truly flexible factories.

Read the original on gist.github.com ↗