Skip to the content.

Domain-driven design using Kotlin

GitHub license Kotlin

This framework lets you start your coding from domain layer with pure Common Kotlin. Test-driven development is also supported via generated unit test stubs.

The Dokt plugin generates application layer, which follows Command and Query Responsibility Segregation (CQRS) and Event Sourcing (ES) patterns. It can’t generate infrastructure layer :) but you can code it to any platform.

Features

The “Hello, World!” tutorial:

  1. Apply Dokt plugin in the build.gradle.kts file:
plugins {
    id("app.dokt") version "0.2.0"
}
  1. Write domain logic in src/commonMain/kotlin/Hello.kt file:
import app.dokt.Root
import kotlinx.serialization.Serializable

/** Events that Greeter emits  */
interface Events {
    fun greeted(greeting: String)
}

/** Greeter aggregate root. Identified by UUID (default). */
@Serializable // For unit testing
class Greeter : Root<Events>(), Events {
    val greetings = mutableListOf<String>()

    /** Greet command handler */
    fun greet(who: String) {
        if (who.isBlank()) throw IllegalArgumentException("Missing 'who'!")
        emit.greeted("Hello, $who!")
    }

    /** Greeted event handler */
    override fun greeted(greeting: String) {
        greetings.add(greeting)
    }
}
  1. Run generateCode task.
  2. Write unit test in src/commonTest/kotlin/GreeterTest.kt file:
/** Greeter unit tests */
class GreeterTest : GreeterSpec({ // GreeterSpec is generated in previous step.
    greet { // Command handler is a generated test context
        test("World") { // "World" test case
            greeter // Greeter is arranged with a random UUID.
                .act { greet("World") } // The command act
                .emits(Greeted("Hello, World!")) // Asserts the emitted DTO.
        }
    }
})
  1. Run allTests and you should pass your test.

Check more examples.

Thanks

Following frameworks have inspired this project a lot: