Coupling and dependency injection
The following is a brief summary of dependency injection with particular reference to architectural coupling as found in standard 3 tier Java EE type projects.
Two classes are coupled if one class contains a reference to another. In the example below the Person class is coupled to the String class as the fields of the Person class include a String type field. The Person class depends on the String class and were the behaviour of the String class to change the Person class may break.
Some coupling is a necessary part of object orientated programming but it is to be avoided as much as possible as it reduces the flexibility of your program. In the example above the dependency of the Person class on the String class is a reasonable level of coupling given the low likelihood of the String class being changed but when adding dependencies your own reference types which are much more likely to be changed in response to changing requirements then coupling becomes more of an issue. If you have a class that is coupled to a large number of other classes in your project (e.g. a Data Access Object or DAO that provides database access to throughout your project) then refactoring your project after changing the DAO is not trivial.
This problem can be ameliorated by the use of design steps collectively known as dependency injection.
- Program to interfaces – where you would usually embed your reference type into a class replace it with an Interface which specifies the behaviour your class will provide.
- Pass reference by parameters – where you have an Interface reference, initialise it by passing the implementation of the Interface as a parameter using a
setReference(InterfaceReference ir)type method.
- Centralise configuration – create a “container” that constructs the specific implementation and uses the set method defined in stage 2 to pass it the implemented interface to the dependent class
Following these 3 steps means that the interface remains constant but the implementation can be updated by changing code in the container class only. In most frameworks (e.g. Java EE, Spring) a sophisticated container is provided which can read from configuration files.