plugins/nw/skills/nw-legacy-refactoring-ddd/SKILL.md
DDD-guided legacy refactoring patterns -- strangler fig, bubble context, ACL migration, 14 tactical/strategic/infrastructure patterns, and incremental monolith-to-microservices methodology
npx skillsauth add nwave-ai/nwave nw-legacy-refactoring-dddInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
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.
testing
Acceptance test creation methodology for the DISTILL wave. Domain knowledge for the acceptance designer agent: port-to-port principle, prior wave reading, wave-decision reconciliation, graceful degradation, and document back-propagation.
testing
Methodology for minimizing test count while maximizing behavioral coverage - behavior definition, anti-pattern catalog, consolidation patterns, stopping criterion, coverage-preserving validation
testing
Methodology for minimizing test count while maximizing behavioral coverage - behavior definition, anti-pattern catalog, consolidation patterns, stopping criterion, coverage-preserving validation
development
Design mandates for acceptance tests - hexagonal boundary, business language abstraction, user journey completeness, pure function extraction, 3 Pillars (domain language / chained narrative / production composition), and the layered ATD discipline (Universe-bound assertion, layer-dependent PBT mode, two-tier acceptance, example-based sad paths)