The Dependency Injection… maybe for some of you this is the first time you hear about this word. Or you’ve heard about it but don’t know what it’s about?. Or maybe you already know and using it nowadays? It’s OK though, let’s review about it. I’ll explain you the basic of what it is and how it works.
Quoted from Wikipedia,
In software engineering, dependency injection is a technique whereby one object supplies the dependencies of another object. A “dependency” is an object that can be used, for example as a service. Instead of a client specifying which service it will use, something tells the client what service to use.
So, what’s the meaning? Hold on, I’ll give you an example,
Let’s assume you have a class named CoffeeMaker to create a coffee. And you need to add a “roast” service to it in order to roast some CoffeeBeans to make an Espresso.
If we look from the perspective of dependency injection concept, this CoffeeMaker is our target class (client), and we need to inject an object named RoastService to it, so that we can get the functionality as we want. Yes, we want an Espresso!
Without dependency injection, our logic would look like this,
This is not efficient, because every time we want to create a CoffeeMaker instance, we have to create a new instance of RoastService, and pass it manually to CoffeeMaker’s constructor.
What if you have a situation that had to handle many type of coffee? or recently you’ve buy a large amount of CoffeeMaker and want to add several functionalities to all of it? or maybe you need to add a new service to your CoffeeMaker? It’s just a pain in the ass to manage it.
To avoid this problem, we need something that can add RoastService to our CoffeeMaker without changing the whole code base.
This is why the dependency injection is created. With DI, we can easily inject the RoastService repository to the CoffeMaker.
Wait.., RoastService is a repository?!
Why do you call RoastService as a repository?
Let’s look at the definition of dependency injection again,
A “dependency” is an object that can be used, for example as a service.
This means that any object we use for some purpose is called dependency or repository (many programmer prefer to use the repository word though).
Okay.. so we need to inject the repository to the client.., but how?
Actually, you can create your own dependency injection method from scratch. But I recommend you to use the dependency injection framework that have been tested & trusted by community out there. In Kotlin, we can use the dependency injection framework named Koin.
What is Koin?
Koin is a pragmatic lightweight dependency injection framework for Kotlin developers. Written in pure Kotlin using functional resolution only: no proxy, no code generation, and no reflection.
With Koin, we can easily implement a dependency injection with just a three simple step.
- Declare a module
2. Start your Koin
3. Inject your repository class
You only need to use inject word to inject your repository for your client. But, this is just the basic usage. With Koin, you can do more than this. Let’s get started.
The Magic of Koin
Inject by Constructor
Koin support injection by constructor. Take a look at the code below.
with a get() method, Koin will automatically inject what class is suitable for that parameter, without explicitly declaring what the type of that class.
Module & definitions
You can apply a KoinTest interface to use your Koin in unit testing.
Simple right?, easy peasy lemon squeezy!
If you want to learn more about Koin, read the quickstart below:
Back to our Coffee Maker Problem
I’ve show you how easy it is to use Koin and what benefit we can get with it. Now, let’s make some espresso!
First of all, let’s prepare our coffee type and the ingredients.
Then, create our RoastService class to implement how we process the ingredients.
You’ve know that CoffeeBeans is our main ingredients to make a coffee, that’s why we declare it in constructor, so that Koin can directly inject it on module declaration.
Our roast service is ready, it’s time to build our CoffeeMaker.
Last but not least, prepare the Koin’s module and start it. We will use singleton pattern to our RoastService & CoffeeMaker, because we want this class is single instance only.
Enjoy your Espresso! Oh, be careful.., it’s hot..
That’s all. As you can see, it’s easy to implement dependency injection (DI) with Koin.
From this, I hope you can learn the basic of dependency injection and how to implement it with DI framework, in this case we use Koin.
But maybe for some of you still think,
DI is so complex, but why many programmer use it? what’s the point of this all?
Beside of injecting repository, dependency injection is great for structurize your repository class, it can also modify the creational behavior of your repo. You may seems don’t trust nor understand it, because I only give you a simple problem case. Trust me, you will need DI when you meet a complex structure & architecture of an app.
From the quote,
Instead of a client specifying which service it will use, something tells the client what service to use.
Now you know that “something” is a DI. And that’s mean, instead your your client code manually specify what service it will use, DI will tell your client what service to use.