by Saleh Najar
The Dependency Injection pattern is a great pattern that enables Agility in a system. By Agility, I mean the Agility architectural quality attribute which includes Reusability, Configurability, Flexibility and Adaptability. To understand the Dependency Injection pattern correctly, the light should be shed on the 'dependency' part as this is the key to understanding the pattern then applying it.
In order to perform its role, every system or component depends on other systems or component. It is the flexibility in controlling those dependencies that gives us the power of "polymorphism" changing behaviour, on any scale.
The Dependency Injection pattern solves the problem of who chooses your dependencies. A component or system has two choices in relation to its dependencies: It either itself selects which dependency to use or have it selected for it by its client. The former produces rigid systems and the latter produces agile systems.
The Dependency Injection pattern says that the dependency of a component should be passed from the outside rather than from the inside. The user/caller/client of a system decides what dependency the component must use to do its job.
Why is this important? Because it introduces tremendous flexibility and change of behaviour at runtime and not to mention the support for the OCP principle (Open-Closed Principle). For example, let's say we have an invoicing system that depends on a certain component to calculate its taxes depending on the country. Using the Dependency Injection pattern, we should pass the tax calculation component to the invoicing system from the outside. That way, in Canada for example, we can pass it the Canadian component to calculate taxes but if the product was bought in the U.S., we can pass it the U.S. component to calculate taxes. With the Dependency Injection pattern, we now have the flexibility to decide at configuration time or runtime how should taxes be calculated without modifying any code.
The Dependency Injection pattern is not limited to Object-Oriented. It can be applied at any scale from the lowers function level to higher levels of abstraction such as services.
So next time you're designing a component or system, strive to have its dependencies passed in from the outside and you'll have a higher quality and agile system.