7 min read • Guide 535 of 877
Managing Legacy Code in Active Projects
Legacy code requires careful handling to avoid breaking existing functionality while enabling new development. GitScrum helps teams track legacy-related work separately, plan incremental improvements, and maintain clear visibility into the balance between maintenance burden and feature development.
Legacy Code Strategies
| Strategy | When to Use | Effort |
|---|---|---|
| Add tests only | High-risk, frequently changed | Low |
| Extract and test | Module worth preserving | Medium |
| Wrap and replace | Strangler Fig pattern | Medium-High |
| Full rewrite | Obsolete, unmaintainable | High |
Working with Legacy Code
LEGACY CODE IMPROVEMENT FRAMEWORK
1. ASSESS THE LEGACY CODE
┌─────────────────────────────────────────────────┐
│ For each legacy component, evaluate: │
│ │
│ Change Frequency: │
│ ├── High: Modified monthly → Priority │
│ ├── Medium: Modified quarterly → Plan ahead │
│ └── Low: Rarely touched → Leave alone │
│ │
│ Bug Rate: │
│ ├── High: Frequent bugs → Fix urgently │
│ ├── Medium: Occasional bugs → Improve │
│ └── Low: Stable → Maintain │
│ │
│ Test Coverage: │
│ ├── None: No tests → Add tests │
│ ├── Low: < 40% → Improve │
│ └── Good: > 70% → Maintain │
└─────────────────────────────────────────────────┘
2. CATEGORIZE APPROACH
┌─────────────────────────────────────────────────┐
│ │
│ High Change Frequency │
│ │ │
│ ┌──────────┼──────────┐ │
│ │ WRAP │ EXTRACT │ │
│ │ AND │ AND │ │
│ │ REPLACE │ TEST │ │
│ │ │ │ │
│ ├──────────┼──────────┤ │
│ │ DEFER │ ADD │ │
│ │ (costs │ TESTS │ │
│ │ exceed │ ONLY │ │
│ │ benefit)│ │ │
│ └──────────┴──────────┘ │
│ Low Quality │ High Quality │
│ │
└─────────────────────────────────────────────────┘
The Boy Scout Rule
INCREMENTAL IMPROVEMENT PRACTICE
RULE: Leave the code better than you found it
WHEN TOUCHING LEGACY CODE:
┌─────────────────────────────────────────────────┐
│ Before making your change: │
│ 1. Add tests for the code you'll modify │
│ 2. Verify tests capture current behavior │
│ │
│ Make your change: │
│ 3. Implement the feature/fix │
│ 4. Ensure tests still pass │
│ │
│ Leave it better: │
│ 5. Small refactor (rename, extract method) │
│ 6. Add any missing documentation │
│ 7. Improve test coverage slightly │
│ │
│ Constraint: Improvement adds ≤30% to task time │
└─────────────────────────────────────────────────┘
EXAMPLE:
┌─────────────────────────────────────────────────┐
│ Task: Add discount calculation to order │
│ Time estimate: 3 hours │
│ │
│ Improvement time budget: ~1 hour │
│ │
│ Improvements made: │
│ ├── Added 3 tests for existing calculateTotal │
│ ├── Renamed confusing variable names │
│ ├── Extracted duplicate logic to helper │
│ └── Added JSDoc for public methods │
│ │
│ Result: Feature works + code slightly better │
└─────────────────────────────────────────────────┘
Strangler Fig Pattern
GRADUAL REPLACEMENT STRATEGY
STRANGLER FIG APPROACH:
┌─────────────────────────────────────────────────┐
│ New features use new code │
│ Old features gradually migrate │
│ Legacy shrinks over time │
└─────────────────────────────────────────────────┘
IMPLEMENTATION:
┌─────────────────────────────────────────────────┐
│ │
│ PHASE 1: Create wrapper │
│ ┌────────────────────────────────────────────┐ │
│ │ Consumers → Facade → Legacy Code │ │
│ └────────────────────────────────────────────┘ │
│ │
│ PHASE 2: New implementation behind facade │
│ ┌────────────────────────────────────────────┐ │
│ │ ┌→ New Code (new features)│ │
│ │ Consumers → Facade │ │
│ │ └→ Legacy (existing) │ │
│ └────────────────────────────────────────────┘ │
│ │
│ PHASE 3: Migrate features to new code │
│ ┌────────────────────────────────────────────┐ │
│ │ ┌→ New Code (80%) │ │
│ │ Consumers → Facade │ │
│ │ └→ Legacy (20%) │ │
│ └────────────────────────────────────────────┘ │
│ │
│ PHASE 4: Remove legacy │
│ ┌────────────────────────────────────────────┐ │
│ │ Consumers → Facade → New Code (100%) │ │
│ └────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────┘
Legacy Backlog Management
LEGACY IMPROVEMENT TRACKING
BACKLOG STRUCTURE:
┌─────────────────────────────────────────────────┐
│ Project: Legacy Improvements │
│ │
│ Labels: │
│ ├── [legacy-testing] - Add test coverage │
│ ├── [legacy-refactor] - Code improvements │
│ ├── [legacy-replace] - Module replacement │
│ └── [legacy-debt] - Technical debt items │
│ │
│ Capacity: 15% of team time per sprint │
│ │
│ Prioritization: │
│ 1. Modules being actively modified │
│ 2. High bug rate areas │
│ 3. Performance bottlenecks │
│ 4. Security concerns │
│ 5. Developer frustration areas │
└─────────────────────────────────────────────────┘
TASK TEMPLATE:
┌─────────────────────────────────────────────────┐
│ Title: Add test coverage to PaymentService │
│ Labels: [legacy-testing] [payments] │
│ │
│ Current State: │
│ Test coverage: 12% │
│ Bug rate: 3 bugs/month │
│ Change frequency: High │
│ │
│ Goal: │
│ Add tests for core payment flows │
│ Target coverage: 60% │
│ │
│ Approach: │
│ 1. List critical paths to test │
│ 2. Create test fixtures │
│ 3. Write tests for happy path │
│ 4. Add edge case tests │
│ │
│ Acceptance: │
│ ☐ Coverage > 60% for PaymentService │
│ ☐ All existing tests still pass │
│ ☐ No behavior changes │
└─────────────────────────────────────────────────┘
Metrics Dashboard
LEGACY IMPROVEMENT METRICS
CODE QUALITY TRENDS:
┌─────────────────────────────────────────────────┐
│ Module: PaymentService │
│ │
│ Test Coverage: │
│ Jan: 12% → Feb: 35% → Mar: 58% ↗ Improving │
│ │
│ Bug Rate (per month): │
│ Jan: 5 → Feb: 3 → Mar: 1 ↘ Improving │
│ │
│ Change Velocity (time per change): │
│ Jan: 4h → Feb: 3h → Mar: 2h ↘ Improving │
└─────────────────────────────────────────────────┘
OVERALL LEGACY STATUS:
┌─────────────────────────────────────────────────┐
│ Total legacy modules: 45 │
│ ├── Critical (needs attention): 8 │
│ ├── Improving (work in progress): 12 │
│ ├── Stable (acceptable state): 20 │
│ └── Modern (fully updated): 5 │
│ │
│ Trend: -3 critical modules this quarter │
└─────────────────────────────────────────────────┘
Best Practices
- Test before changing legacy code
- Small, incremental improvements with each touch
- Dedicated capacity for legacy work (10-20%)
- Track metrics to show improvement
- Strangler pattern for large replacements
- Document tribal knowledge when discovered
- Celebrate progress even if slow
- Don't rewrite unless truly necessary
Anti-Patterns
✗ Changing legacy without tests
✗ Big bang rewrite attempts
✗ No time allocated for improvements
✗ Mixing feature + major refactor in one PR
✗ Only fixing when broken
✗ No metrics on legacy health