The power of design patterns — Dependency Injection
Start using the dependency injection design pattern now!
Dependency injection is one of the simplest patterns to implement. It works by defining dependencies through interfaces, and passing specific implementations through constructors or setters. This creates some major benefits:
- Decoupled objects — Dependencies for an object are created outside the object. Objects are no longer concerned with a specific implementation to get a desired behavior.
- Testability — Without Dependency Injection, an object, along with all of its dependencies have to be created. If one of the dependent objects can’t be tested, then the main object can’t be tested. With dependency injection, dependencies are passed into an object, allowing for mock objects to be created instead.
Example
(Complete code example at the end)
Lets examine a common structure:
- Data Layer: Contains services to access data
- Feature Layer: Uses the data layer to compose features
- Client Layer: Displays features the the user
In this example, a feature needs to make an API call. The data layer contains the remote service, and the feature consumes the remote service:
This leads to unmaintainable code:
- The remote service and feature are now coupled, if the remote service needs to change it will affect the feature.
- The feature isn’t testable, because the remote service isn’t testable.
Instead of having tightly coupled objects we can use dependency injection to decouple them:
This is a lot more maintainable:
- The remote service and feature are decoupled. The remote service can change without causing the feature to change.
- The feature can be tested. Since the remote service isn’t testable, we can create a mock service to fulfill the dependency. That can be passed into the feature when running unit tests.
This example shows how using the dependency injection design creates clean, maintainable code. Applying the pattern moved the creation of dependent objects outside the consuming object. This decoupled the objects from each other, and enabled unit test to be written.
Start applying the dependency injection design pattern to your own projects today!
Full code example: