个人理解,组装式开发指的是将系统分解为标准组件,再由标准组件组装成系统,以此形成的架构被称为组装式架构。跟传统代码复用技术关键的不同点在于组件的含义。组件是高度标准化的单元,具备可复用性、标准化、可替换性、可包装及独立自治这些特征。组装式开发背后的核心逻辑是基于标准化思想的代码复用。
关于标准化,乐高积木玩具我们都知道,玩具厂商制造了一批标准的积木,孩童可以基于这些积木组装成不同款式的玩具,喜欢飞机,就组装飞机,喜欢坦克,就组装坦克,这也是利用了标准化的可换性原理。再回到软件行业,基于组件实现大规模的软件复用这个概念,最早来源于 Doug McIlroy 在 1968 年的一次软件工程学会上的演讲,演讲名为 “大规模生产的软件组件”,之后这被公认为软件复用的起源。基于这个思想,如果我们能够引入组装式开发的思想,将业务代码分解成标准化的组件,然后再基于这些组件组装成不同的功能,进而满足不同场景下的业务需求。对于我们开发的代码而言,首先由定义标准的人定义接口标准,然后开发人员根据定义的标准去开发接口,开发出来的接口可以给到各个系统进行调用,在项目上或代码上也是一种标准。大到每一个项目,每一个产品,小到每一行代码,每一个代码工具,都是一个标准。
组装式开发的历史坎坷崎岖,更难的是在每个技术领域这些问题的答案还都不一样。比如在颗粒度的问题上,组件的颗粒度到底要多大,颗粒度越大,被修改的风险也就越大,而过小的颗粒度可以让组件更稳定,但是会带来组装的复杂性。再比如在应对变化这个问题上,这段逻辑到底是通用的还是个性的,非常难以辨别,但是我们的系统设计又强依赖于这个判断,如果最初的判断失误,就有可能导致系统最终的失败。我们就遇到过这种情况,自信满满地封装了一个组件,感觉应该可以满足各种复杂的情况,刚好就在下一个需求来临时,发现不太匹配。
我们还通过可视化组装的方式来简化组装过程,总体思路如下:
- 产品功能归类之系列化:定制化的项目告诉我们,单一的项目无法满足市场化的需求,多样性更具备市场竞争力。但是高效的多样性需要范围的约束,所以产品化项目前期需要大量的市场调研以及后期的迭代优化。现代汽车生产商会对产品进行系列化,比如宝马轿车有 7 系、5 系、3 系,系列化是厂商在效率和多样性之间追求平衡的产物。在软件开发领域亦然,组件的复用应该是有范围的,我们首先将产品功能进行系列化归类,进一步降低了系统整体的复杂性及设计难度。
- 功能组件提取与预组装:组件标准化是组装式开发的前提,所以我们需要先将组件提取出来。在最终组装功能的时候,为了降低组装的复杂性,我们引入了 “预组装” 的概念。针对每个系列的产品功能,我们将通用部分提前组装好,将定制部分提前预留出来,定制部分包括功能和特性的定制,这部分可延迟到需要的时候再组装。
- 变化应对之可变性建模:在电动车出现以前,所有的汽车几乎都需要燃油来发动,因此燃油机属于共性功能的需求。但是我们发现,有的车主是新手,对车子非常爱惜,因此需要全景的倒车仪。有的车主是老司机,他们根本不需要全景的倒车仪,所以全景倒车仪就属于变化功能的需求。不仅如此,我们还发现对于同样有全景倒车仪诉求的车主,他们也会选择具有不同特性的设备功能,这部分属于更细粒度的定制需求。所以,变化本身是复杂的,是有层次的,变化需要被单独建模,才能够被有效管理。
- 可视化组装与配置填充:细颗粒度的组件带来了一定的组装复杂性,为简化组装过程,我们将可用组件呈现在用户的界面上,开发同学通过点击鼠标即可完成组件的组装,而对于功能特性组件的配置填充,也是在用户界面上直接完成的。
组装式开发实践有没有解决最初的问题?组件分为大颗粒度的功能组件和小颗粒度的特性组件,不同颗粒度的组件都具备复用性和应变能力,因此在展示功能搭建方面的效率有了显著提升。内部数据显示,我们组的开发效率至少提升 50% 以上。其次,每个组件单元都是经过良好设计的逻辑单元,单个组件的规模都有所控制,因此代码的复杂度得到明显的降低。通过信息功能的系列化编制,整个信息展示系统也有所收束,接口数由上百个减少到了个位数,大大降低了接口的维护成本。
每个领域都有各自领域的复杂性,比如有的领域问题在于计算复杂,有的领域在于模型的存储和维护复杂。由于软件开发是一个工程问题,我们不能仅仅考虑技术的复杂性,同时还要考虑业务及人员的问题。科学的思维告诉我们,解决问题要讲究范式,当一个范式不满足的时候,需要有敢于突破的勇气。组装式开发由小到大,组装成一个可复用,可应变的应用。