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.
Use when receiving code review feedback, before implementing suggestions, especially if feedback seems unclear or technically questionable - requires technical rigor and verification, not performative agreement or blind implementation
Use when completing tasks, implementing major features, or before merging to verify work meets requirements
Execute git commit with conventional commit message analysis, intelligent staging, and message generation. Use when user asks to commit changes, create a git commit, or mentions "/commit". Supports: (1) Auto-detecting type and scope from changes, (2) Generating conventional commit messages from diff, (3) Interactive commit with optional type/scope/description overrides, (4) Intelligent file staging for logical grouping
Comprehensive GitHub code review with AI-powered swarm coordination
Behavioral guidelines to reduce common LLM coding mistakes. Use when writing, reviewing, or refactoring code to avoid overcomplication, make surgical changes, surface assumptions, and define verifiable success criteria.
Use this skill to review code. It supports both local changes (staged or working tree) and remote Pull Requests (by ID or URL). It focuses on correctness, maintainability, and adherence to project standards.
Refactor bloated AGENTS.md, CLAUDE.md, or similar agent instruction files to follow progressive disclosure principles. Splits monolithic files into organized, linked documentation.
Create high-quality git commits: review/stage intended changes, split into logical commits, and write clear commit messages (including Conventional Commits). Use when the user asks to commit, craft a commit message, stage changes, or split work into multiple commits.
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.