What are the main advantages of Kodein over Koin i...
# kodein
e
What are the main advantages of Kodein over Koin in context of multiplatform project? What made you choose it over Koin?
r
Composition. In Koin you have a unique and global container, and you need to start the Koin container in your app. With Kodein, you can have mutliple containers if needed, and you don’t need to start them, just consume / combine them.
👍 1
e
@romainbsl what do you mean by “start container”?
e
Does it mean that Koin checks the graph during this “start” and that Kodein doesn’t check the graph?
r
Neither. Both might crash if you lack a dependency at runtime. We are working on a way to check graph with one line of unit test, but we don’t have much bandwidth at the moment to work on it.
e
I have been using Toothpick in my projects for years now, after I moved from Dagger2. And it has a pretty nice tradeoff between performance and stability doing this graph check on startup. What are technical restrictions of doing that in Kodein?
what does that “start” thing in Koin actually do? why it is there and is not in the Kodein?
and do you know how Koin users manage multi module structured apps if they have this Composition restrictions?
r
Koin defines a “god” global context, I think start build that gloabl context. (I am no expert here). Koin users use modules to be merge in the global context at startup. Kodein does not need “start” because it does not use global context, thus a Kodein DI container can be simply consumed. We have no technical restrictions, but performance might be impacted on heavy graphs. That is why we prefer to wait our new API to check consistency with unit test.
e
I found that since v3.2 Koin also supports some kind of composition:
Copy code
A new function includes() is available in the Module class, which lets you compose a module by including other modules in an organized and structured way.
Is it the same as in Kodein or still different?
Copy code
// `:feature` module
val childModule1 = module {
    /* Other definitions here. */
}
val childModule2 = module {
    /* Other definitions here. */
}
val parentModule = module {
    includes(childModule1, childModule2)
}
r
By Composition I meant having multiple DI containers (with ones you may not be aware of in submodules for instance), Koin as a unique one that needs to be started.
e
When can having several containers be useful or critical?
r
accessing part of a graph in a unique part of an app, like accessing Paid feature through its own sub-graph for instance, overriding Free instances.
or declaring a container in a library / module without the need for library consumer to be enforced to use Kodein if they are using something else in their app
e
So the code using Kodein has standalone infrastructure in that module but can be also extended/joined in other parent modules?
r
yup
e
that makes a lot of sense! thanks for explanation! And do I understand correctly that that difference comes from the core architecture approach used in the libs? Now I don’t understand why Koin is so popular if it has such restrictions..
r
IMHO, probably better marketing, API may have been less verbose at some point, and now it is organic, even if Kodein is KMP ready since 2017/18 we loose traction in the benefit of Koin because of Android devs that use Koin for some time.
maybe Koin has a better intergration with Android also, but we prefer to be more focused on KMP TBH
e
What I am trying to understand are there any technical consequences of this Composition approach which don’t allow to create the API as easy to use and as clean as in Koin? DSL could be different, right?
Although I don’t know if Koin actually has much better API in some aspects, because I didn’t use it in a real project neighter.
r
I don’t really understand your question, actually. • DSL are different but not that far. • Koin has Composition over modules but Kodein go further with container. • Koin enforce the use of global context and starting it (even for library consumer!), Kodein doesn’t
e
I meant that if Koin is more popular because it has DSL that is easier to use/understand at some points, that it should be possible to make the same in Kodein and take the best from both. If it is not the case, then even better! 😃
r
Ah! We’ve simplified our DSL, but some edge case needs more verbose DSL. However simple cases are pretty straightforward, and we hope, as simple as with Koin 🙂
e
Yeah, I will try that out right now. Thank you! 🙂
i
Kodein has some edge case features I end up using like
multiton
and
multi-binding
you can do this is koin too but it isn't as nice. As discussed being able to just use it sans lifecycle makes other things easier too imo like setting up some test cases.
e
@ian.shaun.thomas Thank you for the response! Could you please tell more about the second part?
i
Copy code
val di = DI {
   bind<Thing> { singleton { MyThing() } }
}
that is a valid graph which you can use immediately
Copy code
@Test
fun myTest() {
   val thing = di.direct.instance()
   ...
}
e
Yes, looks nice
@romainbsl you said that Kodein doesn’t make graph check because of possible performance issues. Why not add optional check? For example one would turn it on only for QA/Dev builds and turn off for production. In this case it will not impact real users, but will fail in testing in almost all cases.
r
Yes that could be. But, in fact the work we have done so far on the KSP plugin that allows to check grpah in unit test could be used at runtime as well. So my guess is that we would leverage both with the KSP plugin
a
I can help for the Koin part. Koin can be also completely isolated (SDK, White label apps), and you can combine modules in the way you want. Ping me for more details on Koin 🙂
also can give insights on the testing API
r
Hey Arnaud 🙂 Thanks, TBH I don’t know all the technical details of Koin, as I am not a user ^^. So, the global context can be avoided in a SDK ? This the main criticism I had from clients that use Koin. For example, can we avoid iOS from starting the container as iOS devs usually do not care/use about DI directly from Kotlin.
a
So, the global context can be avoided in a SDK
yep, you can isolate completely for SDK purpose yes
582 Views