原文:https://codingstyle.cn/topics/187

《变化驱动:正交设计》 读书笔记

软件设计设计的最初动机:功能实现。
这个时候为了实现功能,将所有的功能都写在一个函数里面,这个时候就造成了“上帝类”的存在。但是上帝类的出现已经超出了我们的控制。所以这个时候为了适应变化,我们会对模块进行拆分。

结构:客户-API-实现

为什么要进行软件“设计”?

Kent Beck给出的答案是:软件设计是为了在让软件在长期范围内容易应对变化。

局部化影响:任何一个变化,对于我们当前的软件设计影响范围都可以控制在一个尽量小的局部。(单一职能原则)

如何做到局部化影响?
内聚和耦合。
内聚:软件单位内部的关联紧密程度,高内聚追求的是关联紧密的事务,应该被放在一起,并且只有关联紧密的事物才应该被放在一起。

耦合性,则是强调两个或多个软件单位之间的关联紧密程度。因而低耦合追求的是,软件单位之间尽可能不要相互影响。

模块化设计:首先将一个低内聚的模块首先拆分为多个高内聚的模块;然后再考虑这多个模块之间的API设计,以降低这些高内聚的软件单元之间的耦合度。

除了内聚与耦合之外,还有另外一种关系:正交。具备正交关系的两个模块,可以做到一方的变化不会影响另外一方的变化。换句话说,双方各自独自变化,互不影响。

一个类只应该有一个变化的原因。
所谓一个变化原因,指一个变化会导致整个类所包含的各个元素都要发生变化。为何会如此?因为它们的关联程度太紧密(因而高内聚),以至于牵一发而动全身。

变化方向,并不总是以重复代码的形式出现的(其典型症状是散弹式修改,或者if-else、switch-case、模式匹配);尽管其背后往往存在一个以重复代码形式表现的等价形式(这也是为何copy-paste-modify如此流行的原因)。

模式匹配:
模式(pattern) 是一个只包含变量、构造子和通配符的表达式。

分离变化-可扩展性
分离不同变化方向,目标在于提高内聚度。因为多个变化方向,意味着一个模块存在多重职责。将不同的变化方向进行分离,也意味着各个变化方向职责的单一化。
什么时候进行分离变化?
当你发现需求导致一个变化方向出现时,将其从原有的设计中分离出去。

怎样拆分才算合理?
消除重复-分离变化

客户端和实现之间的API应该如何定义。
缩小依赖范围-向着稳定的方向依赖