November 15, 2004

Dependency Injection minus the overhead

Dependency Injection or Inversion Of Control has changed the way I think about software design, but the extra layer of wiring required has often kept me from realizing its full potential. Now Dave Thomas has come up with a neat way to do Dependency Injection in Rails without any of the overhead that usually comes with it. Even if you're not into Rails or Ruby you ought to read what Dave has to say.

The idea: Since all your classes in Rails descend from a framework class anyway, we might as well let the framework handle the wiring for us. So somewhere we have a Service Locator which knows which implementations are going to be used for which service, like

:student => 'mock_student.rb'

Now instead of using a concrete implementation for a Student interface by saying:

require 'mock_student.rb'

...we simply state which service we are planning to use and let the framework use the Service Locator to wire up the implementation at runtime:

model :student

After that statement we may use the Student interface as if it was a concrete class, and do things like Student.new('Amy') instead of MockStudent.new('Amy') or even StudentFactory.createStudent('Amy').

The beauty of this approach is not merely its unobtrusiveness, but also that you can practically add Dependency Injection as an afterthought. David Heinemeier Hansson raves:

It's basically business as usual with DI for free. So you wouldn't even have to choose whether to do DI or not up front. Just as soon as you're feeling the pain, you start injecting.

Neat.