Modernize legacy codebases, migrate frameworks, and reduce technical debt. Use for legacy system updates or framework migrations.
Install
npx skillscat add htlin222/dotfiles/legacy Install via the SkillsCat registry.
This skill provides tools and strategies for modernizing legacy codebases, including framework migrations, language upgrades, and technical debt reduction. It addresses the challenge of updating outdated systems while minimizing risk through patterns like strangler fig and branch by abstraction. Developers should use it when upgrading legacy systems, migrating frameworks, decomposing monoliths, or reducing technical debt in existing codebases.
Legacy Modernization
Safely upgrade and modernize legacy systems.
When to Use
- Framework migrations
- Language version upgrades
- Monolith decomposition
- Technical debt reduction
- Dependency updates
Migration Strategies
Strangler Fig Pattern
┌─────────────────────────────────────┐
│ Load Balancer │
└──────────────┬──────────────────────┘
│
┌───────┴───────┐
│ │
┌──────▼──────┐ ┌──────▼──────┐
│ Legacy │ │ New │
│ System │ │ Service │
└─────────────┘ └─────────────┘
1. Route new features to new service
2. Gradually migrate existing features
3. Eventually retire legacy systemBranch by Abstraction
# 1. Create abstraction layer
class PaymentProcessor(ABC):
@abstractmethod
def process(self, amount: float) -> bool:
pass
# 2. Wrap legacy implementation
class LegacyPaymentProcessor(PaymentProcessor):
def __init__(self, legacy_system):
self.legacy = legacy_system
def process(self, amount: float) -> bool:
return self.legacy.old_process_method(amount)
# 3. Create new implementation
class ModernPaymentProcessor(PaymentProcessor):
def process(self, amount: float) -> bool:
# New implementation
pass
# 4. Use feature flag to switch
processor = (ModernPaymentProcessor() if feature_flag("new_payment")
else LegacyPaymentProcessor(legacy))Migration Checklist
Before Starting
- Document current behavior
- Add tests for existing functionality
- Set up monitoring and alerts
- Create rollback plan
- Communicate with stakeholders
During Migration
- Make incremental changes
- Test after each change
- Monitor error rates
- Keep legacy running in parallel
- Document breaking changes
After Migration
- Remove feature flags
- Clean up legacy code
- Update documentation
- Archive old codebase
- Post-mortem lessons learned
Common Migrations
jQuery to React
// Phase 1: Embed React in jQuery app
const root = document.getElementById("new-component");
ReactDOM.render(<NewComponent />, root);
// Phase 2: Shared state
window.appState = { user: null };
// Both jQuery and React read from appState
// Phase 3: Gradual replacement
// Replace one component at a timePython 2 to 3
# Use __future__ imports for compatibility
from __future__ import print_function, division, absolute_import
# Use six for cross-version compatibility
import six
if six.PY2:
text_type = unicode
else:
text_type = str
# Run 2to3 tool
# python -m lib2to3 --write --nobackups src/Compatibility Layers
# Adapter for API changes
class CompatibilityAdapter:
def __init__(self, new_service):
self.new = new_service
# Old API signature
def get_user(self, user_id):
# Translate to new API
return self.new.fetch_user(id=user_id)
# Deprecation warning
def old_method(self):
warnings.warn(
"old_method is deprecated, use new_method instead",
DeprecationWarning
)
return self.new.new_method()Examples
Input: "Migrate from Express to Fastify"
Action: Create adapter layer, migrate routes incrementally, test each step
Input: "Reduce technical debt in this module"
Action: Add tests first, refactor incrementally, maintain compatibility