Assisted Injection Proposal
Nobody has claimed this yet.
- Dominant language
- Kotlin
- Stars
- 537
- Forks
- 46
- PR merge metrics
- No merged PRs in 30d
Description
This proposal is to have some sort of AssistedInjection support for Motif.
Motif already has an API for factory implementation to create child Scope with given dynamic variables, but it is restricted only to Scope creation. By extending this functionality to any other type, we can already achieve assisted instance creation via Motif.
Problem
Currently, it is not supported to provide an instance with dynamic variables to child scope. In order to provide that, you can create a separate instance that would be responsible for generating the instance you need and provide that object as static instance.
Example; Assuming a callback needs to hold on to an instance so that can notify back with given instance, that means a new instance is required per given item.
class SampleImplementation(
private val dynamicData: DynamicData,
private val logger: Logger
) : SampleInterface { }
@motif.Scope
interface SampleScope {
fun createChildScope(callback: SampleInterface): ChildScope
}
class ConsumerExample(
private val sampleScope: SampleScope,
private val logger: Logger
) {
fun usage(dynamicData: DynamicData) {
val childScope = sampleScope.createChildScope(
new SampleImplementation(dynamicData, logger)
)
}
}
This makes ConsumerExample to know about how to create an instance of SampleInterface, which violates inversion of control and also creates a direct dependency to Logger even though it is not needed besides creating the instance for the callback.
Workaround
In order to work around this, we can create a factory implementation that can create an instance of the callback lazily and provide this factory in DI so that ConsumerExample can have the factory and generate the instance it needs.
interface SampleInterfaceFactory {
fun create(dynamicData: DynamicData): SampleInterface
}
@motif.Scope
interface SampleScope {
@motif.Objects
open class Object {
fun sampleInterfaceFactory(logger: Logger): SampleInterfaceFactory {
return dynamicData -> SampleImplementation(dynamicData, logger)
}
}
}
class ConsumerExample(
private val sampleScope: SampleScope,
private val sampleInterfaceFactory: SampleInterfaceFactory
) {
fun usage(dynamicData: DynamicData) {
val childScope = sampleScope.createChildScope(
sampleInterfaceFactory.create(dynamicData)
)
}
}
Even though this is doable, it still introduces a lot of boilerplate code.
Proposed Solution
Considering we already have enough information in DI tree, we can benefit from Assisted Injection and pass only the dynamic dependencies and have the rest provided by Motif.
@motif.Scope
interface SampleScope {
fun createChildScope(callback: SampleInterface): ChildScope
fun createSampleImplementation(dynamicData: DynamicData): SampleImplementation
}
class ConsumerExample(private val sampleScope: SampleScope) {
fun usage(dynamicData: DynamicData) {
val childScope = sampleScope.createChildScope(
sampleScope.createSampleImplementation(dynamicData)
)
}
}
Motif should be able to create an instance of SampleImplementation with give DynamicData given that it already has a Logger instance in the DI tree. So the implementation would need to diff given dynamic dependencies with constructor dependencies and satisfy remaining dependencies from DI.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading Motif's existing Scope API, especially createChildScope and its factory implementation support, then trace how constructor dependencies are resolved. The proposal is complete when a scope can create an instance from supplied dynamic dependencies while resolving remaining dependencies from the DI tree, with coverage for the assisted-injection behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- kotlin
- Domain
- mobile-dev
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100