SuperAPI AI 工具集

dont-repeat-yourself

编程与开发

查看项目

更新于 10-16 02:09

技能介绍

概述

DRY(Don't Repeat Yourself)的核心原则是:系统中的每一处知识都必须有唯一、明确的表示。

如果你发现自己把同一段逻辑写了两遍,就把它提取出来。重复是等待发生的 bug。

何时使用

  • 正在编写与已有代码相似的代码
  • 正在复制粘贴并修改
  • 正在多个文件中做同样的修改
  • 校验逻辑在多个表单中重复
  • 相同的计算出现在不同位置

铁律

绝不要重复逻辑。提取并复用。没有例外:

  • 不因为“复制更快”
  • 不因为“它们略有不同”
  • 不因为“我以后再重构”
  • 不因为“就几行而已”

检测:复制粘贴异味

如果你正要复制代码并修改它,停下来:

// ❌ 违规:重复的校验
function validateRegistrationEmail(email: string): boolean {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}

function validateProfileEmail(email: string): boolean {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); // 同样的逻辑!
}

// ✅ 正确:单一事实来源
function validateEmail(email: string): boolean {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}

// 到处复用
const isValidRegistration = validateEmail(regEmail);
const isValidProfile = validateEmail(profileEmail);

检测:“需要改多处”测试

如果修一个 bug 需要改动多个位置,说明存在重复:

// ❌ 税率计算有 bug,需要改 3 个文件
// cart.ts:      const tax = price * 0.08;
// checkout.ts:  const tax = price * 0.08;
// invoice.ts:   const tax = price * 0.08;

// ✅ 单一事实来源
// tax.ts:       export const calculateTax = (price: number) => price * TAX_RATE;

正确模式:提取并参数化

当代码“几乎相同”时,提取公共部分,把差异参数化:

// ❌ 违规:略有差异的相似函数
function formatUserName(user: User): string {
  return `${user.firstName} ${user.lastName}`;
}

function formatAdminName(admin: Admin): string {
  return `${admin.firstName} ${admin.lastName} (Admin)`;
}

// ✅ 正确:参数化
function formatName(person: { firstName: string; lastName: string }, suffix?: string): string {
  const name = `${person.firstName} ${person.lastName}`;
  return suffix ? `${name} (${suffix})` : name;
}

抗压协议

  1. “复制更快”

    • 压力:“我就复制这个改一下”
    • 回应:复制会产生两个需要维护的地方,bug 会分叉。
    • 行动:先提取共享逻辑,再在两处使用。
  2. “它们略有不同”

    • 压力:“这些函数几乎一样但不完全一样”
    • 回应:“几乎一样”=提取公共部分,把差异参数化。
    • 行动:找出共享部分,提取它,把差异变成参数。
  3. “就几行而已”

    • 压力:“只有 3 行,不值得提取”
    • 回应:3 行重复 5 次=15 行要维护,bug 会成倍增加。
    • 行动:即使很小的重复也提取,并给它们起好名字。
  4. “我以后再重构”

    • 压力:“先发布,之后再 DRY”
    • 回应:你不会的。重复会扩散。现在 DRY 只需 2 分钟。
    • 行动:在提交重复之前先提取。

危险信号——停下并重新考虑

如果注意到以下任何一项,你即将违反 DRY:

  • 工作流中使用 Ctrl+C / Ctrl+V
  • “这个和那个函数很像”
  • 同一正则/校验出现在多处
  • 相同的错误处理模式重复出现
  • 相同的数据转换逻辑重复
  • 常量在多个文件中定义

以上所有情况都意味着:提取到共享位置。

重复的类型

类型 示例 解决方案
代码 同一函数体出现两次 提取函数
逻辑 同一算法,不同名称 提取并参数化
数据 同一常量出现在多个文件 集中常量
结构 同一类形状重复 提取接口/基类
知识 业务规则出现在多处 单一事实来源

快速参考

症状 行动
复制粘贴代码 提取共享函数
同一校验出现两次 创建校验器模块
同一常量出现在多个文件 创建常量文件
相似函数 提取+参数化
修 bug 需要改多处 合并到一处

常见借口(全部无效)

借口 现实
“复制更快” 维护重复更慢。
“它们略有不同” 提取公共部分,参数化差异。
“就几行” 几行 × 多处=大量 bug。
“我以后再重构” 你不会的。现在就提取。
“上下文不同” 同一逻辑=同一代码,与上下文无关。
“复制版更易读” 命名并提取后的函数更易读。

底线

一处知识,一处代码。

当你要写相似代码时:停下,找到已有代码,必要时提取,然后复用。重复是维护噩梦的根源。