home / skills / benchflow-ai / skillsbench / legacy-code-reviewer

legacy-code-reviewer skill

/registry/terminal_bench_2.0/full_batch_reviewed/terminal_bench_2_0_modernize-scientific-stack/environment/skills/legacy-code-reviewer

This skill analyzes legacy codebases to identify deprecated patterns and guides modern refactoring for Python 3.12+ and ES2024+ with tests.

npx playbooks add skill benchflow-ai/skillsbench --skill legacy-code-reviewer

Review the files below or copy the command above to add this skill to your agents.

Files (2)
SKILL.md
9.1 KB
---
name: Legacy Code Reviewer
description: Expert system for identifying deprecated patterns, suggesting refactoring to modern standards (Python 3.12+, ES2024+), checking test coverage, and leveraging AI-powered tools. Proactively applied when users request refactoring, updates, or analysis of legacy codebases.
allowed-tools: Read, Grep, Glob, Web Search
last-updated: 2025-12-15
---

# Legacy Code Review and Refactoring Plan

## Core Philosophy

Legacy code review is not just about finding bugs—it's about understanding the **original intent**, reducing technical debt, and incrementally modernizing while maintaining stability. Apply the principle: *"Make it work, make it right, make it fast"* in that order.

---

## Instructions

### 1. Discovery & Analysis

**Use Read, Grep, and Glob tools to:**
- Identify files referenced by the user
- Search for deprecated APIs, patterns, or libraries (e.g., `collections.MutableMapping` → `collections.abc.MutableMapping`)
- Detect code smells:
  - Unused imports/functions (candidates for deletion)
  - Duplicated code blocks (refactor to DRY)
  - High cyclomatic complexity (McCabe > 10)
  - Missing type hints (Python) or JSDoc (JavaScript)

### 2. Modern Tooling Recommendations

**Python Legacy Code (2024-2025 Best Practices):**

| Tool | Purpose | Usage |
|------|---------|-------|
| **Ruff** | Ultra-fast linter + formatter (replaces Flake8, Black, isort) | `ruff check --fix .` |
| **Vulture** | Dead code detection | `vulture src/` |
| **Refurb** | Suggests modern Python idioms | `refurb check src/` |
| **mypy** | Static type checking | `mypy --strict src/` |
| **Bandit** | Security vulnerability scanner | `bandit -r src/` |
| **Radon** | Complexity metrics | `radon cc -s src/` |
| **pytest** + **coverage** | Test coverage analysis | `pytest --cov=src tests/` |

**JavaScript/TypeScript Legacy Code:**

| Tool | Purpose | Usage |
|------|---------|-------|
| **ESLint** (with `eslint-plugin-deprecation`) | Detect deprecated APIs | `eslint --fix .` |
| **Prettier** | Code formatting | `prettier --write .` |
| **TypeScript Compiler** | Type checking for TS/JS | `tsc --noEmit` |
| **ts-prune** | Dead code detection | `ts-prune` |
| **SonarQube** | Multi-language code quality | CI/CD integration |

**AI-Powered Code Review (GitHub Integration):**

| Tool | Key Feature |
|------|-------------|
| **GitHub Copilot** | Suggests refactorings, generates tests, explains legacy functions |
| **CodeRabbit** | Full codebase context-aware reviews in PRs |
| **Qodo.ai (Codium)** | AI test generation and quality checks |
| **DeepSource** | Security + performance analysis |
| **Greptile** | Semantic code search across large repos |

### 3. Refactoring Process (Step-by-Step)

> [!IMPORTANT]
> **Always write tests BEFORE refactoring. If no tests exist, create characterization tests first.**

1. **Understand the Intent**
   - Ask: "What problem was this solving?"
   - Review git history: `git log --follow <file>` and `git blame <file>`
   - Document assumptions in code comments

2. **Establish Safety Nets**
   - Run existing tests: `pytest tests/` (Python) or `npm test` (JS)
   - Measure current coverage: `pytest --cov` → target 80%+ for critical paths
   - Add characterization tests if coverage < 60%

3. **Incremental Refactoring (Layer by Layer)**
   - **Phase 1:** Fix linting/formatting (Ruff, Prettier) — *low risk*
   - **Phase 2:** Add type hints (mypy, TypeScript) — *medium risk*
   - **Phase 3:** Extract functions, reduce complexity — *medium risk*
   - **Phase 4:** Replace deprecated APIs with modern equivalents — *high risk*
   - **Phase 5:** Extract to new modules (strangler fig pattern) — *high risk*

4. **Verification Gates**
   - All existing tests pass (`pytest`, `npm test`)
   - No new linting errors (`ruff check`, `eslint`)
   - Code coverage unchanged or improved (`pytest --cov`)
   - Security scan passes (`bandit`, `npm audit`)

5. **Documentation**
   - Update docstrings with modern examples
   - Add inline comments explaining **why**, not **what**
   - Create migration guide if API changes affect users

### 4. Common Legacy Code Patterns (Python)

| Deprecated | Modern Replacement | Reason |
|-----------|-------------------|--------|
| `from collections import MutableMapping` | `from collections.abc import MutableMapping` | Moved in Python 3.3+ |
| `os.path.join(a, b)` | `pathlib.Path(a) / b` | Type-safe, cleaner API |
| `% formatting` | `f"{variable}"` or `str.format()` | More readable, faster |
| `try/except` without context | `with contextlib.suppress(Exception):` | Cleaner error handling |
| `dict.has_key(k)` | `k in dict` | Pythonic, removed in Py3 |
| No type hints | `def func(x: int) -> str:` | Catches bugs at dev time |

### 5. GitHub Pull Request Best Practices (2024-2025)

> [!TIP]
> **Keep PRs small (<400 lines) for faster, more accurate reviews.**

- **Small PRs:** Break large refactors into atomic changes
- **Self-Review First:** Review your own PR before requesting others
- **Automated Checks:** Enforce linting, tests, security scans in CI/CD
- **Clear Descriptions:** Explain **what**, **why**, **impact**, **how tested**
- **Use Draft PRs:** For work-in-progress, get early feedback
- **Feature Flags:** For risky changes, use toggles to A/B test old vs new logic

---

## Output Format

### Provide the following in your review:

1. **Summary of Findings**
   - List deprecated patterns found (with line numbers)
   - Complexity metrics (if applicable)
   - Security vulnerabilities (if any)

2. **Recommended Tooling**
   - Specific commands to run (e.g., `ruff check --fix src/`)
   - Expected output/improvements

3. **Refactoring Plan (Phased)**
   - Phase 1: Low-risk fixes (formatting, linting)
   - Phase 2: Medium-risk (type hints, small extractions)
   - Phase 3: High-risk (API migrations, architectural changes)

4. **Example Code Block**
   - Show **before** and **after** code
   - Include comments explaining the change
   - Demonstrate modern conventions

---

## Example Usage

**User Request:**
> "Can you review `@src/legacy/old_database_connector.py` and suggest how to update it for better performance and maintainability?"

**Agent Response:**

### Summary of Findings
- **Line 23:** Using deprecated `collections.MutableMapping` (should be `collections.abc.MutableMapping`)
- **Line 45-67:** Database connection logic duplicated 3 times (DRY violation)
- **Line 89:** No type hints, making debugging difficult
- **Complexity:** McCabe score of 15 (threshold is 10)

### Recommended Tooling
```bash
# Run modern linters
ruff check --fix src/legacy/old_database_connector.py
mypy src/legacy/old_database_connector.py
bandit -r src/legacy/

# Check complexity
radon cc -s src/legacy/old_database_connector.py
```

### Refactoring Plan
**Phase 1 (Low Risk):**
- Fix import: `collections.MutableMapping` → `collections.abc.MutableMapping`
- Run Ruff to auto-fix formatting/linting

**Phase 2 (Medium Risk):**
- Add type hints to all functions
- Extract duplicated connection logic to `_get_db_connection()` helper

**Phase 3 (High Risk):**
- Replace raw SQL with SQLAlchemy ORM (if applicable)
- Implement connection pooling for performance

### Example Refactoring

**Before (Legacy):**
```python
from collections import MutableMapping  # DEPRECATED

def connect_db(host, port):
    conn = psycopg2.connect(host=host, port=port)  # Duplicated 3 times
    return conn
```

**After (Modern):**
```python
from collections.abc import MutableMapping
from typing import Optional
import psycopg2
from psycopg2 import pool

# Connection pool (shared resource)
_connection_pool: Optional[pool.SimpleConnectionPool] = None

def get_db_connection(host: str, port: int) -> psycopg2.extensions.connection:
    """
    Get a database connection from the pool.

    Args:
        host: Database host (e.g., 'localhost')
        port: Database port (e.g., 5432)

    Returns:
        Active database connection

    Raises:
        psycopg2.OperationalError: If connection fails
    """
    global _connection_pool
    if _connection_pool is None:
        _connection_pool = pool.SimpleConnectionPool(
            minconn=1, maxconn=10, host=host, port=port
        )
    return _connection_pool.getconn()
```

**Key Improvements:**
- ✅ Fixed deprecated import
- ✅ Added type hints (`str`, `int`, `psycopg2.extensions.connection`)
- ✅ Extracted to single function (DRY)
- ✅ Implemented connection pooling (performance)
- ✅ Added comprehensive docstring

---

## Verification Checklist

Before marking refactoring complete:

- [ ] All existing tests pass
- [ ] Linting passes (`ruff check`, `eslint`)
- [ ] Type checking passes (`mypy`, `tsc`)
- [ ] Security scan clean (`bandit`, `npm audit`)
- [ ] Code coverage maintained or improved
- [ ] Documentation updated
- [ ] PR reviewed by at least one peer
- [ ] Manual testing performed (if applicable)

---

## Additional Resources

- [GitHub Copilot for Legacy Code](https://github.blog/2024-01-22-10-unexpected-ways-to-use-github-copilot/)
- [Refactoring Guru (Design Patterns)](https://refactoring.guru/)
- [Python Type Hints Cheat Sheet](https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html)
- [Google's Code Review Best Practices](https://google.github.io/eng-practices/review/)

Overview

This skill provides an expert legacy code review and pragmatic refactoring plan focused on modernizing Python (3.12+) and ES2024+ codebases. It identifies deprecated patterns, measures complexity and coverage gaps, and recommends tooling plus phased, safety-first refactors. The output is actionable: findings, exact commands, and a stepwise migration plan.

How this skill works

The reviewer scans the requested files and repo using search and static analysis to locate deprecated APIs, duplicated logic, unused code, missing types, and high cyclomatic complexity. It suggests concrete tooling (linters, type checkers, dead-code detectors, security scanners) and produces a phased refactor plan with verification gates and example before/after code. Tests and CI checks are emphasized as safety nets.

When to use it

  • You inherit or audit an older codebase with Python <-> JS/TS mixed code.
  • You need to replace deprecated APIs and adopt modern language idioms.
  • You want a safe, incremental refactor plan that preserves behavior.
  • You need to raise test coverage and add characterization tests before changes.
  • You plan CI/CD enforcement of linting, type checks, and security scans.

Best practices

  • Write characterization tests before changing behavior; target ≥80% critical-path coverage.
  • Keep PRs small (<400 lines) and apply the strangler fig pattern for large migrations.
  • Run automated tooling locally and in CI: Ruff/ESLint, mypy/tsc, Bandit/npm audit.
  • Fix lint/format first, then add types, then restructure and replace APIs (low → high risk).
  • Document why changes were made; update docstrings and create a migration guide for breaking changes.

Example use cases

  • Review a legacy Python connector file to replace deprecated collections imports and add pooling.
  • Scan a mixed repo to identify dead JS/TS modules and add tsconfig + tsc checks.
  • Create a phased plan to migrate code to modern async APIs while preserving tests.
  • Produce exact commands to run linters, static analysis, complexity reports, and security scans.
  • Generate a before/after snippet showing idiomatic f-strings, pathlib, and type annotations.

FAQ

What is the safest first change to make in legacy code?

Start with formatting and lint fixes (Ruff/Prettier/ESLint) and add characterization tests if tests are missing. These are low-risk and improve code readability immediately.

How do I handle areas with no tests?

Write characterization tests that capture current behavior, target critical paths first, then refactor behind those safety nets.