DDD Tactical Katas
Four deliberate, time-boxed exercises. Pick any one to start; cycle through all four over a week if you want full coverage. Each kata should take 45-90 minutes; re-run each one monthly with a new domain prompt.
Kata 1 -- Identify Subdomains from a Business Case
Prompt. You are presented with a business description (below) you have never seen before. Produce a strategic design in 60 minutes.
Business case. "MedReach is a telemedicine platform. Patients book virtual appointments with doctors, pay out-of-pocket or with insurance, join a video consultation, receive e-prescriptions, and get medication shipped via a partner pharmacy. MedReach also offers a subscription for chronic-care patients (monthly check-ins, medication auto-refill, labs scheduling)."
Deliverables.
- Subdomain inventory with classification (core / supporting / generic) and 1-sentence justifications citing at least two heuristics each.
- 5-8 candidate bounded contexts with business-capability and language sketches.
- Strategic bets: name the 1-2 contexts where this company most needs a strong engineering team. Defend.
- Two terms ("patient", "appointment", "prescription" …) whose meaning differs between contexts. Give definitions.
- 1-page strategic design memo that a non-technical exec could read.
Time-box. 60 minutes total: 15 min inventory, 15 min boundaries, 15 min disambiguation, 15 min memo.
Self-check. Did you cite specific heuristics (language, actor, rate-of-change, autonomy, subdomain, …) or just gut feeling? If all gut feeling, redo.
Kata 2 -- Draw a Context Map
Prompt. For the output of Kata 1 (MedReach), draw the complete context map in Mermaid. Each edge must have direction, relationship pattern, and a translation pattern (if any), and name what crosses.
Deliverables.
- Mermaid diagram with every context, every edge, and every external system.
- Separate boxes for generic / external vendors (
[[ Stripe ]],[[ Zoom ]],[[ Partner Pharmacy ]],[[ Lab Network ]],[[ Insurance EDI ]]). - 1-paragraph rationale for each edge's relationship pattern citing at least one heuristic.
- Reader's guide (1 page) pointing out: the 2-3 fragile edges, the edge most likely to demand an ACL, and any edge where you downgraded the pattern (e.g., from partnership to customer-supplier).
- "Year-3 future map" -- redraw after a hypothetical business change (MedReach adds an in-person clinic network). What context is added, split, or reclassified?
Time-box. 90 minutes.
Self-check. Did you label edges with business vocabulary (AppointmentScheduled, PrescriptionIssued) or with transport concepts (POST /appointments)? If transport, redo.
Kata 3 -- Design an Aggregate for E-commerce Checkout
Prompt. Given the requirements below, design the Checkout aggregate, implement the domain model, and write tests.
Requirements.
- A checkout contains line items (product_id, quantity, unit_price), a shipping address, a chosen payment method token, an optional promo code, a currency, and a computed total.
- Unit prices are captured at add-to-checkout time (not recomputed at submit).
- A promo code can be applied; it can be a percent-off or a fixed-amount discount. Only one active promo at a time. Total after promo must be ≥ 0.
- Changing the shipping address may change the tax; the checkout exposes a command
change_addressthat recomputes tax. submit()transitions the checkout to a terminalSUBMITTEDstatus and emitsCheckoutSubmitted. A submitted checkout is read-only; further commands raise.- Concurrency: optimistic versioning; concurrent modifications to the same checkout fail safely.
Deliverables.
- Aggregate sketch (root, child entities, VOs, references by ID, invariants explicitly listed with numbers 1, 2, 3, …).
- Code (Python, Kotlin, Go, or TypeScript) implementing:
- the value objects (
Money,Quantity,Address,PromoCode,LineItem…) - the aggregate root with commands
add_item,remove_item,apply_promo,remove_promo,change_address,submit - the domain events emitted
- the value objects (
- Unit tests -- at least one per invariant -- pure, no mocks, no DB.
- A 1-paragraph discussion of one boundary decision: e.g., "I kept
LineItemas a value object list, not an entity, because identity is not needed once the checkout is submitted." - A note on one cross-aggregate flow -- where you would emit an event instead of reaching into another aggregate (e.g., inventory reservation).
Time-box. 90 minutes.
Self-check. Does any invariant live outside the aggregate (in a handler, in a validator, in a service)? If yes, move it in and re-test.
Kata 4 -- Model a Domain Event Stream for Shipping
Prompt. Design the complete domain event stream for a shipment's life at Parcel Shipping Co., from booking to final resolution (delivered, returned, or lost). Produce both the internal domain events and the integration events published to other contexts.
Deliverables.
- Internal event catalog. List every domain event the
ShipmentandShipmentJourneyaggregates emit. For each, provide name, payload (Python dataclass or TypeScript type), and the invariant that must hold when it fires. - Integration event catalog. For each internal event that needs to leave the context, produce the corresponding integration event JSON schema with version tag (e.g.,
shipping.shipment.booked.v1). Justify any fields dropped or renamed. - Event flow diagram. A Mermaid sequence diagram showing the event flow across contexts for:
- happy path (book -> deliver -> invoice -> payment)
- exception path (delivery exception -> customer support)
- cancellation path (cancel before label, cancel after label -- one allowed, one not)
- Translation code. Implement the mapper from one internal event to its integration event. Show at least two cases where the integration event drops fields or renames.
- Outbox sketch. SQL for the outbox table, and a 1-paragraph description of the relay's failure modes.
- Idempotency note. For one consumer (e.g., Billing), show how the event is consumed idempotently (dedupe by
event_idagainst aprocessed_eventstable).
Time-box. 90 minutes.
Self-check. Can a brand-new consumer of shipping.shipment.delivered.v1 understand the fact without asking Tracking a single follow-up question? If no, the integration event is under-specified.
After All Four
If you have done all four katas, you have:
- an exercised strategic design muscle
- a real context map you can show a colleague
- a tested aggregate in code
- a versioned event contract catalog
Redo one of them every month with a new domain. Compare the outputs at 3 months. The comparison is where the learning compounds.
Evidence Check
The kata set is complete only if:
- you finish each kata within its time-box
- you produce an artifact in each that another engineer could review without you present
- your self-check honestly catches at least one thing you would redo
- you can cite, from memory, the invariant and the event catalog of the checkout you designed and the shipment you modeled