「什麽是物件导向? 对软件架构师来说: 物件导向是透过使用多型(Polymorphism) 来获得对於系统中每个原始码依赖方向的绝对控制力」
取自: Clean Architecture (p.39)
CH5: 物件导向程序设计
思考: What is Object Oriented?
常见回答一: 资料和函式功能的结合
- 不够令人满意。早在 1966 以前程序设计师早透过把资料结构传递给函式达成此种结合
- e.g.,
obj.func();
和 func(obj);
常见回答二: 一种模拟真实世界的方式
- 这在暗示 OO 使软件更容易理解、与现实世界有着更密切的关系
- 仍然不够满意,定义过於松散
经典回答三: 以封装、继承、多型特性所合成的产物
- 谈封装
- 封装不是物件导向所独有的,事实上 C 语言反而拥有完美封装
- 例 (Code)
TODO...
- C++ 出现後,C 语言的完美封装就被破坏了
- 原因: C++ 编辑器需要知道每一个类别的 Instance 所占记忆体的大小
TODO...
- 谈继承
- C 语言或 1960 年代大多数的语言都有能力可以将一个资料结构伪装成另一个资料结构,以此达成继承功能
- 例
TODO
- Object Oriented 的出现确实使资料结构的伪装变得更方便
- 谈多型
- C 语言一样可以达成多型功能
- 透过函式指标 (Function Pointer)
- 例: UNIX 作业系统中的 STDIN, STDOUT 介面
- 这个技巧是所有多型的基础
-
多型就是函式指标的一种应用
- C++ 的多型
- Class 中的虚拟函式 (Virtual Function) 都会存在一个 VTABLE 中,透过 VPTR 存取
- 显式 (Explicit) 使用函式指标的问题
- 函式指标是危险的
- 必须遵循一系列人工的约定来操作这些指标,DEBUG 很难
- 使用 OO 语言使多型变得很简单
多型的威力
- 好处
- 依赖反向
- OO 语言提供安全方便的多型,无论在何处,任何的原始码依赖(Dependency)都可以被反向
CH6: 函数式程序设计
「函数式语言中的变数不会改变(Do Not Vary)」
「为什麽软件架构师关心变数的可变性? 因为: 所有 Race Condition、Deadlock、Concurrent Update Problem 都来自於可变的变数」
「没有变数被更新,就不会有 Race Condition、Concurrent Update Problem。没有可变的 Lock ,就不会有 Deadlock」
取自: Clean Architecture (p.43)
不可变与架构
- 思考: 如何设计在「多执行绪」和「多处理器」情况仍旧耐用的系统?
- 达成不变性的方式
- 有无限储存空间和处理器速度
- 做出某些折衷...
1. 事件来源 (Event Sourcing)
- 想像: 不是储存帐户余额 (状态)、而是储存所有交易
- 这并非不可能达成
例如:
- 所有程序只具备 CR (Create / Read) 的能力,不具备 UD (Update / Delete)
- 不会产生任何平行化问题
- 完全的函数化 (Entirely Functional)
2. 可变性分离
- 将服务分离为可变和不可变的元件
- 使用交易式记忆体 (或事务内存, aka Transactional Memory)
- 补充: 可简单想成是一类针对 Data 一致性(Consistent)特别设计过的 Memory
- 运作逻辑可简单图示成: