面向服务的设计一直都有一个话题,就是服务的“颗粒度”问题,无论是 SOA 还是微服务,都很难把握颗粒度。首先,SOA 在实际操作中并不是真的关心颗粒度问题,一个遗留系统可以直接被封装成一个服务,也可以把很小的功能服务化,二者地位是一样的,所以,大家常说 SOA 本质上是个集成架构,有效解决了异构系统的集成问题,统一了内部通信方式,一般重担会直接压给企业总线。其次,微服务很关心颗粒度问题,但是却很难判断服务合适的大小,太大了,内聚性不好;太小了,通信会过于复杂,降低效率。近几年,也有不少人用 DDD 方法指导微服务设计,取得了一些成果,但是 DDD 方法本身学习门槛比较高,不容易掌握。颗粒度还关乎另一个比较重要的话题,就是组装式开发,之前介绍的业务模型方式是否能够在这方面起到些帮助作用呢?
理论上来讲,肯定可以,因为业务模型的建模过程很注重标准化,标准化就是一个去重的过程,尽可能保证流程构成元素的唯一性,以免重复建设。但是任务这个层级对我们前边讨论的服务颗粒度划分或者组装式开发而言,“粗细”未必合适,它更符合业务视角的企业级架构设计,实现上我也介绍过,要对接到基于业务模型的分析设计方法上,通过活动、任务再走到用例、交易或服务的设计。组装式开发是不是服务之间可以通信、互相调用就是组装了?这样的逻辑对于技术人员而言,好像可以接受,但是却无法传递给业务人员,成了单纯的技术组装。另外,如果服务颗粒度划分过细,这样的组装式开发也会累死通信机制,最后形成一个混乱的网状通信,使得迭代、升级变得非常复杂。那么如何在“粗”和“细”之间找到平衡方式,又容易被业务人员理解呢?这章开始,跟大家讨论下改进的可能方法。
可以在业务模型中再增加一个面向组装式设计的表达,并通过这一表达形成面向业务实例或者产品的组装式设计,这种方式至少在金融领域可以有效。设计逻辑如下:
这种设计一般应包含两个目标,参数化配置和组装式开发,前者好理解,就是一般项目上做的参数化设计,通过参数配置快速刷新产品,参数化设计对于代理保险、实物贵金属、理财等标准化程度高的产品非常适用,因为产品之间几乎就是参数取值方面的差异,但是结合了后者之后,参数的设计就有了些变化。组装式设计要求更强的结构化,面向产品时就要把产品切成“零件”,通过组装“零件”、调整“零件”来快速实现新产品。那么“零件”怎么切呢?金融行业属于服务业,金融产品就是金融服务过程,所以,金融领域中大部分产品其实跟流程是一体两面的关系,将一段流程包装起来销售就成了产品,那产品的“零件”自然来自于流程。流程在业务建模时已经标准化成任务了,那么再进行设计,自然就是针对任务进行调整,将一个“任务”再细分成若干个“零件”,亦或将多个任务聚合成一个“零件”,这些打破了任务结构的零件暂称其为“构件”。构件不像任务对应的是用例,而要对应服务的设计,一个构件可以由一个或一组服务组成,这取决于实际需要或者团队的设计习惯。构件中的服务会涉及参数设计,这些参数都记录在同一个构件上,严格来说这些参数应该都是数据模型中的属性,可以在属性上增加参数标识,以便从数据模型中容易识别出来。这些带有参数的构件加在一起就形成了一个有结构的产品模板,既可以体现出组装式设计,又可以用于参数配置。构件的切分原则应当是每个构件都能给出明确的业务含义,而不是单纯为了给服务分分堆儿。参数的选择既可以定位在需要配置的参数,也可以更加宽泛地表达为构件包含的服务的外部输入报文集合和最终输出报文,这样更方便于构件的组合设计。
构件模型与具体设计的结合如下图所示:
设计上可以实现通过模板配置参数,实例化成业务实例或者产品;通过参数驱动动态界面;模板实例出的产品在预配和销售中完成所有参数的赋值,服务运行时读取赋值结果;基于构件与服务关系的服务清单可以用于服务管理和服务发现;合约关联相应的账户,可以驱动账务记录。最为困难和关键的是构件与服务之间的对应关系,下面我讲讲关于这方面的一些思考,由于本人设计经验有限,权做与大家共同探讨构件可行的设计方式吧。
举个例子,涉及到竞价的产品可能会有这样的流程,即资金拥有方,比如总行,可以通过对某笔闲置资金进行内部的竞价,从而确定出价最高分行可以运用该笔资金获取收益,因为竞价决定资金归谁使用其实是有机会成本的,因此竞价过程中也可能需要通过计算 EVA(经济增加值)的方式,进一步衡量其经济贡献。通过下图,我们把流程模型与数据模型相结合的表达、构件模型的表达与颗粒度较细的服务之间可能的关联关系表示出来:
其中竞价部分流程模型假定为三个任务,数据模型简化处理,设计四个数据实体。构件模型层面,竞价任务可以独立设计构件;从数据上看,意向申报和意向审批虽然按照角色会拆分成两个任务,但是数据其实是一套,是可以合并设计的;EVA(经济增加值)试算可以独立,因为其计算方式具有企业级的通用性,独立有利于其他领域复用;竞价、意向管理在实际业务中可能需要具有“可选性”,因为有些产品是可以没有这些流程的,所以,三个任务可以被设计为三个“可选”构件。这样拆分的构件颗粒度应该不会过细,并且支持业务含义的组装。不过,如果服务层级设计的颗粒度过细,比如,例子中拆分成 9 个服务,这是设计中可能会存在的拆分方式,从实现上讲可能没毛病,但是维护、升级,特别是在业务理解上却会比较麻烦。
从模型的角度讲,构件仍然是逻辑的,要落实到服务才是物理的,而服务的实现很多时候会依赖于开发团队的设计习惯和经验,对于大型企业级项目来讲,如何在企业范围逐步实现合理的颗粒度判断原则是个难题,是要靠过程和沟通去逐步形成,良好的业务模型对于实现开发风格的一致性也是有帮助的。
例子中可以看到,构件打破了原来意向申报、意向审批这两个任务的边界,原来的流程,转变为了竞价通知管理、意向管理和 EVA 试算三个构件的“组装”,这三个构件相对独立,每个构件可以进一步拆分为更细的服务或者直接尝试作为一个服务设计。这样的切分,最终会形成系统实现与模型之间最一致和最紧密的联系,也有点儿“微服务”的影子,并且,在日后的需求分析中会形成由需求直接定位到实现的能力。
首先,这种设计方式是一种可选的设计方式,也即,如果不做这种面向组装的构件模型,只用之前介绍的业务架构方法,也足以实现企业级设计,做好参数化,也可以完成一定程度的灵活配置,只不过对于组装式开发的表达有一定欠缺,这就要看企业希望实现的设计目标了。
其次,这种方法显然难以在业务建模过程中,尤其是在企业初次进行企业级转型,做最初的业务架构设计时一次性完成,也无法以业务人员为主去做,有较多的系统分析与设计方面的考虑,更多是技术人员的工作范畴,因此,必须有技术人员深入参与,跟业务人员共同完成设计。虽然偏重技术,但是由于构件可以有明确的业务含义,完成首轮设计后,业务人员也能够轻松使用这种模型与技术人员共同讨论新需求,以及维护模型,特别是每个构件拆分的服务较少的情况下。
再次,这种模型可能打破原来流程模型中任务的边界,产生新的模型表述方式,这种情况下,可以选择是否将其视为流程模型的一次新视角的迭代,替换掉原有的流程模型。这种模型打破了原来业务模型较为单纯的业务属性,将业务含义与具体实现直接结合在了一起,而且是基于构件串起来的产品执行流程,是一种可以在一定程度上满足流程与能力解耦的表达方式。虽然本文的讨论侧重金融领域,但是其他行业也可以找到适合自身特点的“零件”切分方式。这种方式也并非对本文前述方法论的较大颠覆,实际上只改动了对任务层面的表达,而活动层面并未发生变化,因此其从战略延伸下来分解方式并未变化,而是在实施阶段对业务模型的一次迭代演化,后续文章将进一步阐述这种设计可能的应用方式和好处。