| name | legacy-modernizer |
| description | Modernize legacy code safely in ANY project without breaking existing functionality. Use when working with old code that needs updating while maintaining stability. |
Legacy Modernizer - Safe Legacy Code Evolution
🎯 When to Use This Skill
Use when dealing with:
- Code written 5+ years ago
- No tests or documentation
- "Don't touch - it works" code
- Deprecated dependencies
- Security vulnerabilities in old code
- Performance issues in legacy systems
⚡ The Golden Rule of Legacy Code
NEVER refactor without tests! First make it testable, then make it better.
📋 The Safe Modernization Process
Phase 1: UNDERSTAND (Don't Touch Yet!)
WITH MCP Tools:
"Analyze the architecture and dependencies of [legacy module]"
"Document how this legacy code works"
WITHOUT MCP:
1. Map the Territory:
grep -r "LegacyClass" --include="*.js" --include="*.py" --include="*.java"
echo "=== LEGACY CODE MAP ===" > legacy_analysis.md
echo "Entry points:" >> legacy_analysis.md
grep -r "main\|init\|start" --include="*.js" >> legacy_analysis.md
echo "Dependencies:" >> legacy_analysis.md
grep -r "require\|import\|include" legacy_module/ >> legacy_analysis.md
2. Document Current Behavior:
function legacyFunction(data) {
console.log('[LEGACY TRACE] Input:', JSON.stringify(data));
console.log('[LEGACY TRACE] Output:', result);
return result;
}
Phase 2: PROTECT (Add Safety Net)
WITH MCP (Test Generator):
"Generate characterization tests for this legacy code"
WITHOUT MCP:
Characterization Tests (Capture Current Behavior):
describe('Legacy System - Current Behavior', () => {
it('should handle normal input as currently implemented', () => {
const result = legacyFunction({ id: 1, name: 'test' });
expect(result).toEqual({
status: 'OK',
data: 'TEST',
timestamp: expect.any(Number),
});
});
it('should handle null input as currently implemented', () => {
expect(() => legacyFunction(null)).toThrow('Cannot read property');
});
});
Golden Master Testing:
for input in test_inputs/*; do
./legacy_app < "$input" > "golden_masters/$(basename $input).output"
done
for input in test_inputs/*; do
./modernized_app < "$input" > temp.output
diff "golden_masters/$(basename $input).output" temp.output
done
Phase 3: ISOLATE (Strangler Fig Pattern)
Wrap Legacy Code:
class ModernInterface {
constructor() {
this.legacy = new LegacySystem();
}
async processData(input) {
const legacyFormat = this.convertToLegacyFormat(input);
const result = this.legacy.oldProcessMethod(legacyFormat);
return this.convertToModernFormat(result);
}
convertToLegacyFormat(modern) {
}
convertToModernFormat(legacy) {
}
}
Phase 4: MODERNIZE (Incremental Updates)
Safe Modernization Patterns:
1. Branch by Abstraction:
class DataProcessor {
constructor(useModern = false) {
this.useModern = useModern;
}
process(data) {
if (this.useModern) {
return this.modernProcess(data);
}
return this.legacyProcess(data);
}
legacyProcess(data) {
}
modernProcess(data) {
}
}
2. Parallel Run (Verify Compatibility):
async function processWithVerification(data) {
const [legacyResult, modernResult] = await Promise.all([
legacyProcess(data),
modernProcess(data),
]);
if (JSON.stringify(legacyResult) !== JSON.stringify(modernResult)) {
console.error('Results mismatch!', { legacyResult, modernResult });
return legacyResult;
}
return modernResult;
}
🔧 Common Modernization Tasks
1. Callback Hell → Promises/Async
Before (Legacy):
getData(function (err, data) {
if (err) return handleError(err);
processData(data, function (err, result) {
if (err) return handleError(err);
saveResult(result, function (err) {
if (err) return handleError(err);
done();
});
});
});
After (Modern):
async function modernFlow() {
try {
const data = await getData();
const result = await processData(data);
await saveResult(result);
done();
} catch (err) {
handleError(err);
}
}
2. Global Variables → Module Pattern
Before (Legacy):
var globalConfig = {};
var globalState = {};
function doSomething() {
globalState.counter++;
return globalConfig.prefix + globalState.counter;
}
After (Modern):
class AppModule {
constructor(config) {
this.config = config;
this.state = { counter: 0 };
}
doSomething() {
this.state.counter++;
return this.config.prefix + this.state.counter;
}
}
export default AppModule;
3. SQL Injection → Parameterized Queries
Before (Legacy - DANGEROUS):
const query = `SELECT * FROM users WHERE id = ${userId}`;
db.query(query);
After (Modern - SAFE):
const query = 'SELECT * FROM users WHERE id = ?';
db.query(query, [userId]);
4. Old Dependencies → Modern Alternatives
const DEPENDENCY_MAP = {
request: 'axios',
async: 'native-promises',
underscore: 'lodash',
bower: 'npm',
grunt: 'webpack',
jquery: 'vanilla-js',
};
📊 Modernization Checklist
Security Fixes (Priority 1):
Code Quality (Priority 2):
Performance (Priority 3):
Developer Experience (Priority 4):
🚨 Red Flags in Legacy Code
Watch for these danger signs:
new Date('2024-01-01');
if (value == true)
eval(userInput);
const data = fs.readFileSync();
if (status === 2)
JSON.parse(data);
💡 Migration Strategies by Language
JavaScript → Modern JS:
npx lebab --transform arrow,let,template legacy.js -o modern.js
npx eslint --fix legacy.js
npx tsc --init
mv legacy.js legacy.ts
npx tsc --allowJs --checkJs
Python 2 → Python 3:
2to3 -w legacy.py
print "Hello" → print("Hello")
xrange() → range()
unicode() → str()
jQuery → Vanilla JS:
$('#element').hide();
$('.class').on('click', handler);
document.getElementById('element').style.display = 'none';
document.querySelectorAll('.class').forEach(el => {
el.addEventListener('click', handler);
});
📈 Success Metrics
Track modernization progress:
## Legacy Modernization Scorecard
### Week 1 | Week 4 | Week 8
----------|---------|--------
Coverage: 0% | 45% | 78%
Security Issues: 12 | 6 | 1
Tech Debt (hours): 200 | 120 | 40
Build Time: 5min | 3min | 1min
Bundle Size: 2.4MB | 1.2MB | 600KB
Load Time: 4s | 2.5s | 1.2s
🔄 Rollback Strategy
Always have an escape plan:
if (featureFlags.useModernSystem) {
return modernImplementation();
} else {
return legacyImplementation();
}
ALTER TABLE users ADD COLUMN email_verified BOOLEAN DEFAULT false;
ALTER TABLE users DROP COLUMN email_verified;
Remember: Legacy code is not bad code - it's proven code that needs careful evolution! 🏛️→🏢