Lilly
02/19/2023, 10:01 PMmulti-module project
and utilizing a DI library
. In particular I think about KOIN as DI library. You have to instruct your application somehow to load all koin modules (not gradle modules) to build the dependency graph. One option to achieve this, is to create a separat gradle module, lets call it di which is aware of all other gradle modules, so the app module can simply depend on it and can load the koin modules from there. Further, I came up with idea to put all koin modules in di gradle module rather than let every gradle module provide its koin module. The advantage is that all other gradle modules are independent of a DI library but the disadvantage is that almost every class of the other gradle modules has to be public so that di module is aware of the references. My question is: which approach would you choose and why?Pedro Alberto
02/20/2023, 8:37 AMLilly
02/20/2023, 10:13 AMPedro Alberto
02/20/2023, 10:20 AMval myAppModule = module {
single<MYPublicInterface> {
MyPrivateImpl()
}
}
then in the gradle module I only depend on the one that has the Interface
the koin module is built internally
the feature module has always a shared moduleLilly
02/20/2023, 10:33 AMPedro Alberto
02/20/2023, 10:33 AMLilly
02/20/2023, 10:34 AMPedro Alberto
02/20/2023, 10:34 AMLilly
02/20/2023, 10:35 AMPedro Alberto
02/20/2023, 10:35 AMLilly
02/20/2023, 10:39 AMPedro Alberto
02/20/2023, 10:45 AMarnaud.giuliani
02/20/2023, 1:14 PMLilly
02/20/2023, 1:23 PMinternal class MyClass {}
val myKoinModule {
singleOf(::MyClass)
}
app gradle module (just for completeness)
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
startKoin {
androidLogger()
androidContext(this@DcInternApplication)
modules(appModule, myKoinModule)
}
}
Dependency direction: app -> featurearnaud.giuliani
02/20/2023, 2:33 PMLilly
02/20/2023, 2:54 PMarnaud.giuliani
02/21/2023, 4:14 PMLilly
02/21/2023, 5:21 PMclass Configuratior(private val protocol: Protocol)
Protocol
is a public interface in domain.
proto:
proto contains implementation of Protocol
interface internal class ProtocolImpl() : Protocol
proto also contains:
val myKoinModule {
singleOf(::ProtocolImpl) bind Protocol::class
}
myKoinModule is loaded on startKoin()
So when Configurator
object is created, ProtocolImpl
is created too but how can ProtocolImpl
be created when visibility of it is internal
? It is neither visible nor accesible to the outer world but it can still be accessed via Koin somehow which should be impossible under normal circumstances. Even if the creation is done in proto gradle module, how is the object accessed? There must be some secret magic going on. Please enlighten mes3rius
02/22/2023, 7:33 PMProtocolImpl
is in the correct module, so it can be called.
If you only use singleOf(::ProtocolImpl)
(without bind) then that would compile fine and you can use it inside this module. But when you try to get this dependency in a different module, it won't work because you aren't allowed to write ProtocolImpl
in that other module.
You could replace Koin completely with this code and it would work the same:
fun getA(): Protocol {
return ProtocolImpl(...)
}
fun getB(): ProtocolImpl {
return ProtocolImpl(...)
}
getA can be used anywhere because anyone who calls the function will only see a Protocol
. getB will not work anywhere outside the same module because anyone who calls it will see a ProtocolImpl
.Lilly
02/22/2023, 8:55 PMPedro Alberto
02/23/2023, 9:01 AM