Simplifying Dependency Injection


Wednesday, April 14th, 2010 - By Abhishek Rakshit


A lot has been written about Dependency Injection (DI) however, it still remains a complicated topic. The main articles on this topic are quite thorough and provide really good information but in the process, the basic principle behind DI becomes hard to comprehend. DI is in fact fairly simple – its main goal is removal of a class dependency on some code. This class dependency is then ‘injected’ into the code where it is needed. Using dependency injection helps in code maintenance, re-usability, testability, and improves code readability.

An Explanatory Example
In one of my projects, we needed to use DI to inject different implementations into a core service. Our project needed to be deployed to multiple types of servers while we wanted to share large portions of the core code and at the same time have different functionality for users.


At its simplest, all we needed to do for DI was:


public class Account {
  public User user = new DefaultUser();
  public UserPrivileges getUserPrivileges() {
    return user.getPrivileges();
  }
}

Among other tasks, the Account class is responsible for getting users information, which it does by depending on the User class (or interface) to provide the functionality. We can have multiple classes extending the User class to provide different implementations of the getPrivileges method.


public class Controller {
  public void getAdminUserAccount(){
  Account account = new Account();
  // Controller injects the admin user, overriding the default user
  account.user = new AdminUser();
  return account;
  }
}

The Account class needs to only depend on the User class and customized implementations can be injected by setting the user field as shown in the second code snippet.

Since the dependency in the Account class is injected externally, hence the name Dependency Injection. To put it technically, the User class is the “dependant”, the overrides are the dependencies and the method which sets the override field is the “injector”.

Benefits
DI helps to re-use code in different contexts with customized implementations. It can also be used when code needs to be given to third-party users who can then plug in suitable implementations. Apart from the mentioned benefits, DI can be used to break code cycles and also for code testing since it allows the dependencies to be mocked or stubbed out. DI removes unnecessary dependencies and makes the code more portable as the dependencies are mostly on interfaces. It also helps in eliminating dependency carrying. Dependency carrying is the concept of a method passing on object(s) which it does not use itself. So, all that the method does is pass on the object(s) to some other method. Instead the object(s) can be injected directly to the method which uses them and not through a chain of methods which only act as carriers. All in all, DI can make your code easy to manage and change.

Complications with DI
As always there are some complications with DI such as added indirection in the code, as the injection is performed externally. In cases where the implementation is not always accessible understanding code can become hard. Moreover, when using a framework to DI, the controllers themselves are hard to test and managing the configuration files (for frameworks maintaining verbose configuration files) is a cumbersome task when the project becomes large.

Any Thoughts?
What do you find complicated in DI? In which scenario was DI helpful to you or Are there cases where you avoided using it? Share your thoughts about Dependency Injection.


 

5 Comments

  1. James says:

    I find it is useful for testing. You can provide a mock hibernate/jpa object and not worry about munging your DB.

    • abhishek says:

      Very Right James,
      Using DI for testing is currently one of its main uses as it provides the tester the ability to test individual components. Mock objects can be configured to test for all kinds of behavior. Moreover, the mock objects can record what methods are invoked on them, so it can be verified that the component using the mock uses it as expected.

  2. [...] Eine Einf├╝hrung in Dependency Injection die zeigt, dass es gar nicht immer so kompliziert sein [...]

  3. [...] it, a lot of the sites out there explaining it can be confusing. On the Architexa blog there's a dead simple explanation of DI and what it's good for (warning: it's not a PHP example, but it translates over). DI is [...]

Leave a Reply