Goal
Start from a small, deliberately coupled program — read employees from a CSV, email everyone whose birthday is today — and refactor it into a hexagon: a pure domain core behind ports, infrastructure in adapters. The program is trivial on purpose; the skill is drawing the boundary and proving it holds when the technology changes.
Subject: full brief & instructions
Practices
- Hexagonal architecture — the whole exercise: ports, adapters, the dependency rule.
- Coupling & cohesion — the extraction is the act itself: cut the coupling, regroup by cohesion, keep the dependency pointing inward.
- TDD — outside-in with an acceptance test at the edges, fast unit tests on the core.
- Testing strategies — the test strategy that falls out of the architecture: unit-test the core, contract-test the ports, integration-test the adapters.
- Design patterns — Adapter doing the job it was named for.
Milestones
- Naive build. Implement the flat version (or take the kata's starting code): one
class that reads
employees.csv, finds today's birthdays, and sends greetings via a mail library. Ugly is fine — it's the raw material. - End-to-end safety net. One acceptance test that pins current behavior at the system edges: a fixture CSV in, a fake SMTP server (or captured output) out.
- Find the domain. Separate the pure logic — "who has a birthday on date X" and the greeting content — from all I/O. No interfaces yet; just untangle.
- Driven ports. Extract
EmployeeRepositoryandGreetingSenderinterfaces owned by the core; the CSV reader and the mail sender become adapters implementing them. The core now imports nothing from infrastructure. - Fast tests. Unit-test the core against in-memory fakes; write one contract test per port that both the real adapter and the fake must pass.
- Prove the boundary. Add a second adapter pair — SQLite repository, console or Slack sender — selected purely by wiring. Zero changes in the core, or milestone 4 wasn't honest.
Stretch goals
- Property-test the birthday rule, including Feb 29 birthdays in non-leap years.
- Add a driving port: the same use case triggered by a CLI adapter and by a scheduler adapter.
- Port the core to another language, carrying the unit tests over; only adapters should need rethinking.
Related
- Birthday Greetings — hexagonal extraction — subject — the self-contained work statement: behavior, examples, constraints, acceptance checks.
- Hexagonal architecture and
Coupling & cohesion — the
concept notes whose
# Practicecites this project. - TDD, Testing strategies, Design patterns — drilled along the way.
- Gilded Rose — legacy rescue — refactoring under a safety net at code scale; this kata does it at architecture scale.
- Event-sourced bank account — where the event store becomes just another driven port.