Seeking perspective: Hi! I'm coming from a world o...
# kodein
a
Seeking perspective: Hi! I'm coming from a world of manually-hacked-up DI in Ruby, Go and Java, and I'm a noob for both Kodein and Kotlin. I am building a tool/service (commandline, eventually maybe Android) and previously I would build a
AppConfig
instance — containing references to objects that implement interfaces like
DB: IDatabase
, etc — and pass that
appConfig
into the constructors that implemented [various interfaces] for my service. All very typical factory-pattern stuff - the (for example)
appConfig.DB.query()
methods would then be used by service methods (via a "retrieval"-type approach) and the appConfig reference itself would be blindly passed on to any child-factories which need to be created. But I am learning Kodein and I am messing around with this blog post which suggests making the companion object for
Foo : IFoo
into a
FooFactory
by declaring a
companion object { fun create() : IFoo = ... }
method. With that context, QUESTION: What's the proper Kotlin & Kodein approach to solving the problem of passing an instantiated
appConfig
reference into a
FooFactory
that is the companion object of
Foo
? In fact, would this be stupid to do? I am trying to avoid endless invocations of
Foo(appConfig: DI)
by passing
appConfig
into the
FooFactory
when I create the
FooFactory
, I could maybe declare
Foo.appConfig
as a
lateinit
var in the
Foo
factory/companion-object, and then set it via a static method call, but I feel sure that there must be a better, more typical way in Kodein - possibly modules?
I suppose the short version of this question is: "what's the canonical way to pass a Kodein-DI instance around a complex factory-pattern application, so as to minimise effort?"
Some useful hints in this blog post which focuses on Android, which seems to be saying that Foo should implement KodeinAware which will give it a
kodein
reference/field ... but if I want to push this into a static factory
object
, then either I have to give up on the companion-object hack, or else I need to pass the
kodein
reference into the
object
as a
lateinit
var, as described above?
Am thinking the cleanest thing is to give up on the companion-object hack, build proper
FooFactory
classes which implement
KodeinAware
, and have them generate
Foo
instances which know about / inherit the
kodein
instance as a private constructor argument and/or implement
KodeinAware
.
(*) It seems that
KodeinAware
is now
DIAware
?
s
Hi @Alec Muffett. It seems you have arrived at the conclusion by yourself: don't mix DI & static objects. What we would recommend is to have the factory be bound in your DI container. Something like
bind<MyTypeFactory>() with singleton { MyTypeFactoryImpl(di) }
.
Note that making
MyTypeFactoryImpl
DIAware
is completely optional. The
DIAware
only exists to make DI retrieval easier.
a
Hi @salomonbrys - thanks for the confirm. One last question: I think I am okay to put the factories into the DI container, but I am a little worried about recursive "factory-cited-in-DI-object-requires-different-factory-also-cited-in-DI-object-in-order-to-work"... kinds of dependency. Are there any pitfalls that I should take care to avoid?
s
Nope. That's the point of DI ! Initialization order is taken care for you... As long as there are no dependency loops (ie A depends on B, which depends on C, which depends on A). In such cases, Kodein-DI will throw a meaningful exception.
❤️ 1
a
I'll try to avoid that. Many thanks!