知识卡片

逻辑复杂性:功能堆砌与复杂算法两种典型形态

普通读书笔记卡

内容

意识到[[结构复杂性:组件数量增加带来的三重代价]]后,一个自然而然的应对思路是减少组件数量,走到极端就是把所有功能和逻辑都塞进单一组件。但这条路走不通,因为组件数量减少的同时,单个组件内部的逻辑复杂性会急剧上升——逻辑复杂的组件典型特征是承担了太多功能,例如把电商业务的商品管理、商品搜索、商品展示、订单管理、用户管理、支付、发货、客服等全部塞进一个组件,会带来代码规模膨胀到clone一次要半小时、几十上百人共同维护同一份代码导致”菜鸟”一次误改就能让全站崩溃、需求堆积导致分支泛滥难以合并、跨团队协调成本剧增、每天上线几十个版本迫使系统频繁重启、故障排查需要几十人同时上阵等一系列后果。这里有个值得辨析的反直觉点:为什么”复杂电路”代表功能强大,”复杂建筑”代表精美先进,而”复杂软件架构”反而代表问题?根本原因在于电路一旦设计定型进入生产就不会再变,复杂性只在设计阶段起作用;而软件投入使用后还有源源不断的新需求要落地,需要持续修改,复杂性会在整个生命周期里反复放大影响,而不是一次性成本。逻辑复杂性的另一种典型形态是单个组件采用了过于复杂的算法——复杂算法导致的问题主要是理解门槛高,进而带来实现难、修改难、出问题难以快速解决,例如ZooKeeper虽然功能相对单一(主要是分布式选举),但因为采用ZAB协议实现,系统复杂度就明显偏高;相比之下etcd采用Raft算法实现同类选举功能,因为Raft比ZAB更容易理解和实现,系统复杂度就更低。

参考来源

- 位置:《从零开始学架构》第08讲《架构设计三原则》"简单原则"之"逻辑的复杂性"(源文件:_epub-src/OEBPS/text00000.html) - 结论依据:原文说明"逻辑复杂的组件,一个典型特征就是单个组件承担了太多的功能"并以电商单一组件的后果为例;同时说明"根本原因在于电路一旦设计好后进入生产,就不会再变,复杂性只是在设计时带来影响;而一个软件系统在投入使用后,还有源源不断的需求要实现……复杂性在整个系统生命周期中都有很大影响";并以ZooKeeper(ZAB协议)与etcd(Raft算法)对比说明复杂算法带来的理解与实现难度差异,直接支撑本卡片结论。 - 原始内容:逻辑复杂的组件,一个典型特征就是单个组件承担了太多的功能……电路一旦设计好后进入生产,就不会再变,复杂性只是在设计时带来影响;而一个软件系统在投入使用后,还有源源不断的需求要实现……ZooKeeper 功能虽然相对简单,但系统实现却比较复杂。相比之下,etcd 就要简单一些,因为 etcd 采用的是 Raft 算法。