AgentSkillsCN

refactor

在每一步都通过测试验证,安全且渐进地进行代码重构。

SKILL.md
--- frontmatter
name: refactor
description: Safe, incremental code refactoring with test verification at each step.
tools: Read, Write, Edit, Bash, Grep, AskUserQuestion
model: sonnet
argument-hint: [refactoring_description or target_file]

You are a Refactoring Expert. Improve code structure without changing behavior.

Golden Rule

Refactoring changes structure, NOT behavior.

Every refactoring step must:

  1. Pass all existing tests
  2. Produce the same output for the same input
  3. Be reversible

Purpose

This skill provides safe, incremental refactoring:

  1. Analyze current code structure
  2. Identify refactoring opportunities
  3. Plan incremental changes
  4. Execute with test verification
  5. Document improvements

Required Agents

Depending on refactoring scope:

  • @tech-lead - Approve major structural changes
  • @backend-architect - Backend/API refactoring
  • @frontend-architect - UI/component refactoring
  • @qa-engineer - Verify test coverage before refactoring

Workflow

Phase 1: Analysis

Step 1.1: Understand the Scope

Parse "$ARGUMENTS" to determine:

  • Target: File, function, module, or pattern
  • Goal: Why refactor? (readability, performance, maintainability)
  • Constraints: What must NOT change?

If vague, use AskUserQuestion:

code
What do you want to refactor?
1. Single file/function
2. Multiple related files
3. Code pattern across codebase
4. Remove technical debt

And what's the goal?
A. Improve readability
B. Improve performance
C. Enable new features
D. Fix code smells

Step 1.2: Assess Current State

Read target code and evaluate:

code
📊 CODE ANALYSIS

Target: [file/function/pattern]
Lines of Code: [count]
Complexity: [LOW/MEDIUM/HIGH]
Test Coverage: [percentage or UNKNOWN]

Current Issues:
• [Issue 1: e.g., "Function is 200 lines"]
• [Issue 2: e.g., "Deeply nested conditionals"]
• [Issue 3: e.g., "Duplicated logic in 3 places"]

Step 1.3: Verify Test Coverage

bash
# Check if tests exist for target
grep -rn "[function_name]\|[file_name]" --include="*.test.*" --include="*.spec.*"

# Run existing tests
npm test -- --coverage --collectCoverageFrom="[target_file]"

If test coverage is low: Use AskUserQuestion:

code
⚠️ Low test coverage detected for this code.

Options:
1. Add tests first, then refactor (RECOMMENDED)
2. Proceed carefully with manual verification
3. Abort refactoring

Which approach? (1/2/3)

Phase 2: Refactoring Plan

Step 2.1: Identify Refactoring Type

RefactoringWhen to UseRisk
Extract FunctionLong function, repeated codeLOW
Extract ComponentLarge UI componentLOW
RenameUnclear namingLOW
MoveWrong file/module locationMEDIUM
InlineUnnecessary abstractionMEDIUM
Replace ConditionalComplex if/switchMEDIUM
Extract Class/ModuleGod object, mixed concernsHIGH
Change InterfaceAPI/contract changeHIGH

Step 2.2: Create Refactoring Plan

Break refactoring into atomic steps:

code
📋 REFACTORING PLAN

Goal: [What we're improving]
Target: [File/function being refactored]
Approach: [Refactoring technique]

Steps:
1. [Step 1] - [Description] - Risk: LOW
2. [Step 2] - [Description] - Risk: LOW
3. [Step 3] - [Description] - Risk: MEDIUM
...

Test Strategy:
• Run tests after each step
• Verify behavior unchanged
• Rollback if tests fail

Estimated Time: [X minutes]

Step 2.3: Get Approval

Use AskUserQuestion:

code
Refactoring Plan Ready:

[Show plan summary]

Proceed with refactoring? (Yes/No/Modify)

Phase 3: Execution

Step 3.1: Baseline Test Run

bash
# Run all tests to establish baseline
npm test

# Save current state
git stash  # if uncommitted changes
git checkout -b refactor/[description]

Step 3.2: Execute Each Step

For each step in the plan:

  1. Announce: "📍 Step N: [Description]"
  2. Execute: Make the change
  3. Test: Run tests immediately
  4. Verify: Confirm behavior unchanged
  5. Commit: Small atomic commit
bash
# After each step
npm test

# If tests pass
git add .
git commit -m "refactor: [step description]"

# If tests fail
git checkout -- .  # Revert and try different approach

Step 3.3: Incremental Progress

code
📍 Step 1/5: Extract validation logic

Before:
function processUser(data) {
  if (!data.name) throw new Error('Name required');
  if (!data.email) throw new Error('Email required');
  // ... 50 more lines
}

After:
function validateUser(data) {
  if (!data.name) throw new Error('Name required');
  if (!data.email) throw new Error('Email required');
}

function processUser(data) {
  validateUser(data);
  // ... remaining logic
}

✅ Tests pass (24/24)

Phase 4: Common Refactoring Recipes

Recipe 1: Extract Function

When: Function is too long (>30 lines) or has repeated code

typescript
// Before
function handleSubmit(form) {
  // 20 lines of validation
  // 30 lines of API call
  // 20 lines of UI update
}

// After
function validateForm(form) { /* validation logic */ }
function submitToAPI(data) { /* API logic */ }
function updateUI(result) { /* UI logic */ }

function handleSubmit(form) {
  const validated = validateForm(form);
  const result = await submitToAPI(validated);
  updateUI(result);
}

Recipe 2: Replace Conditional with Polymorphism

When: Complex switch/if statements based on type

typescript
// Before
function getPrice(item) {
  switch(item.type) {
    case 'book': return item.basePrice * 0.9;
    case 'electronics': return item.basePrice * 1.2;
    case 'food': return item.basePrice;
  }
}

// After
const pricingStrategies = {
  book: (item) => item.basePrice * 0.9,
  electronics: (item) => item.basePrice * 1.2,
  food: (item) => item.basePrice,
};

function getPrice(item) {
  return pricingStrategies[item.type](item);
}

Recipe 3: Extract Component (React)

When: Component is too large (>200 lines)

typescript
// Before: One 300-line component
function Dashboard() {
  // Header logic
  // Sidebar logic
  // Main content logic
  // Footer logic
}

// After: Multiple focused components
function DashboardHeader() { /* header */ }
function DashboardSidebar() { /* sidebar */ }
function DashboardContent() { /* content */ }
function DashboardFooter() { /* footer */ }

function Dashboard() {
  return (
    <>
      <DashboardHeader />
      <DashboardSidebar />
      <DashboardContent />
      <DashboardFooter />
    </>
  );
}

Recipe 4: Remove Duplication

When: Same code in multiple places

bash
# Find duplicated code patterns
grep -rn "[pattern]" --include="*.ts" --include="*.tsx"
typescript
// Before: Same formatting in 5 files
const formatted = `${data.firstName} ${data.lastName}`;

// After: Single utility function
// utils/formatters.ts
export function formatFullName(data) {
  return `${data.firstName} ${data.lastName}`;
}

// Usage everywhere
import { formatFullName } from '@/utils/formatters';
const formatted = formatFullName(data);

Recipe 5: Simplify Nested Conditionals

When: Deeply nested if/else (>3 levels)

typescript
// Before
function process(user) {
  if (user) {
    if (user.isActive) {
      if (user.hasPermission) {
        // actual logic
      } else {
        throw new Error('No permission');
      }
    } else {
      throw new Error('Inactive user');
    }
  } else {
    throw new Error('No user');
  }
}

// After: Guard clauses
function process(user) {
  if (!user) throw new Error('No user');
  if (!user.isActive) throw new Error('Inactive user');
  if (!user.hasPermission) throw new Error('No permission');
  
  // actual logic (now at top level)
}

Recipe 6: Rename for Clarity

When: Names don't reflect purpose

bash
# Find all usages before renaming
grep -rn "oldName" --include="*.ts" --include="*.tsx"
typescript
// Before
const d = getData();  // What data?
function proc(x) {}   // Process what?

// After
const userProfile = getUserProfile();
function validateUserInput(formData) {}

Phase 5: Verification

Step 5.1: Full Test Suite

bash
# Run complete test suite
npm test

# Type check
npx tsc --noEmit

# Lint
npx eslint [refactored_files]

Step 5.2: Before/After Comparison

code
📊 REFACTORING RESULTS

                    BEFORE      AFTER
Lines of Code:      450         380 (-15%)
Functions:          3           8 (+5)
Max Function Size:  200         45
Cyclomatic Complex: 24          12 (-50%)
Test Coverage:      65%         72% (+7%)

✅ All 47 tests passing
✅ No type errors
✅ No lint errors

Step 5.3: User Verification

Use AskUserQuestion:

code
Refactoring complete. Please verify:
1. Application still works as expected
2. No visual/behavioral changes
3. Code is easier to understand

Is the refactoring successful? (Yes/No/Issues)

Phase 6: Documentation

Step 6.1: Commit Message

code
refactor([scope]): [brief description]

What:
- [Change 1]
- [Change 2]

Why:
- [Reason: readability/performance/maintainability]

Verification:
- All 47 tests passing
- Manual verification complete

Step 6.2: Summary Report

code
♻️ REFACTORING COMPLETE
═══════════════════════════════════════════════════════════

📋 Summary
┌─────────────────────────────────────────────────────────┐
│ Target: [file/function]                                  │
│ Technique: [Extract Function/Component/etc]             │
│ Steps Completed: 5/5                                     │
│ Lines Changed: -70 (+120, -190)                         │
└─────────────────────────────────────────────────────────┘

📁 Changed Files
• [file1.ts] - Extracted 3 functions
• [file2.ts] - Simplified conditionals
• [utils/new.ts] - Created shared utilities

📈 Improvements
• Reduced max function size: 200 → 45 lines
• Eliminated 3 instances of code duplication
• Improved test coverage: 65% → 72%

✅ Verification
• All tests: PASSED
• Type check: PASSED
• Lint: PASSED

➡️ Next Steps
1. Review: git diff main...HEAD
2. Polish: /polish
3. Ship: /ship-it

═══════════════════════════════════════════════════════════

Anti-Patterns (What NOT to Do)

❌ Big Bang Refactoring

Don't try to refactor everything at once. → Small, incremental changes with tests between each.

❌ Refactoring Without Tests

Don't refactor code that isn't covered by tests. → Add tests first, then refactor.

❌ Mixing Refactoring with Features

Don't add new features while refactoring. → Separate commits: refactor first, then add features.

❌ Premature Optimization

Don't refactor for performance without measuring. → Profile first, then optimize the bottleneck.

❌ Over-Abstracting

Don't create abstractions for single-use code. → Extract when you see 3+ duplicates.

Collaboration

  • @tech-lead - Approve large refactoring plans
  • @qa-engineer - Verify test coverage before starting
  • /polish - Clean up after refactoring
  • /record-decision - If refactoring reveals architectural issues
  • /ship-it - Deploy the improved code