askill
legacy-modernizer

legacy-modernizerSafety 100Repository

Modernize legacy code safely in ANY project without breaking existing functionality. Use when working with old code that needs updating while maintaining stability.

0 stars
1.2k downloads
Updated 1/26/2026

Package Files

Loading files...
SKILL.md

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:

# Find all files related to the feature
grep -r "LegacyClass" --include="*.js" --include="*.py" --include="*.java"

# Trace execution flow
echo "=== LEGACY CODE MAP ===" > legacy_analysis.md
echo "Entry points:" >> legacy_analysis.md
grep -r "main\|init\|start" --include="*.js" >> legacy_analysis.md

# Find dependencies
echo "Dependencies:" >> legacy_analysis.md
grep -r "require\|import\|include" legacy_module/ >> legacy_analysis.md

2. Document Current Behavior:

// Add temporary logging to understand flow
function legacyFunction(data) {
  console.log('[LEGACY TRACE] Input:', JSON.stringify(data));
  // ... existing code ...
  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):

// Not testing if it's "right", just what it currently does
describe('Legacy System - Current Behavior', () => {
  it('should handle normal input as currently implemented', () => {
    const result = legacyFunction({ id: 1, name: 'test' });

    // Capture EXACT current output
    expect(result).toEqual({
      status: 'OK',
      data: 'TEST', // Even if this seems wrong!
      timestamp: expect.any(Number),
    });
  });

  it('should handle null input as currently implemented', () => {
    // Even if it crashes, document it!
    expect(() => legacyFunction(null)).toThrow('Cannot read property');
  });
});

Golden Master Testing:

# Capture current outputs
for input in test_inputs/*; do
  ./legacy_app < "$input" > "golden_masters/$(basename $input).output"
done

# After changes, verify outputs match
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:

// Step 1: Create wrapper (Facade)
class ModernInterface {
  constructor() {
    this.legacy = new LegacySystem();
  }

  async processData(input) {
    // Modern interface
    const legacyFormat = this.convertToLegacyFormat(input);
    const result = this.legacy.oldProcessMethod(legacyFormat);
    return this.convertToModernFormat(result);
  }

  convertToLegacyFormat(modern) {
    // Transform modern input to legacy format
  }

  convertToModernFormat(legacy) {
    // Transform legacy output to modern format
  }
}

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) {
    // Original implementation
  }

  modernProcess(data) {
    // New implementation
  }
}

2. Parallel Run (Verify Compatibility):

async function processWithVerification(data) {
  const [legacyResult, modernResult] = await Promise.all([
    legacyProcess(data),
    modernProcess(data),
  ]);

  // Compare results
  if (JSON.stringify(legacyResult) !== JSON.stringify(modernResult)) {
    console.error('Results mismatch!', { legacyResult, modernResult });
    // Use legacy result for safety
    return legacyResult;
  }

  // Both match, safe to use modern
  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

// Mapping old to new
const DEPENDENCY_MAP = {
  request: 'axios', // HTTP client
  async: 'native-promises', // Flow control
  underscore: 'lodash', // Utilities
  bower: 'npm', // Package management
  grunt: 'webpack', // Build tool
  jquery: 'vanilla-js', // DOM manipulation
};

// Safe migration approach:
// 1. Install new alongside old
// 2. Migrate one file at a time
// 3. Run tests after each migration
// 4. Remove old when complete

πŸ“Š Modernization Checklist

Security Fixes (Priority 1):

  • SQL injection vulnerabilities
  • XSS vulnerabilities
  • Hardcoded secrets removed
  • Outdated crypto replaced
  • Input validation added
  • HTTPS enforcement

Code Quality (Priority 2):

  • Global variables eliminated
  • Callbacks β†’ Promises/Async
  • Var β†’ Let/Const
  • == β†’ ===
  • Error handling improved
  • Dead code removed

Performance (Priority 3):

  • Database queries optimized
  • Caching implemented
  • Lazy loading added
  • Bundle size reduced
  • Memory leaks fixed

Developer Experience (Priority 4):

  • Tests added (>60% coverage)
  • Documentation written
  • Linting configured
  • Types added (TypeScript/JSDoc)
  • CI/CD pipeline setup

🚨 Red Flags in Legacy Code

Watch for these danger signs:

// 🚨 Date handling
new Date('2024-01-01'); // Timezone issues!

// 🚨 Type coercion
if (value == true)
  // Use === instead

  // 🚨 Eval usage
  eval(userInput); // Security nightmare!

// 🚨 Synchronous I/O
const data = fs.readFileSync(); // Blocks everything!

// 🚨 Magic numbers
if (status === 2)
  // What does 2 mean?

  // 🚨 No error handling
  JSON.parse(data); // Will crash on bad input

πŸ’‘ Migration Strategies by Language

JavaScript β†’ Modern JS:

# Use automated tools first
npx lebab --transform arrow,let,template legacy.js -o modern.js
npx eslint --fix legacy.js

# TypeScript migration
npx tsc --init
mv legacy.js legacy.ts
npx tsc --allowJs --checkJs

Python 2 β†’ Python 3:

# Automated conversion
2to3 -w legacy.py

# Common fixes
print "Hello"     β†’ print("Hello")
xrange()         β†’ range()
unicode()        β†’ str()

jQuery β†’ Vanilla JS:

// jQuery
$('#element').hide();
$('.class').on('click', handler);

// Vanilla
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:

// Feature flags for safe rollout
if (featureFlags.useModernSystem) {
  return modernImplementation();
} else {
  return legacyImplementation();
}

// Database migrations with rollback
// up.sql
ALTER TABLE users ADD COLUMN email_verified BOOLEAN DEFAULT false;

// down.sql
ALTER TABLE users DROP COLUMN email_verified;

Remember: Legacy code is not bad code - it's proven code that needs careful evolution! πŸ›οΈβ†’πŸ’

Install

Download ZIP
Requires askill CLI v1.0+β–Ά

AI Quality Score

95/100Analyzed 2/9/2026

An exceptional, comprehensive guide for legacy code modernization. It prioritizes safety through characterization tests and incremental patterns like the Strangler Fig. The content is highly actionable with specific CLI commands, code transformations, and success metrics.

100
95
90
95
95

Metadata

Licenseunknown
Version-
Updated1/26/2026
Publisherj0KZ

Tags

apici-cddatabaseobservabilitysecuritytesting