July 25, 2020
What is dependency injection
Dependency injection is a technique to organize dependencies of services at runtime. If you have a really large application you may have encountered the problem of passing some objects down the whole stack and maybe using singletons and static method to overcome this.
But these are hard to substitute in Tests. Though to avoid this we let a framework organize these dependency issues for us. See Wikipedia .
You may know dependency injection from some popular frameworks like Spring or Angular .
Terms of dependency injections
In order to understand the following paragraphs I will explain some common vocabulary of dependency injection.
Module
A module is somewhat a container for your dependency graph. It contains all objects known to the dependency injection context.
To separate dependency injection contexts you can create multiple modules.
Component
A component is the element that requests and receives the dependencies from the framework.
Getting started with Koin
Koin lets you organize your dependencies in a functional Kotlin native style.
fun myModule() = module {
single() { DataBaseConnector() }
single() { WebService() }
}
This declares a module with a DataBaseConnector
and a WebService
as Singletons.
To get started with injection you can simply call startKoin
with a list of modules as parameter.
fun main(args: Array<String>) {
startKoin(listOf(myModule())
stopKoin()
}
Between startKoin
and stopKoin
we can leverage the dependency injection framework.
fun main(args: Array<String>) {
startKoin(listOf(myModule())
MyComponent()
stopKoin()
}
MyComponent
is a component which will receive the dependencies.
To access them in the class we use the delegate feature by inject()
of Kotlin.
class MyComponent() : KoinComponent {
private val dataBaseConnector by inject<DataBaseConnector>()
private val webService by inject<WebService>()
init {
// Get the data from the database
dataBaseConnector.getRows().let {
// Display the data with the webService
webService.serve(it)
}
}
}
Comparison to Dagger
Pros
The main advantage over the Dagger framework in my eyes is, that you don’t need code generation and therefore a simpler buildprocess.
Koin leverages more of Kotlins features and solves dependency injection in a functional style that is pretty concise.
Dagger has the advantage of not defining the dependency tree by hand.
You can just annotate all your classes with @Inject
and @Singleton
and dagger resolves this for you.
But the extra effort you have in Koin is definitely worth just because you get a cleaner dependency notation all in one place.
Cons
A major drawback of Koin in my eyes is the Logger. It has no SLF4J binding and has to be implemented by hand. Koin has some arbitrary KoinLogger
for all internal logs. Apart from this I have found the logger quite useful at debugging dependency problems.