《架构之道》读后感

273 阅读9分钟

三个点

该书提出了很多概念和观点,如果非得说比较重要的点,有下面三个:

  1. 功能始终是集成的结果,而不是实现的结果

  2. 易变性

  3. 核心用例

如果还有什么稍微有点分量的,那就是“管理器”了。

理解

功能是集成的结果

这个观点可以说是本书最重要的观点,其始终贯穿着本书的观点和理论。也是最值得读者花时间去理解、去串联其他点、 去回忆(回忆之前参与过的项目代码)、去实践的点。

  • 例子

书中给出的一个例子是汽车将人从A地运送到B地这一功能。要做到这个功能需要通过发动机、变速箱、坐椅、道路、燃料等组件集成在一起。另外一个例子是“文字处理”功能。为了实现该功能,需要集成键盘、屏幕、硬盘、总线、CPU和内存等组件。通过这些组件提供的能力完成文字处理功能。

如果直接实现汽车的运送功能,或许会实现成自行车,反正都能满足运送需求。但这个无法应对需求变更(易变性),比如能遮风挡雨。

书中的例子可能有些抽象。考虑一个代码例子,有一个功能实现起来有点复杂。方案1是在一个函数中将功能实现了。方案2是将该功能划分成三个函数funA,funB和funcC,并依次在funA中调用funcB,funcB中调用funcC。方案3则是搞多一个函数func,在func中依次调用funcA、funcB和funcC。funcA返回的结果用临时变量存储,并作为参数传递给funcB。

第三种方案通过集成三个函数,满足了功能。而前两种方案都是有实现的味道,特别第一种是直接实现的。有经验的开发人员一眼就看出第三种方案解耦较好,如果PM提出另外一个类似的功能,或许可以基于funcB和funcC,再加一个funcD来做到。这样的组织形式,更能对抗需求的变更和新增,减少开发人员对新需求的抵触感。

PS:func可以认为是管理器。

推广而言,一个功能如果实现中函数调用链深度越深,就越少集成的味道。如果越多函数调用打平在管理器中,那么集成性就越好。当然也得防止将过多的集成逻辑放到管理器中,此时或许增加一层管理器会更加合适。

  • 集成

不仅仅函数,模块组件更是如此。不要直接实现所需的功能,而是将需求所需的能力拆分成几个基础组件,然后基于这几个组件集成功能。这样的好处也比较明显:1. 解耦;2. 需求变化不大时,可以通过稍微调整集成组件的方式满足新的需求。

这不就是模块化嘛,用得着说得那么高深吗?嗯,是的!这个观点是让开发人员先将功能拆分成几个组件,然后精力集中开发各个组件,最后只需简单集成一下即可实现功能。而不是直接开干实现功能。

直接开干容易开发出一个大泥球系统,逻辑错综复杂,难于维护和测试。最可怕的是无法应对需求的变更。书中给了一个烹饪例子。如果直接实现一个烹饪功能,那代码会倾向于往烹饪靠,各种基于烹饪的设定。后续要换成另外一种煮饭功能时,需要的改动量就大了。如果一开始就组件化,将烹饪功能拆分成几个基础组件,那么无论是烹饪还是其他煮饭功能,都是不同的集成方式而已。

易变性

顾名思义,易变是某个功能容易发生变化。未雨绸缪,需要提前考虑这些易变的地方(也就是易变区域)。因为做好系统可扩展的最好时机是在设计阶段。

  • 由来

《架构之道》认为基于功能分解系统是有问题,具体表现是无法cover系统需求的变化以及大大增加系统的复杂度。从而,书中提出一种基于易变性分解系统。基于易变性的分解识别潜在变化的区域,并将这些区域封装到服务或者系统构建块中。然后将所需的行为实现为易变封装区域之间的交互。

如上图,根据功能分解的交易系统无法应对买债券、大宗商品;客户端从web变成APP;报告类型也可能从纸质版变成短信、邮件等变化。此时改造会造成比较大的架构调整。

如上图,有关不同类型金融产品交易,都是封装进交易工作流中。不同类型的报告都封装在通知组件中。简单而言,就是一旦确定了易变区域,就需要将它们封装到架构的组件中。

  • 发现易变区域

一般是在需求分析和与项目干系人访谈时,明确系统的易变区域。

书中提出通过时间和空间两条易变轴发现易变区域。时间轴是指同一个客户随着时间推移发生的变化。空间轴是指不同客户之间的变化。

  • 与集成的关联

易变性和“功能是集成的结果”是紧密关联的。

由于需求会随着时间变化而改变,当满足需求的功能出现变化时,可以通过调整集成的内容(也就是换个管理器),满足新的功能。

当然这个其实是因果反转了。实际上应该是先做好预测,分析系统各个功能的易变区域,然后为这些易变点设计相应的组件。最后通过一个管理器集成一个满足当前需求的功能。后面PM变更功能点时,就可以通过重新基于之前的组件或者新增的新组件,构建一个新的管理器,集成一个新的功能。

简单来说就是:一旦确定了易变区域,就需要将他们封装到架构的组件中。为这些易变区域开发一系列的组件,然后从中挑选几个组件集成当前的功能。后续功能变成其他时,可以快速通过另外的集成方案完成新功能

  • 好处

通过易变性分析,可以识别某个需求其实是解决方案而非需求。书中的例子是:烹饪是满足房屋里人民在家里吃需求的一种可能的解决方案,而非需求。因为可以通过外卖或者下馆子解决。

为什么要提这个点。因为解决方案只是一种集成方案,这容易联想到这个需求还有另外的解决方案,也就是另外的集成方案。为了应对其他的解决方案(集成方案),就需要主动去分析易变区域,为多种集成方案设计和开发所需的组件。尽量做到不同的集成方案(功能),能够最大可能复用组件。

核心用例

核心用例代表了系统业务的本质。正常情况下,业务的本质不会怎么改变。PM花里胡哨的需求,其实都是一些辅助功能,并没有改变业务的本质。因为核心用例是业务的本质,因此核心用例并不会太多,也就3到5个。

  • 例子

书中第五章的TradeMe系统,核心用例是匹配技工用例。因为这个系统主要是撮合技工和承包商交易的系统,如何为双方找到合适匹配的技工进而撮成交易,才是系统的核心功能。那些创建技工、付款之类的都是为了辅助性的。

又比如配置管理系统。核心用例必然是1. 编辑配置内容;2. 配置发布;3. 配置读取。至于其他功能都是辅助的,比如:配置版本diff、配置权限管理、配置发布前需要review。

  • 用途

从零设计一个系统(或者重构一个老系统),往往无处下手。特别是第一次做系统设计的开发人员。书中介绍的方法是寻找系统的核心用例。通过核心用例将系统的最本质的功能和资源定型下来,并开发实现。PM的其他用例都是在此基础上修修补补的。

管理器

管理器可以当认为是“功能是集成结果”理论的践行者。

其主要是完成集成操作。通过调整调用不同的组件的顺序,以及条件判断,完成一种集成,实现一种功能。如果是易变区域中的另外一个类似功能,那么可以调整管理器中的组件的调用顺序或者条件判断,完成新的集成,实现新的功能。下图就是三种不同的集成方式。

综合应用

       在项目设计初期,并未有各个服务和组件。靠的就是核心用例的调用链,将各个服务和组件的功能定下来,慢慢细化和浮现的。调用链是架构师的产出,需要记录到文档中。作为项目的输出之一。

从核心用例出发,明确核心用例链路上需要用到的各个功能。然后分析功能的易变性,细化出各种可能的变化,综合考虑各种易变功能,列出各种变化所需的组件,为这些易变区域设计最大可能复用的基础组件。最后通过组件集成当前所需的功能,实现核心用例。当后面变更某个功能时,只需调整该易变区域的集成方案即可(也就是管理器)。