1. 一个具体问题
运费规则同时写在网页、后端、客服手册和报表脚本里。一次调价只改了其中三处,于是用户页面展示的金额与账单不同。问题不一定是代码复制太多,而是同一个业务事实有多个独立维护的版本。
2. 一句话解释
DRY 要求一项知识拥有清晰、唯一的权威表达,避免同一规则在不同位置独立维护而逐渐不一致。
3. 出处与原意
Andy Hunt 与 Dave Thomas 在《The Pragmatic Programmer》中提出 DRY,即 Don’t Repeat Yourself。原意面向知识的重复表达,范围包括代码、配置和文档;把它缩成“绝对不能出现相似代码”会丢掉最重要的判断标准。
4. 原理与机制
当一项规则变化时,所有表达都需要同步;副本越多,漏改概率和核验成本越大。共享函数、配置生成、模式定义或自动化文档都可以减少这种同步负担。关键问题是两段逻辑是否因同一个原因而一起变化。如果只是当前长得相似,却分别服务不同业务,将它们强行合并会制造条件分支和耦合。DRY 不要求物理上只有一份数据:缓存与副本可以存在,只要权威来源和更新路径明确。
权威表达也需要清楚的所有权和更新流程。把规则集中到一个共享库,却让所有团队必须同步升级,可能用一致性换来发布阻塞。可采用版本化契约、生成产物与兼容窗口,使知识来源统一而部署保持适当独立。审查时应追问规则变化如何传播、旧版本能存在多久、如何发现不同步,而不是仅检查是否调用了同一个公共函数。
5. 一个完整案例
假设案例:活动报名和商品购买都用“数量乘单价”的代码,开发者准备抽成一个万能结算模块。访谈后发现报名可能有团体名额规则,商品则有库存和运费,两者变化原因不同,于是保留各自计算。真正需要统一的是同一商品运费规则:后端配置成为权威来源,前端通过接口获得展示值,客服说明从配置生成。测试重点验证展示与实际收费相符。团队减少了知识分叉,却没有为了消除几行相似代码而扩大抽象。
6. 适用条件与反例
适合经常联动修改的规则、格式定义和跨系统契约。若抽象的调用方需要大量开关才能使用,应重新检查所谓重复是否真实。过早复用会使本来独立的变化互相影响,短期保留少量相似代码有时能帮助识别正确边界。
7. 今天可以尝试的行动
找一次过去需要同时改三处的需求,问这些位置表达的是不是同一个事实。若是,指定权威来源并建立自动派生或一致性校验;若不是,给各自规则起清楚名字。用“下一次变更要改几处”衡量收益,而不是只统计删掉多少行。