AgentSkillsCN

code-refactoring

当代码存在重复逻辑、函数过长、复杂度过高、存在占位函数,或亟需提升可维护性时——可采用系统化的重构模式,在不改变代码行为的前提下,优化代码结构。

SKILL.md
--- frontmatter
name: code-refactoring
description: Use when code has duplication, long functions, high complexity, placeholder functions, or needs maintainability improvements - systematic refactoring patterns to improve code structure without changing behavior

Code Refactoring

Overview

Systematic refactoring patterns to improve maintainability, reduce complexity, eliminate duplication, and remove technical debt while preserving behavior.

Core principle: Refactor safely with tests first, make incremental changes, verify behavior preserved.

Violating the letter of this process is violating the spirit of refactoring.

When to Use

Use when encountering:

  • Code duplication (DRY violations)
  • Long functions (>50 lines, complex logic)
  • High cyclomatic complexity (nested conditionals, multiple branches)
  • Placeholder functions (pass, raise NotImplementedError, stubs)
  • Magic numbers/strings (unexplained constants)
  • Deep nesting (>3 levels)
  • Large classes (>300 lines, multiple responsibilities)
  • Repeated patterns that could be extracted
  • Technical debt that blocks new features

Don't refactor when:

  • Code works correctly and is rarely touched
  • Refactoring would break critical functionality without tests
  • Time pressure requires shipping features first (document debt, refactor later)

The Iron Law

code
NO REFACTORING WITHOUT TESTS FIRST

If tests don't exist, write them before refactoring. If tests exist but don't cover the code, add coverage first.

Safe Refactoring Workflow

Phase 1: Identify Refactoring Target

  1. Detect Code Smells

    • Long functions (>50 lines)
    • High complexity (cyclomatic complexity >10)
    • Duplication (similar code in 2+ places)
    • Placeholder functions
    • Magic numbers/strings
    • Deep nesting (>3 levels)
  2. Understand Current Behavior

    • Read code carefully
    • Trace execution paths
    • Identify dependencies
    • Document what code does (not how)
  3. Assess Impact

    • What code calls this?
    • What tests exist?
    • What would break if changed?
    • Is refactoring worth the risk?

Phase 2: Write Tests (If Missing)

REQUIRED: If no tests exist for code being refactored:

  1. Write tests that capture current behavior
  2. Run tests to establish baseline
  3. All tests must pass before refactoring
  4. Tests should cover:
    • Happy path
    • Error cases
    • Edge cases
    • Boundary conditions

If tests exist but coverage is low:

  • Add missing test cases
  • Ensure all paths covered
  • Verify tests pass

Phase 3: Refactor Incrementally

One change at a time:

  1. Make smallest possible change

    • Extract one method
    • Rename one variable
    • Extract one constant
    • One change per commit
  2. Run tests after each change

    • All tests must pass
    • If tests fail, revert and try different approach
    • Don't proceed until green
  3. Commit frequently

    • Each successful refactoring step
    • Clear commit message: "refactor: extract method X"
    • Makes rollback easy if needed
  4. Verify behavior unchanged

    • Run full test suite
    • Check integration tests
    • Manual verification if needed

Phase 4: Verify and Document

  1. Run all tests - Must pass
  2. Check code quality - Linter, type checker
  3. Document changes - What was refactored and why
  4. Measure improvement - Complexity reduced, duplication eliminated

Code Smell Detection

Long Functions

Symptom: Function >50 lines or does multiple things

Detection:

python
# Count lines in function
# Check for multiple responsibilities
# Look for "and" in function name (e.g., "process_and_validate")

Refactoring: Extract Method

High Complexity

Symptom: Cyclomatic complexity >10, deeply nested conditionals

Detection:

python
# Count decision points (if, elif, for, while, except)
# Measure nesting depth
# Look for switch-like if/elif chains

Refactoring: Extract Method, Replace Conditional with Polymorphism, Simplify Conditionals

Code Duplication

Symptom: Similar code appears in 2+ places

Detection:

python
# Search for similar code blocks
# Look for copy-paste patterns
# Identify repeated logic

Refactoring: Extract Method, Extract Class, Pull Up Method

Placeholder Functions

Symptom: Functions with pass, raise NotImplementedError, or stub implementations

Detection:

python
def action_comment(...):
    pass  # Placeholder

def verify_signature(...):
    raise NotImplementedError  # Stub

Refactoring: Implement functionality or remove if unused (YAGNI)

Magic Numbers/Strings

Symptom: Unexplained constants in code

Detection:

python
if status == 200:  # What is 200?
if retry_count < 3:  # Why 3?

Refactoring: Extract Constant, Replace Magic Number with Named Constant

Deep Nesting

Symptom: >3 levels of indentation

Detection:

python
if condition1:
    if condition2:
        if condition3:
            if condition4:  # Too deep
                do_something()

Refactoring: Extract Method, Early Return, Guard Clauses

Large Classes

Symptom: Class >300 lines, multiple responsibilities

Detection:

python
# Count lines in class
# Check for multiple "and" in class name
# Look for methods that don't use self

Refactoring: Extract Class, Extract Subclass, Replace Inheritance with Delegation

Refactoring Catalog

Extract Method

When: Long function, duplicated code, complex logic

Process:

  1. Identify code block to extract
  2. Create new method with descriptive name
  3. Move code to new method
  4. Replace original with method call
  5. Pass necessary parameters
  6. Return result if needed
  7. Run tests

Example:

python
# Before
def process_order(order):
    # Validate
    if not order.items:
        raise ValueError("Order must have items")
    if order.total < 0:
        raise ValueError("Total must be positive")

    # Process payment
    charge = order.total * 1.1  # Tax
    payment.process(charge)

    # Send confirmation
    email.send(order.customer, "Order confirmed")

# After
def process_order(order):
    validate_order(order)
    process_payment(order)
    send_confirmation(order)

def validate_order(order):
    if not order.items:
        raise ValueError("Order must have items")
    if order.total < 0:
        raise ValueError("Total must be positive")

def process_payment(order):
    charge = order.total * 1.1
    payment.process(charge)

def send_confirmation(order):
    email.send(order.customer, "Order confirmed")

Extract Class

When: Class has multiple responsibilities, large class, related data/behavior together

Process:

  1. Identify cohesive group of data/behavior
  2. Create new class
  3. Move fields and methods to new class
  4. Create instance in original class
  5. Delegate calls to new class
  6. Run tests

Example:

python
# Before
class TaskWorker:
    def __init__(self):
        self.ws_hub = ws_hub
        self.running = False
        self.semaphore = asyncio.Semaphore(10)
        self.active_tasks = set()
        # ... 1000+ lines

# After
class TaskWorker:
    def __init__(self):
        self.ws_hub = ws_hub
        self.concurrency = ConcurrencyManager(max_tasks=10)
        self.task_processor = TaskProcessor(self.ws_hub)

class ConcurrencyManager:
    def __init__(self, max_tasks):
        self.semaphore = asyncio.Semaphore(max_tasks)
        self.active_tasks = set()

    async def acquire(self):
        return await self.semaphore.acquire()

    def release(self):
        self.semaphore.release()

Eliminate Duplication

When: Same code appears in multiple places

Process:

  1. Identify duplicated code
  2. Find differences (parameters, context)
  3. Extract common code to method/class
  4. Parameterize differences
  5. Replace all occurrences
  6. Run tests

Example:

python
# Before
def process_github_webhook(payload):
    signature = payload.get("signature", "")
    if signature.startswith("sha256="):
        signature = signature[7:]
    # ... verify

def process_jira_webhook(payload):
    signature = payload.get("signature", "")
    if signature.startswith("sha256="):
        signature = signature[7:]
    # ... verify

# After
def normalize_signature(signature: str) -> str:
    if signature.startswith("sha256="):
        return signature[7:]
    return signature

def process_github_webhook(payload):
    signature = normalize_signature(payload.get("signature", ""))
    # ... verify

def process_jira_webhook(payload):
    signature = normalize_signature(payload.get("signature", ""))
    # ... verify

Replace Placeholder

When: Function has pass, raise NotImplementedError, or stub

Process:

  1. Understand what function should do
  2. Check if function is actually called (YAGNI check)
  3. If unused: Remove function and calls
  4. If used: Implement functionality
  5. Write tests for implementation
  6. Run tests

Example:

python
# Before
async def action_comment(provider: str, comment: str):
    pass  # Placeholder

# After
async def action_comment(provider: str, comment: str):
    if provider == "github":
        await github_client.post_comment(comment)
    elif provider == "jira":
        await jira_client.post_comment(comment)
    elif provider == "slack":
        await slack_client.post_message(comment)
    else:
        raise ValueError(f"Unknown provider: {provider}")

Reduce Complexity

When: High cyclomatic complexity, deeply nested conditionals

Process:

  1. Identify complex conditional logic
  2. Extract conditions to methods with descriptive names
  3. Use early returns/guard clauses
  4. Replace nested ifs with flat structure
  5. Consider polymorphism for type-based conditionals
  6. Run tests

Example:

python
# Before
def process_task(task):
    if task:
        if task.status == "pending":
            if task.priority == "high":
                if task.assigned_to:
                    execute_task(task)
                else:
                    assign_task(task)
            else:
                queue_task(task)
        else:
            log_skipped(task)

# After
def process_task(task):
    if not task:
        return

    if task.status != "pending":
        log_skipped(task)
        return

    if not task.assigned_to:
        assign_task(task)
        return

    if task.priority == "high":
        execute_task(task)
    else:
        queue_task(task)

Extract Constant

When: Magic numbers/strings in code

Process:

  1. Identify magic number/string
  2. Create constant with descriptive name
  3. Replace all occurrences
  4. Add comment explaining value if needed
  5. Run tests

Example:

python
# Before
if status_code == 200:
    process_success()
elif status_code == 401:
    handle_unauthorized()
elif status_code == 404:
    handle_not_found()

# After
HTTP_OK = 200
HTTP_UNAUTHORIZED = 401
HTTP_NOT_FOUND = 404

if status_code == HTTP_OK:
    process_success()
elif status_code == HTTP_UNAUTHORIZED:
    handle_unauthorized()
elif status_code == HTTP_NOT_FOUND:
    handle_not_found()

Consolidate Error Handling

When: Error handling duplicated, inconsistent error messages

Process:

  1. Identify error handling patterns
  2. Create centralized error handler
  3. Define error codes/messages
  4. Replace scattered error handling
  5. Run tests

Example:

python
# Before
if not user:
    raise ValueError("User not found")
if not order:
    raise ValueError("Order not found")
if not payment:
    raise ValueError("Payment not found")

# After
class ErrorCodes:
    USER_NOT_FOUND = "USER_NOT_FOUND"
    ORDER_NOT_FOUND = "ORDER_NOT_FOUND"
    PAYMENT_NOT_FOUND = "PAYMENT_NOT_FOUND"

def raise_not_found(resource: str, identifier: str):
    code = getattr(ErrorCodes, f"{resource.upper()}_NOT_FOUND")
    raise NotFoundError(code, f"{resource} not found: {identifier}")

if not user:
    raise_not_found("user", user_id)

Red Flags - STOP and Reassess

  • Refactoring without tests
  • Multiple changes in one commit
  • Tests failing after refactoring
  • Changing behavior while refactoring
  • Refactoring under time pressure without tests
  • Large refactoring without incremental steps
  • No way to verify behavior preserved

Common Mistakes

MistakeFix
Refactor without testsWrite tests first, establish baseline
Change behaviorRefactor = same behavior, better structure
Too many changes at onceOne change per commit, test after each
Ignoring failing testsFix tests or revert refactoring
Not understanding codeRead and trace execution first
Breaking dependenciesMap dependencies before refactoring

Integration with TDD

REQUIRED: Use testing skill before refactoring:

  1. If tests exist: Run them, ensure all pass
  2. If tests missing: Write tests using TDD workflow
  3. Refactor incrementally
  4. Run tests after each change
  5. All tests must pass before proceeding

Refactoring is part of TDD REFACTOR phase - improve code structure while keeping tests green.

Real-World Impact

From refactoring sessions:

  • Reduced task_worker.py from 1043 to 400 lines (extract classes)
  • Eliminated 200+ lines of duplication (extract methods)
  • Reduced complexity from 25 to 8 (extract methods, early returns)
  • Removed 5 placeholder functions (implemented or removed)
  • Improved testability (smaller functions, clearer dependencies)

Quick Reference

SmellDetectionRefactoring
Long function>50 linesExtract Method
High complexity>10 decision pointsExtract Method, Simplify Conditionals
DuplicationSame code 2+ placesExtract Method, Extract Class
Placeholderpass, NotImplementedErrorImplement or Remove
Magic numbersUnexplained constantsExtract Constant
Deep nesting>3 levelsExtract Method, Early Return
Large class>300 linesExtract Class

The Bottom Line

Refactoring improves code without changing behavior.

Tests first. Incremental changes. Verify after each step. Preserve behavior always.