类别: 原则
类型: 软件开发原则
起源: 软件工程,1990年代 / 《程序员 pragmatics》,1999
别名: DRY、不要重复自己、单点真实来源
类型: 软件开发原则
起源: 软件工程,1990年代 / 《程序员 pragmatics》,1999
别名: DRY、不要重复自己、单点真实来源
快速回答 — DRY原则(Don’t Repeat Yourself)指出,每一条知识在一个系统中必须只有一种明确的表现形式。该原则首次在安迪·亨特(Andy Hunt)和戴夫·托马斯(Dave Thomas)1999年出版的《程序员 pragmatics》中阐述,已成为软件开发中最有影响力的原则之一。该原则不仅适用于代码,还包括文档、数据库模式、测试和任何其他系统工件。当信息被重复时,修改需要在多个地方进行,增加了一致性问题和错误的风险。
什么是DRY原则?
DRY原则是一种软件开发哲学,主张消除代码、文档和其他系统工件中的重复。其核心思想看似简单却非常有力量:任何知识片段——无论是业务规则、计算、数据结构还是用户界面元素——都应该只存在于一个地方。当相同的信息出现在多个地方时,开发者必须记住更新每个实例,造成持续的维护负担,并引入错误的机会。“重复是设计良好系统的主要敌人。” — 安迪·亨特和戴夫·托马斯,《程序员 pragmatics》该原则通过《程序员 pragmatics:从小工到专家》(1999年)获得了广泛认可,这本有影响力的书籍确立了软件开发的许多最佳实践。然而,这个underlying idea早在这本书之前——程序员早就认识到复制逻辑会造成维护噩梦。亨特和托马斯所做的是清晰地阐述了这个原则,并给了它一个令人难忘的名字。 DRY适用于多种形式的重复。代码重复发生在相同逻辑出现在多个地方时。文档重复发生在同一信息在多个文档中被解释时。数据重复发生在相同数据存储在多个位置时。模式重复产生于数据库结构相互镜像时。该原则要求开发者为每条知识确定单一权威来源,并构建引用该来源的系统。
DRY原则的三层理解
- 入门: 在复制粘贴代码时,停下来问:“我可以将其提取为一个可重用的函数或变量吗?“即使是小规模的重复也会随着时间累积。
- 实践: 在多个层面应用DRY——函数、类、模块和服务。使用继承、组合和配置管理等技术来集中知识。
- 进阶: 认识到过度积极的DRY会产生不当的耦合。有时重复比错误的抽象更可取。平衡DRY与YAGNI和KISS原则。
起源
DRY原则在安迪·亨特和戴夫·托马斯1999年出版的《程序员 pragmatics:从小工到专家》中正式介绍。这本成为软件开发文献基石的书籍将DRY描述为构建可维护软件的核心原则。亨特和托马斯认为,重复导致系统更难理解、修改和扩展。 该原则建立在软件工程的早期 ideas 之上。数据库设计中”单点真实来源”的概念早于DRY,像在一个地方定义常量并在整个代码中引用它们的做法也是如此。DRY具有影响力的原因是它在所有知识重复形式中的广泛应用,不仅在代码中,还包括文档、流程和组织结构。 DRY流行的时机意义重大。1990年代后期见证了大型软件系统的增长,开发者越来越面临重复代码库的维护挑战。DRY为做出设计决策提供了清晰的启发式方法,这些决策将在系统的整个生命周期中受益。今天,DRY仍然是计算机科学课程和专业开发团队遵循的基础原则。核心要点
应用场景
代码重构
将重复的逻辑提取到可重用的函数、类或模块中。使用继承或组合来共享行为而不重复实现。
配置管理
将配置值存储在集中式文件或环境变量中。避免硬编码可能在不同环境中更改的值。
数据库设计
规范化数据库模式以消除冗余数据存储。使用外键和连接,而不是在表之间复制数据。
文档编写
编写一次解释概念并在整个过程中引用该说明的文档。避免在多个地方重复相同的信息。
经典案例
Ruby on Rails 框架 famously 体现了DRY原则。Rails 引入了”约定优于配置”的概念,通用模式被定义一次并自动应用于整个应用程序。例如,Rails 中的模型定义自动生成数据库访问方法——相同的逻辑不会在多个地方重复。当 Rails 开发者需要更改模型与数据库的交互方式时,他们在一个地方进行更改,它会传播到整个应用程序。这种方法使 Rails 应用程序的维护和修改变得非常容易,开发者报告称,与不太强调 DRY 的框架相比,重复代码明显更少。边界与失效场景
DRY原则虽然至关重要,但有重要的局限性。首先,过度热情的DRY会产生不当的抽象。将不相关的概念强制放入共享代码会造成紧密耦合,使原始代码和”重构”版本都更难维护。 其次,过早的抽象是有风险的。DRY应该指导已证实重复的重构,而不是启发投机性泛化。为可能有一天会被重用的代码创建抽象通常会导致复杂、难于理解的系统。 第三,有些重复是可以接受的——甚至是必要的。看起来相似的代码可能有不同的存在原因,强制它们在一起会造成虚假的统一性。测试代码经常因为正当理由从生产代码中复制结构:测试必须能够独立维护。常见误区
DRY意味着永远不复制代码
DRY意味着永远不复制代码
DRY是关于避免知识重复,而不是字面上的代码。有时最清晰的解决方案涉及重复语法,而底层知识保持单一来源。
DRY总是提高可维护性
DRY总是提高可维护性
错误的抽象会使维护变得更难。在提取重复之前,确保抽象准确地代表共享概念。
DRY只适用于代码
DRY只适用于代码
该原则扩展到文档、数据库模式、API 设计和组织流程。任何重复的知识都是 DRY 处理的候选对象。
相关概念
KISS原则
DRY 通常简化代码,使其更容易理解。KISS 通过强调简单性来补充 DRY,指导如何消除重复。
YAGNI原则
不要构建可重用的组件,直到你需要它们。YAGNI 防止违反 DRY 精神的过早抽象。
单点真实来源
一个相关的数据库概念,数据应该存储在一个地方。DRY 是将这个想法应用到系统中所有知识的方式。
代码重构
改进代码结构的实践,通常通过应用 DRY。重构是实现 DRY 的操作活动。
奥卡姆剃刀
两个原则都偏向简单性。DRY 消除重复,而奥卡姆剃刀消除不必要的假设。