ÆFLASH

Dependency Injection

I had heard the term "dependency injection" thrown around many times before, but hadn't really taken the time to research it. However, I recently had an epiphany and I realized what it is and why it is an important (and simple) idea.

Say you had a class or module, I will use javascript as an example:

var FooBar = function () {
    this.foo = new Foo();
    this.bar = new Bar();
    //...   
};

//...

FooBar is a class that has 2 member variables, that are themselves classes. They are both instantiated and assigned in the constructor. However, we could rewrite this to be:

var FooBar = function (foo, bar) {
    this.foo = foo;
    this.bar = bar;
    //...
};
//...

...and elsewhere, where FooBar is actually used, you have:

SomeFactory.createFooBar = function () {
    return new FooBar(new Foo(), new Bar());    
};

That's it. The dependencies Foo and Bar are simply passed in ("injected") to the FooBar constructor. The class FooBar does not need to explicitly state it's dependencies, it just relies on what is passed to it during instantiation. If these were modules, FooBar would not have an explicit dependency on Foo and Bar -- it would be implicit.

Why is this important?

First of all, it enables easy testing. Say Bar was a module that interfaced with a remote service, and was slow. However, you want to be able to test the basics quickly in a unit test. You could then simply do:

TestFactory.createTestFooBar = function () {
    return new FooBar(new Foo(), new MockBar());    
};

MockBar would just be a module that implemented all the same methods as Bar. In a strongly typed world, Foo and Bar would be defined as interfaces, and you would simply pass in a concrete implementation depending on whether you wanted the real, mock, or otherwise alternate functionality. In a scripting language or dynamically typed language (or go), you can just rely on duck-typing, and pass in any object that has all the requisite methods.

It simplifies your app's dependency graph. Instead of FooBar depending on Foo and Bar, whatever depends on FooBar also depends on Foo and Bar, eliminating a level in the tree. The order in which FooBar, Foo, and Bar are included is also irrelevant.

This is also a way to simplify a module's explicit dependencies. This can be useful in the NodeJS/NPM world. A lot of NPM modules rely on the same modules, but slightly different versions. One module will depend on underscore@1.22, another at underscore@1.24, etc. and each would end up with a separate copy in it's node_modules folder. If your app includes both of these modules, you will have some redundancy and duplication. (A concern if you are building for the browser!) However, if a module expected to have an underscore module passed in during initialization, this would remove the explicit dependency, and your app could rely on a single library instead of several.

Grunt plugins do this well -- every plugin expects to have a grunt object passed in to it's main function. This avoids the problem of your 5 plugins each including a slightly different Grunt version, each of which would have to parse your Gruntfile, and talk to the other Gunt versions. Really inelegant, and kind of a nightmare.

This did cause some issues when there were some breaking changes between Grunt 0.3.x and Grunt 0.4.x -- plugins had to be updated to support the API changes. However, it was simply up to the implementor to specify the versions of grunt plugins that were compatible with the relevant grunt version.

AMD can also be thought of as dependency injection at the module level. Your module factory function expects to have it's dependencies passed into it. RequireJS even supports alternate configs where you can override modules -- in other words, swap out ModuleFoo for ModuleMockFoo behind the scenes for testing.

All in all, it is a simple way to write more decoupled and modular code.

code javascript modules dependency injection