I have had the pleasure of interviewing a large number of java  developers in 2014, from fresh grads to seasoned veterans. One of the overriding surprises for me has been the lack of understanding regarding dependency injection, inversion of control and Spring (specifically Spring core).

As a quick refresher, let’s discuss dependency injection (DI).  Objects have dependencies on other objects to do whatever it is that it needs to do. A car has a dependency on an engine to be able to move. It has a dependency on a radio in order for the driver to be entertained. Programmatically, you can have the car create it’s dependencies like so:

public class Car {

 
private final Engine engine;

private final Radio radio;

public Car(){

engine = new Engine();

radio = new Radio();

}

}

There are a number of problems with this approach, the main issue is that it’s really hard to test. You can’t test the functionality of the car without creating a radio, and creating a radio, and creating all the other things.  If the thing you’re testing on has lots of expensive dependencies such as databases then it’s going to be exceptionally slow.  It may not even be possible to create your dependencies during a test, making it impossible to try out. If your object relies on a fully functioning database cluster, chances are you aren’t able to just start one up for the purpose of testing.

This is where dependency injection comes in.  Simply put, the things your object needs (i.e. what it depends on) get given to it (injected). The object plays no role in creation, and just aggregates objects together for some purpose. It can exclusively focus on the functionality or activity that it is designed to perform.


public class Car {
 

private final Engine engine;

private final Radio radio;
 

public Car(Engine engine, Radio radio){

this.engine = engine;

this.radio = radio;

}

}

Now you can pass in whatever engine or radio you want.  This means that it can be mocked out for tests; you can assert on the interaction between the object and it’s dependencies which will result in much cleaner seperation of concerns. It also allows you to swap the implementation- it can be a V8 for a super car. It can be a hybrid for an eco car.  The important thing is a car doesn’t care, or more importantly, it shouldn’t care. Its job is to use the engine to get power for the radio, and wheels, and windscreen wipers. . 

So far we have not touched Spring. There is never a need to touch Spring with regards to DI.  Spring is one of many possible ways of injecting dependencies.  There are other frameworks too, like Google Guice. But if you only take one thing away from reading this article then I hope it is the realisation that Dependency Injection is a style of programming and in no way requires a framework.

With Spring you create XML documents that outline how you would like the object to be created.  At runtime the Spring container then creates everything that is required in the application using reflection and injects the dependencies in.  It is one way of structuring an application, and it’s gotten very popular which is why people seem to find Spring and DI synonymous.

But, would it blow your mind to know that this is also dependency injection?

public class CarManufacturer {

public void buildACar(){

new Car(new PetrolEngine(), new RetroRadio());

}

}

It really is that simple. To quote Martin Fowler, “Dependency Injection is a 25-dollar term for a 5-cent concept”.  We’ve all spent years living in an XML hell and assuming this was the only way of doing things. It is a fallacy to believe that large scale systems cannot be built without a formal DI framework.  I’ve worked on 50,000 line codebases in which the only DI framework was the “new” keyword. It’s mighty powerful and is integrated into the language, and I can guarantee it has full IDE support.

These codebases are a joy to work on.  Application startup times can be sub-second for the entire thing. Testing is easy and clear; how many Spring projects actually test the wiring of the application?  The best feature by far is compile time safety.  With Spring we have taken one of Java’s greatest features, the fact you can compile and be sure your application is syntactically correct, and completely removed it. 

This is not meant as a Spring rant.  This is meant for the developer who has used Spring for five years and didn’t think there was another way.  Dependency injection and Spring are orthogonal concerns and should be treated as so.  We can all agree that dependency injection results in loosely coupled applications that can be well tested.  However,  next time you come to build your application, why not try to structure the dependency injection without a framework for a much leaner and understandable code base?

Image by Clare Bell