ENGINEERING NOTE / 2026-08-18
Build a dependency-graph inventory before changing the container
A small inventory makes hidden constructors, qualifiers, scopes, and platform bindings easier to review.
A dependency-injection migration often starts with framework syntax. That is too late. First describe the graph without using the framework’s vocabulary. The inventory should show which objects exist, who owns them, and which runtime fact selects one implementation over another.
Start from entry points
List application entry points: the Android application, a worker, a navigation destination, a command-line process, and each test fixture. Trace the objects requested at each entry point. Stop the trace at explicit boundaries such as a database driver, HTTP transport, clock, file system, or platform service.
For every node, record:
- its public interface and concrete implementation;
- constructor dependencies;
- lifetime: process, session, screen, request, or transient;
- qualifier or runtime parameter;
- owning Gradle module; and
- replacement used in tests.
This reveals two common problems. The first is a dependency that exists only because a service locator can reach it. The second is a lifetime that is implied by container syntax but never stated as an application rule.
Review edges, not only nodes
A graph can contain the correct classes and still be wrong. A process-scoped object can capture a screen-scoped object. A shared module can refer to an Android implementation. Two definitions can use the same untyped string qualifier. Mark these edges as constraints in the inventory.
Koin’s current documentation describes module verification and compile-time validation as different ways to catch missing definitions and qualifier problems. Use the technique supported by the version you have, but keep a human-readable inventory as the architectural record. See Koin configuration verification.
Make the inventory executable in small parts
Do not attempt one test that creates the whole production application. Test coherent slices: account access, search, checkout, or synchronization. Supply explicit test values for runtime parameters. A slice failure then identifies a useful boundary instead of producing one large container startup error.
The finished inventory is not a diagram for a presentation. It is a review aid. Update it when ownership or lifetime changes, and use it to explain why a binding belongs in a module.