What dependency injection means?
Well, we can break it into two parts:
Part1 : Dependency
Part2 : Injection
Dependency is a general situation that arises , when two classes in your code base are interrelated.
Example :
FirstClass makes use of SecondClass.
We say that FirstClass depends on SecondClass, or alternatively,
we can say that SecondClass is the dependency of the FirstClass.
The other way to state the same thing is to say that FirstClass is the client while SecondClass is the service.
This client-service terminology is very common in software design, that the same class can be a client or a service in different circumstances, and that the client-service definition is not universal.
It's contextual.
We can only assign client and service roles when we discuss two specific classes in our codebases.So, in order to function
clients need references to their services.How do they obtain those references?
Well, there are several approaches:
-Clients can instantiate the services internally
-Or clients can call some global static method , and use the returned reference as a service.
The client is being injected with the services from outside. And that's where the term dependency injection comes from.
So, dependency injection is an act of injecting services into clients
from outside.
Now you know that dependency injection is about clients receiving their services from outside, but what exactly does it mean?
Well, it means that clients use one of the three fundamental dependency injection techniques :
These techniques are:
- Constructor injection
- Method injection
- Field injection.
Therefore I am going to quickly demonstrate you their usage.
I have this client class which depends on three services :
Service1, Service2 and Service3.
- First of all I will use construct injection To inject Service1,and since I'm using constructor injection i can go and further finalize this service.
- To inject Service2 i will use method injection,so I will generate getter for service two.
-And, lastly, I can open public access to this field member of type Service3, so that external entity will be able to reach into the client and set this field to some valid reference. That will be field injection.
The respective benefits and drawbacks of this three fundamental dependency :
-Constructor injection : The benefits are that constructor's signature reflects all the dependencies that the client requires to function,this makes the code easier to read and understand.
-Method injection : When you use this technique, clients' dependencies are reflected in method's signature. This means that you can still inspect the client's method,and understand which services it depends upon.
In addition, method injection can happen after the client has already been constructed.
The cons of method injection is that it is not as explicit as constructor injection.
Yes, you can understand which services the client requires, but they are not grouped together into a single constructor as is the case with constructor injection.
A big disadvantage of method injection is that it can lead to implicit ordering requirements, also known as temporal coupling.
Temporal coupling manifests itself as a requirement that one method must be called before another one. Such ordering requirements can be difficult to keep track of as you make changes to the existing code.
Field injection : it can happen after the client has already been constructed. The bad parts of field injection is that it has all the disadvantages of method injection, namely, it means that it is not explicit enough, and might introduce temporal coupling into your code.
Therefore, those dependencies are not evident, and make the code harder to read and understand. So, which of these techniques is the best ?
Constructor injection is the best , it provides the most major benefits, with no drawbacks.So, you should use constructor injection whenever possible.However, there are cases when you won't be able to do that.So you won't be able to use constructor injection if you don't have the service instance , when you instantiate the client.
For example, that's the case when the type of the service used
is determined at runtime, say by user interaction. In addition, you won't be able to use constructor injection if you don't construct the clients.
That's the case with Activities, for example. Sometimes you will be able to construct the client, but due to special limitations, you won't be able to make changes to construction logic.
For example, if you use Fragments, then you can override their constructors, however Android framework still forces you to use no args constructor, the default one, when instantiating fragments.
Otherwise, all kinds of bad things will happen.
So, all in all, a good rule of thumb to follow is to use constructor injection, unless there is some limitation , that prevents you from doing so.
Now you know the fundamental techniques of dependency injection, and you even understand their respective benefits and drawbacks.
-Is this knowledge enough to use dependency injection in your applications?
-If dependency injection is just about passing services from outside, then why do you need dependency injection frameworks?
-And these frameworks are extremely complex too. Why would you need something as complex as that for something as simple as constructor injection?
What's going on here?
Turns out that this is the most important question in the context of dependency injection.
It's clear that the answer can't be found within one specific client and involves higher level of abstraction.
And that's why any discussion of dependency injection in context of a single class is useless at best, and simply harmful in most cases.
So if you imagine multiple clients that receive their services from outside and account for the fact that these services must be constructed somewhere, you'll quickly realize that there must be some kind of large scale structure in place.
And that's what dependency injection really is : a large scale structure at the level of abstraction of the entire application.
I will explain it in detail in the next Part.
Comments
Post a Comment