SuperAPI AI Directory

legacy-code-expert

Testing & quality

View repository

Updated 10-16 00:06

About this skill

ABOUTME: Feathers' dependency-breaking techniques for safely modifying untested legacy code ABOUTME: Seam identification, change point analysis, characterization test planning Legacy Code Expert

When to invoke: before verification-protocol (TDD), when the target code lacks tests and has dependencies that block testing. This skill produces the analysis; verification-protocol drives the test-first cycle that follows.

Workflow

  1. Identify change point (where the modification goes)
  2. Map dependencies blocking testability
  3. Find seams (places to alter behavior without editing production code)
  4. Select techniques (simplest that works, minimal ripple)
  5. Plan characterization tests (capture current behavior)
  6. Define transformation steps (small, reversible)
  7. Hand off to verification-protocol for TDD execution

Seam Types

Seam Mechanism Best For Example
Object Polymorphism, interfaces OOP languages (Java, C#, Go, Ruby) Extract interface, subclass and override
Preprocessing Macros, conditional compilation C/C++ #ifdef TESTING to swap implementations
Link Linker substitution, module replacement C/C++, dynamic languages Replace .o file, monkey-patch module

Seam identification questions:

  • Can I substitute this dependency via a constructor or method parameter?
  • Is there a virtual/overridable method I can intercept?
  • Can I extract an interface the caller depends on?
  • Does the language support module-level replacement (mocks, monkey-patching)?

Dependency-Breaking Techniques

Organized by primary seam type. Prefer techniques higher in each list (simpler, less invasive).

Object Seams

Technique When to Use
Extract Interface Class has concrete dependency; create interface for substitution
Parameterize Constructor Dependency created internally; pass it in instead
Parameterize Method Single method needs a dependency; pass as argument
Extract and Override Call Isolate one problematic call into a virtual method
Extract and Override Factory Method Object creation blocks testing; make it overridable
Extract and Override Getter Field access blocks testing; route through virtual getter
Subclass and Override Method Create test subclass that overrides problematic methods
Extract Implementer Move implementation to new class, keep interface in original
Break Out Method Object Large method with many dependencies; extract to own class
Adapt Parameter Wrap parameter type to break dependency on problematic type
Pull Up Feature Move method to superclass to enable override in subclass
Push Down Dependency Move dependency to subclass, keep parent testable
Introduce Instance Delegator Instance method delegates to static (enables override)

Preprocessing/Text Seams

Technique When to Use
Template Redefinition Use generics/templates to inject test dependencies
Text Redefinition Use macros to redefine dependencies at compile time
Definition Completion Provide test implementation for incomplete type

Link/Global Seams

Technique When to Use
Encapsulate Global References Wrap globals in a class for controlled access
Replace Global Reference with Getter Access global through virtual getter
Introduce Static Setter Add setter for singleton/global (test-only)
Replace Function with Function Pointer Use function pointers for runtime substitution
Link Substitution Replace at link time (C/C++ only)
Supersede Instance Variable Add setter to replace dependency post-construction
Primitivize Parameter Replace object params with primitives to cut dependency

Output Format

Produce this analysis, then hand off to verification-protocol:

## Legacy Code Analysis: [File/Class]

### Change Point
[Where the modification goes and what behavior changes]

### Dependencies Blocking Testing
- [dependency]: [why it blocks tests]

### Identified Seams
| Seam Type | Location | Exploitation Strategy |
|-----------|----------|-----------------------|
| [type] | [where] | [how to use it] |

### Recommended Techniques
1. **[Technique]**: [one-line rationale]
   - Steps: [ordered list of mechanical changes]
   - Risk: [what could go wrong]

### Characterization Tests
[Tests to lock current behavior BEFORE any changes]
- [test]: calls X with Y, expects Z (current behavior, not ideal)

### Transformation Steps
1. [small, reversible step]
2. [next step]
...
N. Hand off to verification-protocol: write failing test for new behavior

Guidelines

  • Safety over elegance: smaller, safer changes win
  • Characterization tests capture ACTUAL behavior (bugs included), not ideal behavior
  • Goal: get tests in place, not perfect design
  • Some debt is acceptable if it enables testing
  • When full rewrite is cheaper than incremental change, say so (R4 deviation)
  • Document reasoning for future maintainers