软件开发准则
在软件开发中,设计原则是指导我们构建软件应用程序的重要准则。
1. SOLID
原则
SOLID是五个设计原则的首字母缩写,分别代表:
单一职责
原则(Single Responsibility Principle):一个类应该只有一个职责,即只做一件事情。- 开闭原则(Open/Closed Principle):软件实体应该对扩展开放,对修改封闭。
- 里氏替换原则(Liskov Substitution Principle):子类必须能够替换其基类而不引发错误。
- 接口隔离原则(Interface Segregation Principle):客户端不应该依赖于它不使用的接口。
依赖反转
原则(Dependency Inversion Principle):高层模块不应该依赖于低层模块,它们都应该依赖于抽象。
2. DRY
原则
- 全称: Don’t Repeat Yourself (不要重复你自己)
- 核心思想: 系统中的每一处知识都必须具有单一、明确、权威的表示。 这远不止是简单的“复制粘贴代码”,它针对的是“知识”和“逻辑”的重复。
- 例子:
- 坏味道: 同一个魔法数字(如
3.14159
)散落在代码的多个地方。 - DRY 做法: 将其定义为常量
const PI = 3.14159;
然后到处引用这个常量。这样,如果需要提高精度,只需修改一个地方。 - 坏味道: 相同的业务规则(如“计算用户折扣”的逻辑)在多个函数或模块中出现。
- DRY 做法: 将这个逻辑抽取到一个独立的函数(如
calculateDiscount(user)
)中,然后所有需要的地方都调用这个函数。
- 坏味道: 同一个魔法数字(如
- 好处:
- 保证一致性: 逻辑只有一份,不会出现不同副本之间行为不一致的情况。
- 易于修改: 修改业务规则只需改动一处。
3. SPOT
原则
- 全称: Single Point Of Truth (单一真相源)
- 核心思想: 对于系统中的任何一份知识(数据或逻辑),都应该只有一个唯一的地方来定义它,而其他地方只是引用它。 它是 DRY 原则的一个更具体、更具指导性的表述,尤其强调数据的权威来源。
- 例子:
- 前端开发: 在 Vue/React 等框架中,组件的状态(State)就是该组件UI的“单一真相源”。UI 应该仅仅是 State 的映射(函数)。当你修改 State 时,UI 会自动更新,而不是直接操作 DOM。
- 配置管理: 所有环境(开发、测试、生产)的配置都应该从一个中心化的配置服务或文件读取,而不是硬编码在多个应用的代码里。
- 数据库: 用户的个人信息只存储在“用户表”中,其他地方通过“用户ID”来引用,而不是复制一份用户信息。
- 与 DRY 的关系: SPOT 是 DRY 在数据和管理层面的具体实践。DRY 是目标(不要重复),SPOT 是实现这个目标的重要方法(指定一个权威来源)。
4. KISS:
- 全称: Keep It Simple, Stupid (保持简单和直接)
- 核心思想: 设计要尽可能简单,避免不必要的复杂性。简单的系统更易理解、更可靠、更易维护。不要过度设计。
5. YAGNI:
- 全称: You Ain’t Gonna Need It (你不会需要它)
- 核心思想: 只在真正需要的时候才实现功能,不要因为“将来可能有用”就去编写额外的代码。这是极限编程(XP)的核心实践,旨在避免过度设计和开发浪费。
6. SoC:
- 全称: Separation of Concerns (关注点分离)
- 核心思想: 将一个程序分解为多个不同的、功能重叠尽可能少的模块。一个模块只负责一个特定的功能或“关注点”。这是实现正交性和模块化的主要手段。MVC(Model-View-Controller)架构就是 SoC 的经典体现。
7. Law of Demeter (LoD) / 最小知识原则:
- 核心思想: 一个对象应该对其他对象有最少的了解。它只应该与它的“朋友”(直接的朋友:成员变量、方法参数、自身创建的对象)交谈,而不与“朋友的朋友”交谈。
- 比喻: 你让你的狗“去吃饭”,而不是命令它的腿“移动”、嘴巴“张开”。
- 代码示例:
* 违反 LoD:user.getDog().getBowl().getFood();
(你知道了 User 有 Dog, Dog 有 Bowl, Bowl 有 Food,知识太多了)
* 符合 LoD:user.feedDog();
方法内部处理所有细节。调用者无需了解狗盆和食物的存在。
8. Composition Over Inheritance (组合优于继承):
- 核心思想: 尽量使用组合(has-a 关系)而不是继承(is-a 关系)来实现代码复用和功能扩展。组合更加灵活,能避免继承层次的过度复杂和僵化。
9. 正交性
- 核心思想: “正交性”源于几何学,指两条直线垂直相交,一个方向的变化不会影响另一个方向。在软件开发中,它意味着系统的各个组件(模块、类、函数等)应该尽可能解耦,职责明确且独立。改变一个组件不应该或极少需要改变另一个组件。
- 比喻: 汽车的设计是正交的。你可以更换轮胎(甚至升级为防滑胎)而无需更改发动机的软件。方向盘和刹车系统相互协作但彼此独立。
- 好处:
- 降低复杂度: 可以单独理解、开发和修改一个模块,而无需理解整个系统。
- 提高可维护性: 修复 bug 或增加新功能的影响范围被限制在局部,减少了“牵一发而动全身”的风险。
- 增强可测试性: 独立的模块可以很容易地进行单元测试。
- 促进代码复用: 低耦合的组件更容易被抽取出来用在新的项目中。
总结与关系
这些原则并非孤立,而是相互关联、相辅相成的:
- 遵循
DRY
和SPOT
是保证系统一致性和可维护性的基础。 - 通过
SoC
和追求正交性
来实现模块化,是达成 DRY 和 SPOT 的主要手段。 - 在整个过程中,要时刻用
KISS
和YAGNI
来约束自己,避免引入不必要的复杂性。 LoD
和组合优于继承 是指导具体设计、实现低耦合(正交性)的重要技巧。
这些原则是编写可维护、健壮和高效代码的基石,将这些原则内化于心,能极大地提升您的软件设计能力和代码质量。