代码重构 code-refactoring

代码重构是一种软件工程技术,用于改进现有代码的结构和质量,而不改变其外部行为。关键技术包括提取方法、替换条件语句、引入参数对象等,旨在提高代码的可读性、可维护性和可扩展性。适用于清理遗留代码、降低复杂性和提升开发效率。关键词:代码重构、软件工程、代码质量、可维护性、重构技巧。

架构设计 0 次安装 0 次浏览 更新于 3/8/2026

name: 代码重构 description: 用于提高代码质量而不改变行为的代码重构模式和技巧。用于清理遗留代码、减少复杂性或提高可维护性。 source: wshobson/agents license: MIT

代码重构

重构原则

何时重构

  • 在添加新功能之前(使更改变得容易,然后进行简单更改)
  • 测试通过后(红绿重构)
  • 当看到代码异味时
  • 代码审查反馈期间

何时不重构

  • 没有测试覆盖的代码
  • 在紧迫的截止日期下没有安全网
  • 即将被替换的代码
  • 当不理解代码作用时

常见代码异味

长方法

// 之前:方法做太多事情
function processOrder(order: Order) {
  // 100行验证、计算、通知、日志记录...
}

// 之后:提取到专注的方法
function processOrder(order: Order) {
  validateOrder(order);
  const total = calculateTotal(order);
  saveOrder(order, total);
  notifyCustomer(order);
}

深层嵌套条件语句

// 之前:箭头代码
function getDiscount(user: User, order: Order) {
  if (user) {
    if (user.isPremium) {
      if (order.total > 100) {
        if (order.items.length > 5) {
          return 0.2;
        }
      }
    }
  }
  return 0;
}

// 之后:早期返回(守卫子句)
function getDiscount(user: User, order: Order) {
  if (!user) return 0;
  if (!user.isPremium) return 0;
  if (order.total <= 100) return 0;
  if (order.items.length <= 5) return 0;
  return 0.2;
}

原始类型迷恋

// 之前:到处都是原始类型
function createUser(name: string, email: string, phone: string) {
  if (!email.includes('@')) throw new Error('Invalid email');
  // 更多验证...
}

// 之后:值对象
class Email {
  constructor(private value: string) {
    if (!value.includes('@')) throw new Error('Invalid email');
  }
  toString() { return this.value; }
}

function createUser(name: string, email: Email, phone: Phone) {
  // 电子邮件已经验证
}

特性嫉妒

// 之前:方法大量使用另一个对象的数据
function calculateShipping(order: Order) {
  const address = order.customer.address;
  const weight = order.items.reduce((sum, i) => sum + i.weight, 0);
  const distance = calculateDistance(address.zip);
  return weight * distance * 0.01;
}

// 之后:将方法移到数据所在处
class Order {
  calculateShipping() {
    return this.totalWeight * this.customer.shippingDistance * 0.01;
  }
}

重构技巧

提取方法

// 识别一个代码块做一件事情
// 将其移动到一个新方法,使用描述性名称
// 用方法调用替换原始代码

function printReport(data: ReportData) {
  // 提取这个块...
  const header = `Report: ${data.title}
Date: ${data.date}
${'='.repeat(40)}`;
  console.log(header);

  // ...到一个方法
  printHeader(data);
}

用多态替换条件语句

// 之前:基于类型切换
function getArea(shape: Shape) {
  switch (shape.type) {
    case 'circle': return Math.PI * shape.radius ** 2;
    case 'rectangle': return shape.width * shape.height;
    case 'triangle': return shape.base * shape.height / 2;
  }
}

// 之后:多态类
interface Shape {
  getArea(): number;
}

class Circle implements Shape {
  constructor(private radius: number) {}
  getArea() { return Math.PI * this.radius ** 2; }
}

class Rectangle implements Shape {
  constructor(private width: number, private height: number) {}
  getArea() { return this.width * this.height; }
}

引入参数对象

// 之前:太多参数
function searchProducts(
  query: string,
  minPrice: number,
  maxPrice: number,
  category: string,
  inStock: boolean,
  sortBy: string,
  sortOrder: string
) { ... }

// 之后:参数对象
interface SearchParams {
  query: string;
  priceRange: { min: number; max: number };
  category?: string;
  inStock?: boolean;
  sort?: { by: string; order: 'asc' | 'desc' };
}

function searchProducts(params: SearchParams) { ... }

用常量替换魔法数字

// 之前
if (user.age >= 18 && order.total >= 50) {
  applyDiscount(order, 0.1);
}

// 之后
const MINIMUM_AGE = 18;
const DISCOUNT_THRESHOLD = 50;
const STANDARD_DISCOUNT = 0.1;

if (user.age >= MINIMUM_AGE && order.total >= DISCOUNT_THRESHOLD) {
  applyDiscount(order, STANDARD_DISCOUNT);
}

安全重构过程

  1. 确保测试存在 - 如果不存在,编写测试
  2. 进行小更改 - 一次一个重构
  3. 每次更改后运行测试 - 立即捕捉回归
  4. 频繁提交 - 如果出现问题,易于回退
  5. 审查差异 - 确保行为未改变

重构检查清单

  • [ ] 开始前测试通过
  • [ ] 每个更改小而专注
  • [ ] 每次更改后测试通过
  • [ ] 没有行为更改(仅结构)
  • [ ] 代码比之前更可读
  • [ ] 提交消息解释重构