Skip to content
AyoKoding

Overview

Want to apply DDD with modern OOP languages? This tutorial teaches Domain-Driven Design tactical and strategic patterns through 75 heavily annotated examples in Java 21+, Kotlin, C#, and TypeScript.

What This Tutorial Is

This tutorial presents 75 examples showing DDD concepts implemented in Java 21+, Kotlin, C#, and TypeScript with heavily annotated code. Each example is self-contained, runnable, and annotated with // => markers that show values, types, states, and effects at each step. Java is the canonical language carrying the deepest annotations; Kotlin, C#, and TypeScript variants appear where language-idiomatic differences matter to the DDD pattern.

Each example demonstrates a focused DDD concept. Examples build progressively: tactical building blocks appear first, integration and layering patterns follow, and strategic patterns close the tutorial. Every example follows a consistent five-part structure (see below).

Prerequisites

  • Comfortable with at least one of Java, Kotlin, C#, or TypeScript at an intermediate level (whichever language you ship with)
  • Familiar with OOP fundamentals: classes, interfaces, inheritance, and composition
  • Has read the paradigm-agnostic DDD overview at DDD Overview

How to Read This Tutorial

This tutorial is code-first. Each example leads with working, self-contained code annotated with // => markers that show values, types, states, and effects at each step.

Read one language deeply if you want to build fluency in that language's DDD idioms. Scan all four languages on each example if you want cross-language insight into how the same DDD concept maps onto different type systems and idioms. Language contrasts are noted in examples where the difference matters to the DDD pattern.

The running domain across all examples is the procurement-platform-be — the backend of a Procure-to-Pay (P2P) platform through which employees submit purchase requisitions, managers approve them, purchase orders are issued to suppliers, goods are received, invoices are matched against deliveries, and payments are disbursed. Using a single domain lets you see how individual DDD building blocks fit together into a coherent system.

What This Tutorial Covers

Tactical patterns:

  • Value Objects — identity-less, equality-by-value domain concepts
  • Entities — objects with identity that persist through state changes
  • Aggregates — consistency boundaries enforced through a root entity
  • Repositories — collection-oriented persistence abstractions
  • Domain Services — stateless logic that does not belong on any entity
  • Domain Events — records of meaningful occurrences in the domain
  • Application Services — orchestration layer between domain and infrastructure

Strategic patterns:

  • Bounded Contexts — explicit model boundaries within a large domain
  • Context Maps — relationships between bounded contexts (partnership, customer/supplier, conformist)
  • Anti-Corruption Layer (ACL) — translation boundary protecting a model from external concepts

What This Tutorial Does NOT Cover

  • Language tutorials: Java, Kotlin, C#, and TypeScript each have their own by-example tutorials for language fundamentals
  • Deep DDD theory: read the DDD Overview for conceptual grounding; Evans's Domain-Driven Design (Addison-Wesley, 2003) for comprehensive theory
  • Event sourcing internals beyond the introductory example in the Advanced section
  • CQRS infrastructure (projections, read-model persistence) beyond the pattern itself

Sibling Tutorial: Functional Programming Approach

If you prefer a functional programming treatment of DDD, see DDD By Example in FP. That tutorial covers the same strategic and tactical patterns through F# discriminated unions, Railway-Oriented Programming, and workflow pipelines, using the same shared procurement-platform-be P2P domain.

Where Go Fits (Partial)

Go has interface satisfaction without inheritance — domain types as structs with methods, repositories as small interfaces satisfied implicitly by concrete adapters. Rob Pike (Google SPLASH 2012 keynote: "Go at Google: Language Design in the Service of Software Engineering") explicitly rejected inheritance hierarchies in favour of composition + interfaces. The most credible Go DDD treatment is Matthew Boyle's Domain-Driven Design with Golang (Packt, 2022); Three Dots Labs maintains the most-cited open-source Go DDD reference.

That makes Go a partial fit for this OOP-DDD track:

  • Translates one-to-one to Go: value objects as struct types with constructors, repositories as small interfaces (one to three methods), application services as functions taking repository interfaces, domain events as structs, bounded contexts as Go packages with clear public surfaces.
  • Does NOT translate to Go: aggregate roots enforcing invariants via inheritance, hierarchical entity types via extends, Specification pattern via abstract class composition, GoF-flavoured factory class hierarchies. Go DDD usually models aggregates as plain structs with explicit transition functions (closer to FP-style transitions than to encapsulated mutable OOP aggregates).
  • Honest path: read this track for tactical patterns that translate (value objects, repository interfaces, application services, domain events), then see in-procedural-by-example for the Go-canonical formulation where composition + structural typing + explicit transition functions are the design force.

Structure of Each Example

Every example follows a consistent five-part format:

  1. Brief Explanation: What DDD concept the example demonstrates (2–3 sentences).
  2. Optional Diagram: A Mermaid diagram when concept relationships are complex enough to warrant visual representation. Skipped for straightforward code definitions.
  3. Code Block(s): Java 21+ implementations (canonical) with // => annotations explaining values, states, and effects. Kotlin, C#, and TypeScript variants appear where language-idiomatic differences matter to the DDD pattern.
  4. Key Takeaway: The core DDD principle to retain (1–2 sentences).
  5. Why It Matters: Real-world business impact and production system context (50–100 words).

Tutorial Structure

  • Beginner (Examples 1–25) — Tactical building blocks: Value Objects, Entities, Aggregates, Repositories, Domain Services, Application Services, and Domain Events using the purchasing bounded context.
  • Intermediate (Examples 26–51) — Integration and layering patterns: Specifications, Factories, CQRS, hexagonal architecture, domain exception hierarchies, and Bounded Context packaging, adding the supplier context.
  • Advanced (Examples 56–79) — Strategic patterns and advanced tactical: Context Maps, Anti-Corruption Layers, cross-context ACL, repositories with infra adapters, event sourcing, sagas, temporal modelling, and common anti-patterns, adding the receiving and invoicing contexts. The murabaha-finance context is optional and introduced only where Sharia-compliant financing patterns add pedagogical value.

Examples by Level

Beginner (Examples 1–25)

Intermediate (Examples 26–51)

Advanced (Examples 56–79)

Last updated May 8, 2026

Command Palette

Search for a command to run...