Inside Koin 3.2 - Optimizing your Modules with Includes
Hello Koin users 👋
After an article on the new Koin DSL, we continue to dig into Koin 3.2 release content. First, be sure to update to the latest version (see the dedicated setup page).
The new Koin 3.2 release is ready 🎉 ! What's inside?
— InsertKoin.io (@insertkoin_io) May 11, 2022
- Kotlin 1.6.x
- Latest Android updates
- ViewModel Reworked ...
- Time API fixed
- New Constructor DSL
- Better Module Loading
- New Native Memory
- Ktor 2.0
- Compose 1.1 https://t.co/a1NoaXFnmE#AndroidDev #Kotlin
Today, I would like to dive into another great feature from this new release. A feature that will significantly help us to write our Koin modules: module includes 🔍
Koin Modules
The Koin module is essential for the following points as a Koin module is:
- the logical unit of organization, to help gather definitions
- an entry point for the Koin DSL, to allow us to declare definitions inside this unit of organization
As a reminder, you can declare a module with the module function like this:
val myModule = module {
}
What does this code? This block will render all the indexes and prepare the underlying factories for your definitions.
Focus on Simple Usage First
While developing the Koin framework, the idea was to avoid going in all directions and especially trying to cover all kinds of Module topology from other existing DI frameworks. The idea was: "let's just develop what we really need".
This allows to gather a group of modules per feature/layer/testable unit, with a simple list:
val uiModule = module { }
val dataModule = module { }
val appModule = listOf(uiModule, dataModule)
startKoin {
modules(appModule)
}
You can even use the plus operator to form a list of modules directly:
val uiModule = module { }
val dataModule = module { }
val appModule = uiModule + dataModule
Modules can be combined in any configuration that suits you. There is no constraint in writing your configuration. The tool follows your software design and not the inverse.
In a nutshell: Koin loads your list of modules: register all indexes and factories. And if you need, you can even verify if a module configuration is broken, with a simple unit test (module verification).
Reuse Complexity
While you begin to have dozens of modules, it starts to be more tricky to organize yourself with common modules. Finally, this implies specifying needed combination each time you need it or diving into fined grained configurations:
// Data layer
val dataModule = module { }
// UI Layers
val uiFeatureModule1 = module { }
val uiFeatureModule2 = module { }
// defining each feature
val featureModule1 = uiFeatureModule1 + dataModule
val featureModule2 = uiFeatureModule2 + dataModule
// listing all features
val appModule = uiFeatureModule1 + uiFeatureModule2
This kind of complex configuration is not ideal to maintain over time. Even more, if you try to maintain a different kind of module list. Let's see below how we have improved this.
New Modules Graph
Improvement of Koin 3.2 resides in providing the new includes function in the Module DSL. This way you can point out what modules are needed for your current module content:
val dataModule = module { }
val featureModule = module {
// included other modules
includes(dataModule)
}
Now that we have a dependency to other modules, Koin will be able to "draw" the graph of all needed modules, and will optimize the global loading:
// Data Components
val dataModule = module { }
// Features
val uiFeatureModule1 = module {
includes(dataModule)
}
val uiFeatureModule2 = module {
includes(dataModule)
}
// Gathering all features
val appModule = module {
includes(uiFeatureModule1, uiFeatureModule2)
}
Finally, loading the appModule will result in loading the following modules: uiFeatureModule1, uiFeatureModule2 & dataModule.
starKoin {
// will load uiFeatureModule1, uiFeatureModule2 & dataModule
modules(appModule)
}
Loading optimization will also avoid any accidental override, that could occur with the previous organization.
You can even use each module in a separate manner, without worrying to include needed dependency by hand. Again, you can verify if your graph is not broken on any module or included modules.
We believe that this new feature will give you a new breath for your Koin configuration. Hope you'll enjoy it.
Do not hesitate to share your thoughts and experience with Koin 3.2! - @insertkoin_io
Cheers 👍