nwave-ai/nw-legacy-refactoring-ddd
DDD-guided legacy refactoring patterns -- strangler fig, bubble context, ACL migration, 14 tactical/strategic/infrastructure patterns, and incremental monolith-to-microservices methodology
npx skills add https://github.com/nWave-ai/nWave --skill nw-legacy-refactoring-ddd
Refactoring legacy systems using Domain-Driven Design as the strategic compass. DDD tells you WHERE and WHY to refactor; traditional techniques (progressive-refactoring, mikado-method) tell you HOW.
Principle: "Start simple, grow big" -- incremental steps tested at each stage.
Ask three questions before any DDD refactoring:
| Cynefin Domain | Refactoring Approach |
|---------------|---------------------|
| Clear | Apply established patterns directly; standard refactoring catalogs |
| Complicated | Analyze with experts, then apply patterns; multiple valid solutions |
| Complex | Probe with safe-to-fail experiments; EventStorming to discover patterns |
| Chaotic | Act first to stabilize, then refactor; emergency patches acceptable |
| Confusion | Gather information before deciding; avoid premature refactoring |
Build new DDD-modeled functionality alongside legacy. Route requests to new code as features complete. Legacy gradually shrinks until fully replaced. Changes are incremental, monitored, low risk of unexpected breakage.
Mikado integration: use Mikado exploration to discover dependencies between legacy components before extracting. Each Mikado leaf becomes an atomic refactoring step.
Create a small bounded context (the "bubble") where DDD principles apply. The bubble communicates with legacy through an Anti-Corruption Layer. Progressively expand the bubble to encompass more legacy functionality.
Steps:
Integration patterns change as refactoring progresses. Map current relationships, identify mismatches, propose new patterns. Typical evolution: Conformist -> Customer-Supplier with ACL -> Partnership.
When a context grows too large or serves conflicting purposes:
Validation: bounded context splits are driven by business evolution, not technical convenience. Validate with domain experts.
When separation causes more friction than value:
These patterns apply tactical DDD concepts (aggregates, value objects, domain events, domain services, CQRS) to refactoring. For foundational definitions and design rules, load domain-driven-design from solution-architect/.
| Pattern | What It Fixes | Key Step |
|---------|--------------|----------|
| Replace primitives with VOs | Primitive obsession | Create self-validating type, replace in aggregate, update mapping |
| Enrich anemic model | Logic in services, data in entities | Move business rules from service "if" statements into owning entity |
| Introduce domain events | Direct coupling between aggregates | Replace method calls with immutable past-tense events + handlers |
| Extract domain service | Cross-aggregate operations in application layer | Create stateless domain-typed service; guard against overuse |
| Introduce CQRS | Read/write contention on same model | Separate read DTOs from write aggregates; CQRS != event sourcing |
Most challenging aspect of DDD refactoring. Use expand/contract pattern for safe migration.
When contexts need data owned by another context:
Prepare for microservice extraction. Mediator is a stepping stone, not a destination.
Only when module is stable, independently deployable, and business-justified.
Measure refactoring progress with automated fitness functions in CI:
| Metric | What It Measures | Tool Examples |
|--------|-----------------|---------------|
| Afferent coupling | Incoming dependencies to module | NDepend, SonarQube, jdepend |
| Efferent coupling | Outgoing dependencies from module | Same |
| Dependency direction | Dependencies flow correctly (inward) | ArchUnit, NetArchTest |
| Test coverage | Safety net for refactoring | Coverage tools |
| Cohesion | Relatedness of components within module | LCOM metrics |
Define fitness function thresholds as acceptance criteria for refactoring stories.
| Test Type | When | Purpose |
|-----------|------|---------|
| Characterization tests | Before touching legacy code | Document current behavior as safety net |
| Contract tests | When splitting contexts | Verify interservice communication |
| Eventual consistency tests | After introducing events | Simulate network failures, verify convergence |
| Schema integrity tests | During database refactoring | Verify constraints and data integrity |
Characterization tests (Feathers): run legacy code, observe output, write tests that assert current behavior -- even if behavior seems wrong. These tests protect against unintended changes during refactoring.
Take nwave-ai/nw-legacy-refactoring-ddd from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.