关于 dont-repeat-yourself
dont-repeat-yourself 是一项面向开发者的编码技能,指导将每段逻辑或知识集中在一个位置。它着重识别复制粘贴模式,并通过参数化差异来提取共用代码。
主要功能
- 01识别重复代码和逻辑
- 02提取共用函数与验证器
- 03参数化相似代码中的差异
- 04集中管理重复常量和规则
- 05利用重复迹象指导重构
适用场景
- 01避免为新功能复制现有代码
- 02合并多个表单中的重复验证
- 03修复分散在多个文件中的计算逻辑
- 04重构略有差异的相似函数
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ yanko-belov/ code-craft --skill dont-repeat-yourself安装后在 Claude Code 中输入/dont-repeat-yourself确认已加载。
详细介绍
DRY(不要重复自己)
概述
系统中的每一条知识都必须只有一种明确无歧义的表示方式。
如果你发现自己要把同一段逻辑写两遍,就把它提取出来。重复代码是随时可能引发问题的隐患。
适用场景
- 编写与现有代码相似的代码
- 复制粘贴后再修改
- 在多个文件中进行相同的修改
- 在多个表单中重复编写验证逻辑
- 在不同位置进行相同的计算
铁律
NEVER duplicate logic. Extract and reuse.
没有例外:
- 不能因为“复制更快”而例外
- 不能因为“它们有一点不同”而例外
- 不能因为“我之后会重构”而例外
- 不能因为“只有几行”而例外
检测:复制粘贴的异味
如果你正准备复制并修改代码,请停下来:
// ❌ VIOLATION: Duplicated validation
function validateRegistrationEmail(email: string): boolean {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
function validateProfileEmail(email: string): boolean {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); // Same logic!
}
// ✅ CORRECT: Single source of truth
function validateEmail(email: string): boolean {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
// Reuse everywhere
const isValidRegistration = validateEmail(regEmail);
const isValidProfile = validateEmail(profileEmail);
检测:“需要在多个地方修改”测试
如果修复一个错误需要修改多个位置,那就说明存在重复:
// ❌ Bug in tax calculation requires changes in 3 files
// cart.ts: const tax = price * 0.08;
// checkout.ts: const tax = price * 0.08;
// invoice.ts: const tax = price * 0.08;
// ✅ Single source of truth
// tax.ts: export const calculateTax = (price: number) => price * TAX_RATE;
正确做法:提取并参数化
当代码“几乎相同”时,提取共同部分,并将差异参数化:
// ❌ VIOLATION: Similar functions with minor differences
function formatUserName(user: User): string {
return `${user.firstName} ${user.lastName}`;
}
function formatAdminName(admin: Admin): string {
return `${admin.firstName} ${admin.lastName} (Admin)`;
}
// ✅ CORRECT: Parameterized
function formatName(person: { firstName: string; lastName: string }, suffix?: string): string {
const name = `${person.firstName} ${person.lastName}`;
return suffix ? `${name} (${suffix})` : name;
}
抵御压力的应对方案
1. “复制更快”
压力:“我就复制这段代码,再改一改”
**回应:**复制会产生两个需要维护的地方。两处代码会逐渐产生差异,进而引发错误。
**行动:**先提取共享逻辑,再在两个地方使用它。
2. “它们有一点不同”
压力:“这些函数几乎一样,但又不完全相同”
回应:“几乎相同”=提取共同部分,并将差异参数化。
**行动:**找出共用部分,将其提取出来,并把差异设为参数。
3. “只有几行”
压力:“只有 3 行,不值得提取”
**回应:**重复 5 次的 3 行代码=15 行需要维护。错误也会不断增加。
**行动:**即使只有少量重复,也要提取出来,并起个好名字。
4. “我之后会重构”
压力:“先发布,之后再整理成 DRY”
**回应:**你不会这么做。重复会不断蔓延。现在整理成 DRY 只需 2 分钟。
**行动:**在提交重复代码之前先提取。
危险信号——停下来重新考虑
如果你注意到以下任意情况,就说明你即将违反 DRY:
- 工作流中出现 Ctrl+C / Ctrl+V
- “这个和那个函数很像”
- 多处出现相同的正则表达式或验证逻辑
- 重复出现相同的错误处理模式
- 重复相同的数据转换逻辑
- 在多个文件中定义常量
以上情况都意味着:提取到共享位置。
重复的类型
| 类型 | 示例 | 解决方案 |
|---|---|---|
| 代码 | 相同的函数体出现两次 | 提取函数 |
| 逻辑 | 相同的算法,不同的名称 | 提取并参数化 |
| 数据 | 多个文件中出现相同的常量 | 将常量集中管理 |
| 结构 | 重复出现相同形态的类 | 提取接口或基类 |
| 知识 | 多处出现业务规则 | 建立唯一可信来源 |
快速参考
| 症状 | 行动 |
|---|---|
| 复制粘贴代码 | 提取共享函数 |
| 相同的验证逻辑出现两次 | 创建验证器模块 |
| 多个文件中出现相同的常量 | 创建常量文件 |
| 相似的函数 | 提取并参数化 |
| 修复错误需要多处修改 | 合并到一个位置 |
常见的自我辩解(均不成立)
| 借口 | 事实 |
|---|---|
| “复制更快” | 维护重复代码更慢。 |
| “它们有一点不同” | 提取共同部分,并将差异参数化。 |
| “只有几行” | 几行代码 × 多个位置=许多错误。 |
| “我之后会重构” | 你不会这么做。现在就提取。 |
| “上下文不同” | 逻辑相同,代码就应相同,与上下文无关。 |
| “复制出来更易读” | 命名并提取后的函数更易读。 |
归根结底
一条知识。在代码中只出现一个地方。
编写相似代码时:停下来,查找已有代码,必要时提取并复用。重复是维护噩梦的根源。
评论
支持 Markdown