Why should we use dependency injection in Angular
In this article, I am going to discuss Why should we use Dependency Injection in Angular Application. Please read our previous article where we discussed Dependency Injection with one example. At the end of this article you will understand why should we use dependency injection and what are the advantages of using dependency injection in angular.
Why should we use Dependency Injection in Angular Application?
Let us understand why do we need dependency injection in angular with an example.
Let us say we want to build a Computer. As we know in order to build a computer we need several objects like processor, hard-disk, ram, mouse, keyboard, etc. To keep this example simple, let’s say we just need a processor object to build a computer.
The following are our Computer and Processor classes. As you can see, at the moment, we are not using dependency injection mechanism to inject the dependency object. To build a Computer we need a Processor object and here the Computer class is now creating an instance of the Processor class. You may aware of this type of programming style as it is easy to understand.
Problems with the above code:
But there are 3 fundamental problems with the above code
- This code is difficult to maintain over time
- Instances of dependencies created by a class that needs those dependencies are local to the class and cannot share data and logic.
- Hard to unit test
Why this code is difficult to maintain?
Let us say, the requirement changes, now in order to create an instance of the processor class, the Processor class needs to know the speed of the processor. One way to achieve this requirement is by passing the processor speed as a parameter to the constructor of the Processor class as shown in the below image.
But with the above changes in the Processor class will breaks the Computer class. That means every time the Processor class changes, the Computer class also needs to be changed. At the moment, the Computer class has only one dependency. But, in reality it may have many dependencies and those dependencies in turn may have other dependencies. So when any of these dependencies change, the Computer class may also need to be changed. Hence this code is difficult to maintain.
How to overcome the above problem?
The reason we have this problem is because the Computer class itself is creating the instance of the Processor class. Instead if an external source can create the processor instance and provide it to the computer class, then this problem can be very easily solved and that’s exactly what dependency injection does. I have rewritten the above code using dependency injection, DI for short as shown below.
Notice with Dependency Injection, the Computer class is not creating the instance of the Processor class itself. Instead we have specified that the Computer class has a dependency on Processor class using the constructor. Now, when we create an instance of the Computer class, an external source i.e the Angular Injector will provide the instance of the Processor class to the Computer class. Since now the the Angular injector is creating the dependency instance, the Computer class need not change when the Processor class changes.
Now, let us understand the second problem
Instances of dependencies created by a class that needs those dependencies are local to the class and cannot share data and logic.
The Processor class instance created in the Computer class is local to the Computer class and cannot be shared. Sharing a processor instance does not make that much sense, so let’s understand this with another example.
Let us say we have a service called UserPreferencesService which keeps track of the user preferences like colour, font-size etc. We want this data to be shared with all the other components in our application. Now if we create an instance of this UserPreferenceService class in every component class like we did in the Computer class, the service instance is local to the component in which we have created it and the data cannot be shared with other components. So if we need this UserPreferencesService in 10 different components, we end up creating 10 instances of the service, one for each component. As the service instance is local to the component that has created it, the data that local service instance has cannot be shared by other components. If this does not make sense at the moment, please do not worry, we will discuss it with a working example in our next article.
On the other hand if we use Dependency Injection (DI), the angular injector provides a Singleton i.e a single instance of the service so the data and logic can be shared very easily across all the components.
Hard to unit test:
From unit testing standpoint, it is difficult to mock the processor object, so unit testing Computer class can get complex. In this example, the Computer class has just one dependency (i.e the dependency on the Processor object).
In a real world application, a given object may have a dependency on several other objects, and those dependencies inturn may have dependencies on other objects. Just imagine, how complicated unit testing can become with all these hierarchies of dependencies if we do not have the ability to mock the dependencies.
With Dependency Injection it is very easy to mock objects when unit testing. This is one of the greatest benefits of DI.
If you are new to unit testing and mocking, it may be difficult for you to understand why unit testing can get difficult and complicated if we do not have the ability to mock dependencies. In our upcoming videos we will discuss unit testing and mocking and it should be much clear at that point.
Advantages of Dependency Injection in Angular?
- Create applications that are easy to write and maintain over time as the application evolves
- Easy to share data and functionality as the angular injector provides a Singleton i.e a single instance of the service
- Easy to write and maintain unit tests as the dependencies can be mocked
In the next article, I am going to discuss Angular Singleton Service with an example. Here, in this article, I try to explain why should we use dependency injection in angular and what are the advantages of using dependency injection in angular application.