Evolving Software

Dependency Injection is a process of supplying external dependencies to componenets, changing the flow of control of the system to be inverted in comparison to the traditional architecture of software libraries. Dependency Injection builds of the concept that you should favor composition over inheritance [Effective Java Programming Language Guide, chapter 4, item 14], but extending it to say that the specific implementations of the subcomponenets that you are using to compose your class should be fully decoupled from the class itself.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public interface BrakeSystem {
 
}
 
public interface Engine {
 
}
 
public class Car {
 
 private Transmission transmission = new AutomaticTransmission();
 private Engine brakes = new GasEngine();
 
}

We can see that in class Car we’ve coupled the implementation of AutomaticTransmission and DiscBrakeSystem to the implementation of Car. What do we do when we want to create an instance of Car that has a manual Transmission? The answer is dependency injection. In this example we find it trivial to remove the coupling of subcomponent implementations by passing in the subcomponents at time of construction rather than at the time of compilation.

1
2
3
4
5
6
7
8
9
10
11
public class Car {
 
 private Transmission transmission;
 private Engine engine;
 
 public Car(Transmission transmission, Engine engine) {
    this.transmission = transmission;
    this.engine = engine;
 }
 
}

Now we can use the constructor to create variations of the cars behaviour.

1
2
3
4
5
6
7
8
9
10
11
12
13
public class CarFactory {
 
 public static final Car createAutomaticCar() {
 return new Car(new AutomaticTransmission(),
 new GasEngine());
 }
 
 public static final Car createManualCar() {
 return new Car(new ManualTransmission(),
 new GasEngine());
 }
 
}

Using this method we can vary the components of car without subclassing it, allowing the freedom to provide numerous unique representations of cars without changing anything in the car class itself. It’s all left to wiring the classes together in an appropriate way.

Can’t I just use the Service Locator Pattern?

Well it is true that dependency injection does aim to solve the same problem as the Service Locator Pattern, usage of the pattern requires you to build in logic that performs the dependency resolution and construction. This introduces cross cutting behaviour that disrupts the cohesion and singular responsibility of the class. By removing the service location logic and relegating it into a factory or some other framework level function, a high level of cohesion can be maintained. This will be true for both the object and its factory, as the single responsibility of the factory is to construct instances of the class, and the class just has to be itself.

Usage of Dependency Injection Frameworks

I sit firmly on the fence about the usage of frameworks for dependency injection, because it seems that they all have a dark side to them that in one way or another reduces readability/trace-ability of the classes. Some like Google Guice use method annotations to define where the injection points are, and while this seems to be be a relatively concise way to inform the framework it adds a lot of extraneous information to your code that doesn’t really make sense within the context of the class.

This is where I actually like the use of factories that construct the objects and do the injection for you. It’s generally clean, and it localizes the couplings to a factory which is naturally where they should be. The downside is sometimes dependency injection can get several layers deep (you have a class that requires classes which require classes etc) and the notion that you would have a factory method for each one of the permutations is quite excessive. However if you only add a method that builds the specific combination that you are looking for this might strike a nice middle ground.