koin-annotations
koin-annotations copied to clipboard
Automatic scan for Modules in dependencies
I'm migrating from Hilt and it has one great feature that is missing in Koin.
Inside the library, you can create a module that will be part of the default singleton component.
@Module
@InstallIn(SingletonComponent.class)
public final class MyLibraryModule {
When you add that library to the project, that library will automatically and without any setup provide implementations for all objects defined in that module.
In Koin, you need to add a module to the Koin setup closure manually. Would be great to have as part of the Koin Annotation project the possibility to do something similar, to scan for all modules in all libraries used in the project and somehow marked as public (shared). Libraries can still have their own internal modules.
To explain motivation for that.
We have many libraries in the company and setting them up is quite complex and tedious work.
I would like to make it plug and play. For example, one library will provide OkHttpClient, and all other libraries can just use it by injection, without necessary to call something like init(okHttpClient) for every library. Or when some library needs configuration, it can just expose the interface and use the injection, and the app using that library will be responsible for providing the implementation. If you do not provide it, it will crash during compile time, and you will immediately know that you are missing something. Or tracking, one library can provide just a general interface for tracking and all other libraries will use just this interface. In the app, I will just add a dependency with tracking implementation, like Firebase, and done, it will immediately start tracking. Or I can simply decide that I will do my own tracking directly in the app, so I will just provide my own implementation of that tracking interface in the app.
Hilt/Dagger automatically generates a special package in the library with all the information about what provides and needs. And during the compilation, KSP checks everything in that one package on the classpath, so it will very fastly get information from all libraries.
But there will be an issue that Koin does not have @Inject annotation so it doesn't know during the compile name all of the requested dependencies that need to be fulfilled, right?
Hello, interesting feedback. In your case, you don't use directly MyLibraryModule but it's installed in the singleton components, right?
Do you mean in hilt? Yes. It is in the example in the first post.
In Koin you need to add a module to the Koin setup closure manually. Manual part is still required as limitation of Koin for now
This is something that would be amazing, as currently you need to collect every module yourself. If there's modules you don't transitively depend on, exposing them is also a bit of a pain (ex: :app module depends on implementation(:feature:a), which depends on implementation(:core:thing). Collecting the CoreThingModule().module requires an explicit dependency on it, or an api() dependency, neither is very pleasant.
To maintain compatibility with KSP & source generation, maybe export/generate an additional koin-metadata.properties that lists the top level (or all) generated modules, so that consumers can merge it and consume it themselves automatically ?
I'm testing out koin annotations in a multi module Gradle project. I've been using the OG style of declaring modules and having to depend on them in the module that has startkoin
Imo without being able to pick these up automatically like it's done in defaultmodule, the only benefit I get from annotations is not having to define every interface- implementation binding
Is it a blocker for you currently to be able to scan for modules?
By using includes from the main module, you pull all your dependencies.
@Module(includes = [...]) // can be from other Gradle module
class MyAppModule
But I see here a need to "push" a module to a given default "space".
Is it a blocker? No, writing includes manually is a bit of a pain, but is not something that changes often.
Is it a problem in a modular architecture, where some modules might be only in the compile class path, but not there once the build is done ? A bit, it basically makes using includes impossible when it comes to putting together features, and module creation is a bunch of runCatching calls in case feature :a is not present.
Does it make it not worth the effort for me to migrate away from Dagger ? Absolutely. At the moment, it doesn't feel worth the benefits (despite how much I hate Dagger's error messages, and how overriding definitions is much more pleasant in Koin)
I also remember that there were some problems with this setup and the Koin IDE plugin not listing injects, but that might be because our project setup is slightly unusual (app consumes feature modules that are published to maven, instead of direct references)
It's not a blocker, just a pain to deal with. Though it doesn't happen very often.
Let's check for some investigation in 2.2
Does something like @ModuleScan would help scan for given package (or even all)?
@ModuleScan looks promising. But I'm not sure how it will work.
But most important is performance, how fast Koin will be able to search all libraries on the classpath for their modules. In Dagger, it is very fast, because they check that one package name, which all libraries built by Dagger have.
Why do we need an additional annotation like @ModuleScan? I would expect every @Module and even the defaultModule to aggregate transitive DI-definitions automatically. Is this not feasible?
I finally went with a proposal of @Configuration to tag a module, to be part of configuration "spaces" (i.e. scopes in some other frameworks). It's close to what we can find also in Spring.
We also need a bootstrap annotation to generate a "startKoin entry point" with modules. The @KoinApplication annotation defines an application entry point and scans for annotations.
See documentation: https://insert-koin.io/docs/reference/koin-annotations/modules#application-bootstrap-with-koinapplication https://insert-koin.io/docs/reference/koin-annotations/modules#configuration-management-with-configuration
I'm deploying new 2.2 Beta to ask feedback, if some of you are interested 👍
I close this issue. The document is linked in the previous message.