Manageable dependency injection for Kotlin

Welcome to OOverkommelig

Dependency injection that is easy to read and write. Written in and for Kotlin.

Current status: beta. API is stable. Documentation is needed.

To use OOverkommelig in your projects, add the following to your Gradle scripts:

repositories {
    maven {
        url 'https://dl.bintray.com/squins/Squins'

dependencies {
    // For JavaScript (which does not support all features):
    implementation 'org.ooverkommelig:ooverkommelig-js:1beta1'
    // For the JVM:
    implementation 'org.ooverkommelig:ooverkommelig-jvm8:1beta1'

And if you use Kotlin for your Gradle scripts:

repositories {
    maven {
        url = uri("https://dl.bintray.com/squins/Squins")

dependencies {
    // For JavaScript (which does not support all features):
    // For the JVM:

Get notified of new releases:

Get automatic notifications about new "ooverkommelig" versions


Here is some (very simplistic) example code to give you a taste. For more complex object graphs see the examples:

// An object graph definition is a self-contained unit consisting of multiple
// object definitions, i.e. it can be instantiated.
// An single interface parameter with one or more functions provides external
// objects (or object definitions), allowing configuration of the object
// graph.
class ApplicationOgd(provided: Provided) : ObjectGraphDefinition(provided) {
    // Explicit declaration of the dependencies of an object graph, so clients
    // of the graph quickly know what they need to provide to be able to use
    // the graph.
    // This inherits from all "Provided" interfaces of all sub graph
    // definitions that make up this object graph definitions, so clients are
    // aware of all dependencies of the object graph.
    // This may look like tightly coupling the object graph client to the sub
    // graph definitions, but the object graph can ensure the API remains
    // backwards compatible when the dependencies of the sub graph definitions
    // change by adding (unused) functions to its "Provided" interface.
    interface Provided : ApplicationSgd.Provided {

    // This is "public", which is not a requirement but reduces the amount of
    // boilerplate. In this case all dependencies have to be provided by the
    // client of "ApplicationOgd". But it is also possible that
    // "ApplicationOgd" provides dependencies by using multiple sub graph
    // definitions, and using an object definition from one for the dependency
    // of another.
    val appSgd = add(ApplicationSgd(provided))

    // By creating an instance of this class and requesting one or more
    // objects, the defined object will actually be created. Note that
    // OOverkommelig also allows for specifying eagerly created objects that
    // will be created once a graph instance is created.
    // The graph instance implements "Closeable", which enables clean-up of
    // objects in the graph. When you only need a graph for a single operation
    // you can use the following code. This ensures that all objects are
    // disposed of once the operation finished:
    //     ApplicationOgd(object : ApplicationOgd.Provided, ProvidedAdministration { ... })
    //             .Graph().use { graph ->
    //                  graph.someService().doYourThing()
    //             }
    // In cases where you need the graph for multiple operations, you create
    // and store it. When it is no longer needed, you dispose of it.
    inner class Graph : DefinitionObjectGraph() {
        fun someService() = req(appSgd.someService)

// A sub graph definition is not self-contained, i.e. it is intended to be
// used in one or more object graphs. The object graph must provide the
// dependencies for the sub graphs it uses, either by using object definitions
// of other sub graphs or by requiring the object graph client to provide
// them.
// Sub graph definitions are the reusable pieces of objects and wiring that
// can be used in multiple contexts. For example:
// - The object definitions that are the same for both Android and iOS apps.
// - Infrastructure objects that are the same for all applications that you
//   build.
class ApplicationSgd(provided: Provided) : SubGraphDefinition(provided) {
    interface Provided : ProvidedBase {
        // Functions instead of values are used to reduce the boilerplate in
        // more complex situations.
        // "Definition" can occur quite a number of times in sub graph
        // definitions. Its type alias "D" can be used to reduce the amount of
        // boilerplate.
        fun logDirectory(): Definition<File>

    // This is a very simple object definition as it only specifies the
    // creation lambda. OOverkommelig also support wiring (allowing object
    // cycles to be created), initialization and disposal.
    // The creation lambda of this object will be invoked only once, and its
    // result will be returned to any other object needing the log file.
    // OOverkommelig supports a range of object definitions: constant, once,
    // always, parameterized once, parameterized always, aspect once (JVM
    // only) and aspect always (JVM only).
    // Again: The values are public to reduce the amount of boilerplate, but
    // this is not a requirement.
    // "req(...)" indicates that the dependency is required. OOverkommelig
    // also supports optional dependencies using "opt(...)".
    // The object definitions allow enormous flexibility: You can use all
    // language constructs and all APIs to determine what should be
    // constructed, how it should be configured, etc. You can do much more
    // than shown in this simplistic example.
    val logFile by Once { File(req(provided.logDirectory()), "log.txt") }

    val log by Once { Log(req(logFile)) }

    val someService by Once { SomeService(req(log)) }

More examples can be found in the repository.


Some of the big advantages of OOverkommelig compared to other dependency injection containers are:

  • The ability to quickly navigate to the definition of a dependency.

  • The ability to quickly navigate from a dependency to its usages.

  • Compile-time check for graph completeness, i.e. compile errors if you reference a dependency that is not defined.

  • Compile-time check of type correctness, i.e. you cannot use an object definition for another type for a dependency.

  • Compile-time check of required dependencies, i.e. you cannot use an optional object definition for a required dependency.

  • Compile-time check of unused dependencies, i.e. your IDE will mark object definitions that are not used by other object definitions.

Download .zip Download .tar.gz
Fork me on GitHub