In designing an object-oriented application, a major tenet of design is “loose coupling”. It means that objects should only have as many dependencies as is needed to do their job and the dependencies should be few. Furthermore, an object’s dependencies should be on interfaces and not on “concrete” objects, when possible. (A concrete object is any object created with the keyword new.) Loose coupling promotes greater reusability, easier maintainability, and allows you to easily provide “mock” objects in place of expensive services.
The “Dependency Injection” (DI) is also known as “Inversion of Control” (IoC), can be used as a technique for encouraging this loose coupling.
There are two primary approaches to implementing DI:
- Constructor injection
- Setter injection
Obviously, at some point, something must be responsible for creating the concrete objects that will be injected into another object. The injector can be a parent object, which I’ll call the “DI controller”, or can be externalized and handled by a “DI container” framework. What follows is a brief overview of the various approaches for using dependency injection techniques.
It’s the technique of passing objects dependencies to its constructor.
E.g. “Person” class exposes a method for retrieving every home address of person. Consequently, the “Person” class needs a data-access object for communicating with the database. Assume, an AddressDAO exists which implements the interface IDAO.
One way that a “Person” object can get this dependency is by executing the following within the: IDAO obj1 = new AddressDAO();. The disadvantage of this are:
- The benefit of having the interface in the first place has been negated since the concrete instance was created locally.
- AddressDAO cannot easily be replaced by a mock object for testing purposes.
Hence, to avoid this following must be done.
Note that the constructor accepts an interface and not concrete object. Also, note that an exception is thrown if the orderDao parameter is null. This emphasizes the importance of receiving a valid dependency. Constructor Injection is, in my opinion, the preferred mechanism for giving an object its dependencies. It is clear to the developer while invoking the object which dependencies need to be given to the “Person” object for proper execution.
But consider the following example… Suppose you have a class with ten methods that have no dependencies, but you’re adding a new method that does have a dependency on IDAO. You could change the constructor to use Constructor Injection, but this may force you to changes to all constructor calls all over the place. Alternatively, you could just add a new constructor that takes the dependency, but then how does a developer easily know when to use one constructor over the other. Finally, if the dependency is very expensive to create, why should it be created and passed to the constructor when it may only be used rarely? “Setter Injection” is another DI technique that can be used in situations such as this.
Setter Injection does not force dependencies to be passed to the constructor. Instead, the dependencies are set onto public properties exposed by the object in need. As implied previously, the primary motivators for doing this include:
- Supporting dependency injection without having to modify the constructor of a legacy class.
- Allowing expensive resources or services to be created as late as possible and only when needed.
Here is the example of how the above code would look like.
Setter Injection should be used sparingly in place of Constructor Injection, because:
- It does not make it clear to the developer which dependencies are needed when, at least until a “has not been initialized” exception is thrown.
- It makes it a bit more difficult to track down where the exception came from and why it got thrown.
With this said, Setter Injection can save on modifying a lot of legacy code when introducing new methods, and can provide a performance boost if the dependency is expensive or not easily accessible.