Skip to content

Shashank Mishra

Dependency Injection for Beginners

Dependency Injection, Android, Dagger3 min read

You might have heard of dependency injection. It’s been one of the hot topics in the Android community for the past few years . So you look around on the internet, find articles about Dagger and are lost when people start mentioning Modules, Components, and Scopes. That is because those articles don’t do a very good job of explaining what is dependency injection (Thermosiphon anyone?) & why you need it.

Before diving into such articles, you must have a clear understanding of why are you using dependency injection (DI) and what benefits does it provide you. As the Principle of Applying Principles states, “The good and proper application of each principle, pattern and practice requires you to understand why you are doing what you’re doing”. So this article will try to answer the following questions :

  • What is a dependency
  • What is dependency injection
  • Why should you use it

What is a dependency

As you can infer from its English meaning, the word dependency indicates that a part of code depends on some other part of code. It could be either loose coupling (where the code depends on an abstract class or interface) or strong coupling (where the code depends on a concrete class). I believe examples provide a better understanding so lets see an example.

snippet_1
1Class A {
2
3 public int doSomeWork() {
4 B objectB = new B();
5 int result = objectB.getResult();
6 int finalResult = result * 2;
7 return finalResult;
8 }
9
10}

The function doSomeWork uses some functionality from class B. So class A has a dependency on class B. If class B required some constructor parameters, it would become the responsibility of doSomeWork to provide those parameters.

snippet_2
1class A {
2
3 public int doSomeWork(int p1, int p2, String p3) {
4 B objectB = new B(p1, p2, p3);
5 int result = objectB.getResult();
6 int finalResult = result * 2;
7 return finalResult;
8 }
9
10}

If the function depended on more objects each of which required multiple constructor parameters, the function doSomeWork would become too unwieldy. Instead of just doing the specific thing it was meant to do, it would also contain code for creation of the needed objects. As you can see, it is not really wise to write our code this way. Now onto our second question, what is dependency injection.


What is dependency injection

The English language to our rescue again! Dependency injection is the act of injecting dependencies. Well, injection is just a fancy word for providing. So dependency injection is the act of providing dependencies.

Hence, instead of this,

snippet_3
1class A {
2
3 public int doSomeWork(int p1, int p2, String p3) {
4 B objectB = new B(p1, p2, p3);
5 int result = objectB.getResult();
6 int finalResult = result * 2;
7 return finalResult;
8 }
9
10}

we could have this

snippet_4
1class A {
2
3 private B objectB;
4
5 public A(B objectB) {
6 this.objectB = objectB;
7 }
8
9 public int doSomeWork() {
10 int result = objectB.getResult();
11 int finalResult = result * 2;
12 return finalResult;
13 }
14
15}

That’s it! You just performed dependency injection. The dependency (Class B) was injected (as a constructor parameter) into the code which needed it (Class A). All the fancy DI frameworks and libraries try to help you in making your code less like snippet_3 and more like snippet_4. Well, why would you want to do that? Let’s move on to our next section to find out.


Why should you use it

1) Reducing responsibility : In code snippet_4, the function doSomeWork is not responsible for the creation objectB. It does not care how objectB is provided or who provides it. It’s only responsibility is to ‘do some work’, and the fewer responsibilities a piece of code has, the less error prone it is.

2) Easier testing : In code snippet_3, doSomeWork is explicitly responsible for creating the objectB. For testing, the creation of object should be done outside the code to be tested. As an example, we could pass a fake objectB in snippet_4 to test doSomeWork.

3) We don’t need to change unrelated code : In future, if we change B (say, we add a constructor parameter), it will require us to change doSomeWork too. If we had initialized B in 10 places throughout our code, it would have required us to change the code in 10 different places If we use dependency injection, we will just modify the part where we initialized B.

4) Improved code reusability : If you use dependency injection, you just need to initialize B just once. You can then just pass that object to whatever part of code that requires it. This makes our code more reusable.


What next

For a more concrete tutorial about dependency injection on Android, check out this playlist by TwistedEquations. You can see how creating each dependency manually can get quickly get out of hand.

I would recommend you to stay away from Dagger Android till you get comfortable with @Module, @Provides, @Inject and @Component. Although it introduces a lot of stuff to reduce the boilerplate required for Dagger, you need to have a clear understanding of the aforementioned concepts before you try it. Learning Dagger and Dagger Android together would be too much for a beginner.


So that’s it. I have tried keeping this article simple and not use any of the technical terms usually used while explaining dependency injection. Thanks for reading my first article!



This article was originally published on Medium

© 2020 by Shashank Mishra. All rights reserved.
Theme by LekoArts