AgentSkillsCN

refactor-patterns

提供代码重构模式与最佳实践,助力打造更整洁、更易维护的代码。适用场景包括:(1) 改善现有代码结构;(2) 应用设计模式;(3) 降低代码复杂度或减少重复代码;(4) 对遗留代码进行现代化改造。触发词:「重构这段代码」、「优化这段代码」、「清理代码」、「简化代码」、「代码过于复杂」、「设计模式」、「SOLID 原则」、「代码异味」、「技术债务」。

SKILL.md
--- frontmatter
name: refactor-patterns
description: >
  Code refactoring patterns and best practices for cleaner, maintainable code.
  Use when: (1) improving existing code structure, (2) applying design patterns,
  (3) reducing code complexity or duplication, (4) modernizing legacy code.
  Triggers: "refactor this", "improve this code", "clean up", "simplify",
  "too complex", "design pattern", "SOLID", "code smell", "tech debt".

Refactoring Patterns

Common refactoring techniques and design patterns for improving code quality.

Code Smells & Solutions

1. Long Functions

Smell: Function > 20-30 lines Solution: Extract Method

python
# Before
def process_order(order):
    # validate
    if not order.items:
        raise ValueError("Empty order")
    if not order.customer:
        raise ValueError("No customer")
    # calculate total
    subtotal = sum(item.price * item.qty for item in order.items)
    tax = subtotal * 0.1
    total = subtotal + tax
    # save
    db.save(order)
    return total

# After
def process_order(order):
    validate_order(order)
    total = calculate_total(order)
    save_order(order)
    return total

def validate_order(order):
    if not order.items:
        raise ValueError("Empty order")
    if not order.customer:
        raise ValueError("No customer")

def calculate_total(order):
    subtotal = sum(item.price * item.qty for item in order.items)
    tax = subtotal * 0.1
    return subtotal + tax

2. Duplicated Code

Smell: Same logic in multiple places Solution: Extract and Reuse

typescript
// Before
function getAdminUsers() {
  return users.filter(u => u.active && u.role === 'admin');
}
function getActiveUsers() {
  return users.filter(u => u.active);
}

// After
const isActive = (u: User) => u.active;
const isAdmin = (u: User) => u.role === 'admin';

const getActiveUsers = () => users.filter(isActive);
const getAdminUsers = () => users.filter(u => isActive(u) && isAdmin(u));

3. Primitive Obsession

Smell: Using primitives for domain concepts Solution: Create Value Objects

python
# Before
def create_user(email: str, phone: str):
    if '@' not in email:
        raise ValueError("Invalid email")
    # email used everywhere as string

# After
@dataclass
class Email:
    value: str

    def __post_init__(self):
        if '@' not in self.value:
            raise ValueError("Invalid email")

def create_user(email: Email, phone: Phone):
    # type-safe, self-validating

4. Feature Envy

Smell: Method uses data from another class excessively Solution: Move Method

javascript
// Before
class Order {
  getDiscountedPrice(customer) {
    if (customer.loyaltyPoints > 100) {
      return this.price * 0.9;
    }
    if (customer.memberSince < lastYear) {
      return this.price * 0.95;
    }
    return this.price;
  }
}

// After
class Customer {
  getDiscount() {
    if (this.loyaltyPoints > 100) return 0.1;
    if (this.memberSince < lastYear) return 0.05;
    return 0;
  }
}

class Order {
  getDiscountedPrice(customer) {
    return this.price * (1 - customer.getDiscount());
  }
}

5. Switch Statements

Smell: Long switch/if-else chains Solution: Polymorphism or Strategy Pattern

typescript
// Before
function calculatePay(employee) {
  switch (employee.type) {
    case 'hourly':
      return employee.hours * employee.rate;
    case 'salaried':
      return employee.salary / 12;
    case 'commission':
      return employee.sales * employee.commissionRate;
  }
}

// After: Strategy Pattern
interface PayStrategy {
  calculate(employee: Employee): number;
}

class HourlyPay implements PayStrategy {
  calculate(e: Employee) { return e.hours * e.rate; }
}

class SalariedPay implements PayStrategy {
  calculate(e: Employee) { return e.salary / 12; }
}

const strategies: Record<string, PayStrategy> = {
  hourly: new HourlyPay(),
  salaried: new SalariedPay(),
};

function calculatePay(employee) {
  return strategies[employee.type].calculate(employee);
}

SOLID Principles

Single Responsibility (S)

One class = one reason to change

Open/Closed (O)

Open for extension, closed for modification

Liskov Substitution (L)

Subtypes must be substitutable for base types

Interface Segregation (I)

Many specific interfaces > one general interface

Dependency Inversion (D)

Depend on abstractions, not concretions

typescript
// Before: depends on concrete class
class OrderService {
  private db = new MySQLDatabase();
}

// After: depends on abstraction
class OrderService {
  constructor(private db: Database) {}
}

Common Refactoring Operations

RefactoringWhen to Use
Extract MethodLong function, reusable logic
Inline MethodMethod body is obvious
Extract VariableComplex expression
RenameUnclear naming
Move Method/FieldFeature envy
Extract ClassClass doing too much
Replace Conditional with PolymorphismComplex type-based logic
Introduce Parameter ObjectMany related parameters
Replace Magic Number with ConstantUnexplained literals

Safe Refactoring Checklist

  1. Tests pass before refactoring
  2. Make small, incremental changes
  3. Run tests after each change
  4. Commit frequently
  5. Review diff before merging
  6. No behavior change (unless intentional)

References