Dependency Injection* is a common and useful design pattern. It moves the responsibility for creating a class’ dependencies out to its instantiater, thus allowing for easier customization and testability. A useful DI flavor is to create constructors that directly depend on a set of components, and having the caller provide these arguments upon construction. A DI framework (e.g. Guice for Java or StructureMap for .Net) will save you the trouble of having to pass along these dependencies directly, and instead turn your object construction into beautiful magic such as:
// In real code you will usually use a Provider instead of an Injector Foo foo = injector.getInstance(Foo.class)
Foo foo = new Foo(bar, baz, boom, .......)
This technique is easiest when a class only depends on services and other general classes.
The problem starts when a class just has to have a real, “non standard” paramater passed upon construction (e.g. a TestRunner class that accepts a numberOfRetries parameter). In simple cases, you might just forgoe the use of your DI framework for the simplicity of writing
But what do you do when your class has both a lot of dependencies, and a parameter you just have to pass during construction time?
One option is using a setter to pass along the actual argument, instead of requiring it during construction. While this can work, it has the shortcomings of not being able to store this value in a final field, and not being able to use it during the constructor, often forcing
you to create a separate init() method.
Another possible option is creating a separate factory class. This class will contain all the “easy” dependencies of the original class, and not the parameter. You can construct such a class with the DI framework directly, and then pass the parameter to its build() method. This skips over the disadvantages of the setter approach, and makes the calling code rather clean, but has the small problem of a code duplication between the factory and the class being built – this is especially apparent if the target class has a huge number of parameters – the factory class is essentially boilerplate “stupid” code.
Introducing … Assisted Injection (applause)
Assisted injection is a Guice concept that elegantly solves the parametric construction problem. It is actually documented quite well, so I’ll just describe it briefly – you only need to declare a factory interface, annotate the relevant constructor parameters with @Assisted, tell guice the name of the builder interface for a given class and you’re home free – Guice creates the boilerplate factory class described above behind the scenes.
Foo foo = injector.getInstance(FooBuilder.class).build(3);
* For the purpose of this post I tream Dependency Injection and Inversion of Control as the same pattern, although they are technically two related yet different patterns.