2.1 编程原则
控制流与布尔代数
控制流(Control Flow) 描述软件中执行如何从一个命令/语句流转到下一个。基本结构: - 顺序:逐行执行。 - 分支:if-else、switch、goto(goto 被认为有害——Dijkstra)。 - 循环:for、while、do-while、foreach、无限循环。 - 函数调用:跳转到函数体执行后返回调用点。
布尔代数由 George Boole 于 1847-1854 年创立,是处理真值(true/false)的逻辑运算体系。三种基本操作——AND(∧ 与)、OR(∨ 或)、NOT(¬ 非)——构成所有数字电路和编程语言中条件表达式的基础。核心定律包括分配律、结合律、交换律、De Morgan 律(¬(A ∧ B) = ¬A ∨ ¬B)、互补律(A ∧ ¬A = 0, A ∨ ¬A = 1)。Claude Shannon 在 1930 年代将其应用于开关电路设计,奠定了数字电子学的基础。
面向对象编程(OOP)
四大核心概念: - 封装:将数据和操作数据的方法绑定在一起,隐藏内部实现。 - 继承:子类继承父类的属性和方法,实现代码复用(需谨慎使用,见组合优于继承)。 - 多态:同一接口,不同实现。通过方法重写和接口实现,让不同类型的对象对同一消息做出不同响应。 - 抽象:只暴露必需接口,隐藏复杂实现细节。
SOLID 原则
Robert C. Martin(Uncle Bob)在 2000 年提出,由 Michael Feathers 在 2004 年命名的五项面向对象设计助记缩略词。
| 原则 | 含义 |
|---|---|
| SRP 单一职责 | 一个类只应有一个引起它变化的原因。每个类只有一个职责。→ 可维护性、可测试性、灵活性 |
| OCP 开闭原则 | 软件实体应对扩展开放,对修改关闭。新增功能不改变已有代码。→ 扩展性、稳定性 |
| LSP 里氏替换 | 使用基类的代码必须能在不知道派生类存在的情况下使用派生类。子类必须遵守父类契约。→ 多态、可靠性、可预测性 |
| ISP 接口隔离 | 客户端不应被迫依赖它们不使用的接口方法。大接口应拆为小的专用接口。→ 解耦、避免不必要依赖 |
| DIP 依赖反转 | 应依赖抽象,不依赖具体实现。高层模块不依赖低层模块,两者都依赖抽象。→ 松耦合、灵活性、可维护性 |
GRASP 模式
General Responsibility Assignment Software Patterns,由 Craig Larman 在《Applying UML and Patterns》中提出。Larman 指出:"软件开发的关键设计工具是一颗受过设计原则良好教育的大脑。不是 UML 或任何其他技术。"
| 模式 | 含义 |
|---|---|
| Information Expert(信息专家) | 将职责分配给拥有完成职责所需信息的类 |
| Creator(创建者) | 如果 B 包含/记录/紧密使用 A,或 B 有初始化 A 所需的信息,则由 B 负责创建 A |
| Controller(控制器) | 由非 UI 类接收和处理系统事件,协调任务,但不自己做太多工作 |
| Low Coupling(低耦合) | 减少类之间的依赖,使修改一个类对其他类的影响最小化 |
| High Cohesion(高内聚) | 类的职责应高度相关并聚焦于特定主题 |
| Polymorphism(多态) | 通过多态操作处理基于类型的行为变化,而非显式的类型分支 |
| Pure Fabrication(纯虚构) | 创建一个问题域中不存在但能实现低耦合高内聚的类(对应 DDD 中的 Service) |
| Indirection(间接) | 通过中间对象协调两个组件,避免直接耦合 |
| Protected Variations(保护变化) | 用接口封装不稳定的部分,使变化不影响其他元素 |
函数式编程(Functional Programming)
函数式编程的核心思想是将计算视为数学函数的求值,强调: - 纯函数(Pure Function):给定相同输入,永远返回相同输出,且没有副作用(不修改外部状态、不读写文件、不发网络请求)。这是可测试性和可预测性的基础。 - 不可变性(Immutability):创建后不可修改的数据结构。修改操作返回新副本而非原地修改。消除了共享可变状态带来的并发 bug。 - 递归(Recursion):用函数自调用替代循环迭代,处理可分解的重复模式。 - 高阶函数(Higher-Order Function):函数可以作为参数传递、作为返回值返回——如 map、filter、reduce。 - 函数组合(Function Composition):将简单函数组合为复杂行为,f(g(x))。
函数式编程是声明式编程的子集。
声明式 vs 命令式编程
| 维度 | 命令式(Imperative) | 声明式(Declarative) |
|---|---|---|
| 关注 | How(怎么做) | What(做什么) |
| 抽象层级 | 低层,接近机器执行 | 高层,接近人类意图 |
| 示例 | for (i=0; i<arr.length; i++) { sum += arr[i]; } |
SQL SELECT SUM(price) FROM orders |
| 子集 | 过程式编程(Procedure) | 函数式编程(Functional) |
两者不是对立关系——大多数程序同时包含两种风格。UI 框架(React/Flutter)天然倾向于声明式,算法实现倾向于命令式。
来源
- Wikipedia — Control flow: https://en.wikipedia.org/wiki/Control_flow
- Wikipedia — Boolean algebra: https://en.wikipedia.org/wiki/Boolean_algebra
- Wikipedia — SOLID: https://en.wikipedia.org/wiki/SOLID
- Wikipedia — GRASP (object-oriented design): https://en.wikipedia.org/wiki/GRASP_(object-oriented_design)
- Anthony Zotti — Declarative vs Imperative Programming: http://amzotti.github.io/programming%20paradigms/2015/02/13/what-is-the-difference-between-procedural-function-imperative-and-declarative-programming-paradigms/