mcpField
D
dry

dry

github.com/jordancoin开发1184 次安装35 周前更新
代码仓库

关于 dry

dry 是一项指导编码 Agent 应用 DRY 原则的技能,强调消除重复知识而非相似代码,并兼顾 KISS、YAGNI 等边界。适用于代码实现与审查。

主要功能

  1. 01区分知识重复与代码相似
  2. 02集中配置、规则与数据来源
  3. 03在模式稳定后提取抽象
  4. 04通过代码生成保持表示同步
  5. 05提供代码审查检查清单

适用场景

  1. 01合并重复的业务规则
  2. 02检查配置与常量是否重复
  3. 03评估抽象是否过早或过度
  4. 04减少修改规则时涉及的文件数

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jordancoin/codingskills --skill dry

安装后在 Claude Code 中输入/dry确认已加载。

详细介绍

DRY — 不要重复自己

应用前

如果 .agents/stack-context.md 存在,请先阅读。根据检测到的技术栈,使用符合其惯用风格的模式来应用此原则。对于框架特定的细节,请使用 context7 MCP 或网络搜索,不要猜测。

原则

系统中的每一项知识都应有唯一且权威的表示。当这项知识发生变化时,你只需在一个地方修改。

为什么这在生产环境中很重要

重复的逻辑是一颗定时炸弹。当业务规则发生变化,而你只在一个地方更新、却漏掉另一处副本时,就会出现难以察觉、也更难调试的不一致行为。副本越多,其中一份悄然偏离的可能性就越大。

DRY 不是为了消除看起来相似的代码,而是为了消除重复的知识——也就是在多个地方表达同一条业务规则、同一个决策或同一个事实来源。

规则

  1. 区分知识重复与代码重复。 两个看起来相同、但代表不同业务概念的函数应该保持独立。编码了同一条业务规则的两个函数则应该合并。
  2. 数据应有唯一事实来源。 配置、常量、模式定义和验证规则都应各自只存在于一个地方。其他所有内容都应由该来源派生。
  3. 模式稳定后再提取。 不要在模式第一次出现时就提取——此时你还不知道抽象应采用什么形式。只有在至少两次看到语义相同的重复模式后,才进行提取。
  4. 集中管理业务规则。 税费计算、权限检查、定价逻辑都必须放在同一个模块中,而不是散布在处理器、前端和脚本里。
  5. 优先使用代码生成,而不是手动同步。 如果两种表示必须保持同步(例如,API 类型和客户端类型、模式和文档),就从一种生成另一种,而不是手动维护两者。

反模式

  • 牵一发而动全身: 修改一条业务规则需要编辑 5 个以上文件,因为这条规则到处都有重复
  • 复制-粘贴-修改: 克隆一个函数并稍作调整,而不是为原函数增加参数
  • 平行层级结构: 在多个层中维护相互匹配的结构(例如,后端和前端中相同的类型定义,却不是从共享模式生成的)
  • 在多个文件中重复使用魔法字符串: 同一个状态码、错误消息或配置键被硬编码在多个位置
  • 重复描述代码的文档: 注释或文档重复说明代码已经表达的内容(并不可避免地逐渐与代码脱节)

错误的 DRY 做法

-- Code looks similar but represents different concepts — DO NOT unify
def calculate_shipping_cost(weight, distance):
    return weight * 0.5 + distance * 0.1

def calculate_insurance_premium(value, risk_factor):
    return value * 0.5 + risk_factor * 0.1

-- These are different business rules that happen to share a formula today.
-- They will diverge. Keep them separate.

正确的 DRY 做法

-- Same validation rule duplicated — UNIFY
// in signup handler
if len(password) < 8 or not has_uppercase(password):
    return error("Password too weak")

// in password-reset handler
if len(new_password) < 8 or not has_uppercase(new_password):
    return error("Password too weak")

-- Fix: single source of truth
def validate_password(password):
    if len(password) < 8:
        return error("Password must be at least 8 characters")
    if not has_uppercase(password):
        return error("Password must contain an uppercase letter")
    return ok()

边界

  • DRY 关注的是知识,而不是语法。 两段看起来相同的代码可能代表不同的事物。不要仅仅因为它们看起来相同就将其合并。
  • 过早追求 DRY 会产生错误的抽象。 糟糕的抽象比重复更糟,因为它更难撤销。提取前先等到你理解了这个模式。
  • 与 KISS 的张力: 过于激进的 DRY 重构可能会引入多层间接结构,比原来的重复更难理解。如果共享函数需要 5 个参数和 3 个布尔标志才能处理所有情况,那么重复反而更简单。
  • 与 YAGNI 的张力: 不要「因为以后可能会在别处用到」就构建通用工具。只有在存在具体的重复内容时才进行提取。
  • 跨边界 DRY 的代价很高。 在服务、仓库或团队之间共享代码会带来耦合。有时,跨边界重复比使用会阻碍独立部署的共享库更健康。

代码审查清单

  • 这项更改是否引入了其他地方已有的重复业务逻辑?
  • 是否存在应该定义为常量的魔法字符串或数字?
  • 如果这条业务规则发生变化,需要更新多少个文件?
  • 是否有共享抽象被迫同时满足过多需求?(错误地应用 DRY)
  • 是否存在可以通过生成来实现同步的并行表示,却需要手动同步?

相关技能

  • yagni:决定是否提取时(等到出现 3 次)
  • kiss:当 DRY 抽象比重复代码更难理解时
  • convention-over-configuration:用于消除重复的配置模式

评论

支持 Markdown