
This was one of the better books I’ve read recently for actually changing how I think about programming. It combines domain-driven design, test-first development, and functional programming into one coherent story, which is pretty rare, since most books only tackle one of those at a time. Unlike some of my other recent reads, the Kotlin itself was well-structured and idiomatic throughout, not just functional-flavored Java.
The book builds a real app, a to-do list called Zettai, outside-in with TDD, starting from acceptance tests and working down to the domain core. It uses http4k, which the author picked specifically for its “everything is a function” philosophy (an HttpHandler is just (Request) -> Response), and Exposed for persistence. The book’s repo only has the start and end states for each step (step1 through step7, spread loosely across 13 chapters) rather than the intermediate changes, so I had to lean on the book’s prose to follow why the code evolved the way it did and not just what it ended up as.
The arc goes from actor-based domain-driven testing, to receiver-typed lambdas and extension functions, to higher-order functions and purity, to a hub-and-spokes (ports and adapters) architecture, and then into the theory: monoids (with a door state machine example), functors, monads, and applicatives, then event sourcing, profunctors, and finally a logging and JSON capstone that applies everything. The theory was mostly motivated with real code before the abstraction got a name, which I appreciated. Functors come out of Holder, List, and Outcome, and then ProjectionQuery deliberately breaks the container idea to push you into thinking “computation, not container.” Monads come from a concrete TxReader<TxReader<T>> nesting problem instead of being introduced abstractly, and applicatives show up through error-accumulating validation with `!` and `*` operators, contrasted against the way monads short-circuit. The exceptions were the door monoid section and parts of chapter 7, where the vocabulary showed up before the payoff did, which was disorienting in the moment even though the payoff eventually arrived by the end of the chapter.
The Kotlin was the kind you’d want to see in a strong codebase, with extension functions, receiver types, sealed classes, and generics all used the way they’re meant to be used and not just as vehicles for FP theory. The actor-based test framework, Pesticide, was a neat pattern too, you write a test once and run it against the domain, a local HTTP server, or a deployed instance, even if I’m not sure I’d adopt the library itself over something mainstream like kotest.
The final third, especially the logging and JSON chapters, had a noticeably higher error rate than the rest of the book. Functions got referenced before they were shown (storeEvents), parameter counts didn’t match, field names had typos, and the JSON chapter builds a hand-rolled JSON library that even the author was “wary” of introducing, and it’s admittedly incomplete, since its own reflection-based codegen “seldom works right without manual intervention.” A thin adapter wrapping kotlinx.serialization in an Outcome probably would have served the book’s own goals better than building JSON parsing from scratch. There’s also an optional 50-page category theory appendix, which was a mixed bag. Functors, monads, and comonads were mostly confirmation of things I’d already earned through the main text, and Kleisli categories turned out to be bind with different notation once I decoded them, but profunctors and the Yoneda lemma were presented abstractly enough that I had to reconstruct them from the code examples myself before they landed.
Looking back at it now, after a stretch in Haskell, I remember a lot more about the DDD and TDD from this book than I do about the details of Kotlin. It was really into TDD, the whole app gets built outside-in from acceptance tests, and I miss that now that I’m working through 1000 pages of Django 5 By Example without a single test in them. Anyway, it’s a dense book, but it was worth the length, and it changed how I think about combining DDD, testing, and FP instead of treating them as separate concerns. I’d recommend it to someone with some Kotlin under their belt and the patience for some rough editing toward the end.
Full book notes.