知识卡片

主序列与I/A图:用痛苦区、无用区和D指标量化组件设计质量

结构图卡

内容

把[[SDP稳定依赖原则稳定性的量化定义与Fan-in-Fan-out指标]]的不稳定性指标I(0=最稳定,1=最不稳定)与抽象化程度指标A(组件中抽象类/接口占比,0=毫无抽象,1=全部抽象,Na/Nc)画在同一张图上,理想的两极是左上角(I=0, A=1)——最稳定且完全抽象,和右下角(I=1, A=0)——最不稳定且完全具体。但真正危险的是另外两个角落:靠近(0,0)的区域叫痛苦区——组件既非常稳定(很多人依赖它,难以修改)又完全不抽象(无法通过扩展来适应变化),这种组件既不能被轻易改动又不能被扩展,进退两难,典型例子是数据库表结构(极难变更又被大量组件依赖,这正是ORM层管理起来如此痛苦的根源)——但如果一个落在(0,0)的组件本身极少变化(如String类),停留在痛苦区反而是无害的,因为它压根不太可能被修改,真正造成麻烦的是那些”多变却又落在痛苦区”的组件。靠近(1,1)的区域叫无用区——组件无限抽象、却没有任何人依赖它,往往是历史遗留下没人用的抽象类,纯属浪费。设计良好的组件应该尽量远离这两个区域,从(1,0)连到(0,1)的这条线被称为主序列线:位于线上的组件既不会为追求稳定而”过度抽象”,也不会为回避抽象而”过度不稳定”——通常这类组件既有足够多的依赖者(因而需要一定抽象性)、又依赖了足够多其他组件(因而必然包含具体实现)。可以用D指标=|A+I-1|量化一个组件偏离主序列线的距离,D=0代表恰好落在主序列线上,D=1代表离得最远;对整个系统,可以统计所有组件D指标的均值和方差来评估设计质量,均值方差都接近0是好设计的标志,方差还可以当作”达标红线”用来揪出设计中的异常组件,也可以按发布版本跟踪单个组件D值随时间的变化趋势,一旦某组件的D值突破红线,就是该重新审视它依赖关系的信号。

结构图

flowchart TD
    A1["(I=0,A=1) 全稳定全抽象<br/>理想极点之一"] --- Main["主序列线: 从(1,0)到(0,1)"]
    A2["(I=1,A=0) 全不稳定全具体<br/>理想极点之二"] --- Main
    Pain["(0,0)附近: 痛苦区<br/>稳定却不抽象,难改又不可扩展"] -.远离.-> Main
    Useless["(1,1)附近: 无用区<br/>抽象却无人依赖,纯属浪费"] -.远离.-> Main
    Main --> D["D指标=|A+I-1|<br/>量化偏离主序列的距离"]

参考来源

- 位置:《架构整洁之道》第14章《组件耦合》"衡量抽象化程度""主序列""痛苦区""无用区""离主序列线的距离"(源文件:_epub-src/text/part0013_split_003.html) - 结论依据:原文定义抽象化指标A与I/A图的两个理想极点,用数据库表结构与String类举例说明痛苦区的构成及"不可变组件落痛苦区无害"的补充判断,定义无用区,并给出主序列线与D指标公式作为量化偏离程度的手段,直接支撑本卡片的结构图与解释。 - 原始内容:这样的组件在设计上是不佳的,因为它很难被修改……我们将这个区域称为痛苦区……该位置上的组件不会是我们想要的……我们将这个区域称为无用区……我们可以将距离两个区域最远的点连成一条线……我将这条线称为主序列线……距离D=|A+I-1|。