读书笔记 《架构整洁之道》(施工中...)
第1部分 概述
Ch2 两个价值维度
艾森豪威尔矩阵
重要且紧急 | 重要不紧急 |
---|---|
不重要但紧急 | 不重要且不紧急 |
软件系统的两个价值维度:
- 系统行为
- 系统架构
常犯错误:将优先级为<不重要但紧急>的任务提到第一优先级去做
第2部分 从基础构件开始:编程范式
Ch3 编程范式
结构化编程 1968
对程序控制权的直接转移进行了限制和规范
面向对象编程
对程序控制权的间接转移进行了限制和规范
函数式编程
对程序中的赋值进行了限制和规范
关注重点:功能性、组件独立性、数据管理
Ch5 面向对象编程
依赖反转
原本:系统行为决定了控制流,而控制流决定了源代码依赖关系
使用多态后:模块和接口在源代码上的依赖关系的方向和控制流是相反的
第3部分 设计原则
SRP 单一职责原则
任何一个软件模块都应该只对某一类行为负责
!将服务不同行为者的代码进行切分
OCP 开闭原则
设计良好的计算机软件应该易于扩展,同时抗拒修改
LSP 里氏替换原则
组件遵守同一约定,以便相互替换
ISP 接口隔离原则
!任何层次的软件设计如果依赖了它并不需要的东西,就会带来意料之外的麻烦
DIP 依赖反转原则
高层策略性的代码不应该依赖实现底层细节的代码
DIP具体的编码守则:
- 应在代码中多使用抽象接口,尽量避免使用那些多变的具体实现类
- 不要在具体实现类上创建衍生类
- 不要覆盖(override)包含具体实现的函数
- 工厂模式
第4部分 组件构建原则
Ch13 组件聚合
REP 复用/发布等同原则
软件复用的最小粒度应等同于其发布的最小粒度
CCP 共同闭包原则
将那些会同时修改、且为相同目的而修改的类放到一个组件中;反之,放到不同组件中
CRP 共同复用原则
不要强迫一个组件的用户依赖他们不需要的东西
Ch14 组件耦合
ADP 无依赖环原则
组件依赖关系中不应该出现环
打破循环依赖:
1.应用依赖反转原则(DIP)
2.创建新组件存放原本不同组件中互相依赖的类
SDP 稳定依赖原则
依赖关系必须要指向更稳定的方向
SAP 稳定抽象原则
一个组件的抽象化程度应该与其稳定性保持一致
第5部分 软件架构
Ch16 独立性
用例
一个系统的架构必须能支持其自身的设计意图
部署
一个设计良好的软件架构可以让系统在构建完成之后立刻就能部署
保留可选项
一个设计良好的架构应该通过保留可选项的方式,让系统在任何情况下都能方便地做出必要的变更
按层解耦
一个系统可以被解耦成若干个水平分层——UI界面、应用独有的业务逻辑、领域普适的业务逻辑、数据库等
用例的解耦
如果我们按照变更原因的不同对系统进行解耦,就可以持续地向系统内添加新的用例,而不会影响旧的用例
重复
架构师们经常会钻进一个牛角尖——害怕重复
!看起来重复,但由于不同的变更速率和变更缘由,并不是真正的重复
!看起来类似的两个用例,复用同一段代码。但只是表面的类似,未来将它们分开会面临很大的挑战
再谈解耦模式
源码层次 | 部署层次 | 服务层次
一个系统所适用的解耦模式可能会随着时间而变化,优秀的架构师应该能预见这一点,并且做出相应的对策
Ch17 划分边界
应在何时、何处画这些线
边界线应该画在那些不相关的事情中间:
- GUI与业务逻辑
- 数据库与GUI
- 数据库与业务逻辑
输入和输出怎么办
❌由于GUI能直接看到,就很自然地把GUI当成了系统本身
I/O是无关紧要的
界面背后存在着一个模型——一套非常复杂的数据结构和函数,那才是系统真正的核心驱动力
插件式架构
系统的核心业务逻辑必须和其他组件隔离,保持独立,而这些其他组件要么是可以去掉的,要么是有多种实现的
这其实是单一职责原则(SRP)的具体实现,SRP的作用就是告诉我们应该在哪里画边界线
Ch19 策略与层次
一般来说,低层组件被设计为依赖高层组件
上图中所有的依赖关系都指向了边界内部,它是该系统中最高层次的组件。这个架构将高层的加密策略与低层的输入/输出策略解耦,当低层策略发生变更时,不太可能会影响高层策略。
Ch20 业务逻辑
业务实体
业务实体包含关键业务逻辑和关键业务数据,它与数据库、图形界面、第三方框架等内容无关。业务实体这个概念中应该只有业务逻辑,没有别的
用例
用例描述一个特定的应用情景,更靠近系统的输入和输出,属于低层概念。而业务实体属于高层概念,并不会直到是哪个业务用例在控制它们。用例依赖于业务实体,而业务实体并不依赖与用例
Ch21 尖叫的软件架构
- 软件的系统架构应该为该系统的用例提供支持
- 结构设计不是(或者说不应该是)与框架相关的
!框架是工具而不是生活信条,要带着怀疑的态度审视每一个框架
Ch22 整洁架构
- 独立于框架
- 可被测试
- 独立于UI
- 独立于数据库
- 独立于任何外部机构
依赖关系原则
源码中的依赖关系必须只指向同心圆的内层,即由低层机制指向高层策略
!任何内层圆中的代码都不应该牵涉外层圆中的代码(eg:函数名、类名、变量名等)
!不应该让外层圆中发生的任何变更影响到内层圆的代码