首先声明,本文章纯属一时脑洞大开,开心就好。
之前写了一篇文章,《如何通过DDD构建一辆汽车》。当时没有说明白的一个问题是DDD是用于IT领域建模的一个方法论,为什么能套用到汽车领域等非IT领域的建模工作上。当时的想法是DDD是基于业务领域的,每个领域都会有它自身的业务,在这一点上其实并没有IT与非IT之分。所以DDD可用于别的领域建模似乎是不言自明的。但是这段时间回想这个问题,感觉上面的理由有点牵强。这就像对于要证明1+1=2,很多人都觉得这不是不言自明的吗,不需要证明啊。但事实是这真的不是不言自明的,1+1=2在数学上是可以有很严密的证明的。回到DDD的问题上,是不是也可以找到一个方法证明其同样适用于别的领域建模呢?思来想去,或许可以借用一下Togaf中Enterprise Continuum的概念来尝试证明一番。
在Togaf中,Enterprise Continuum的定义如下:
The EnterpriseContinuum provides methods for classifying architecture and solution artifacts,both internal and external to the Architecture Repository, as they evolve fromgeneric Foundation Architectures to Organization-Specific Architectures.
简而言之,就是一套方法,用于识别不同层级的架构与解决方案以及它们的关系。结合以下的图会更好理解:
从图中可以看到,Enterprise Continuum包括Architecture Continuum(橙色部分)与Solutions Continuum(绿色部分),每一部分的左边都是基础的(Generic),右边都是组织特定的(Specific )。中间的白色箭头是双向的,表明基础与组织特定间是可以互相转换的。当我得到了一个基础架构后,我可以通过对其进行改编,加入行业或者特定组织的一些限制性因素,使其匹配到具体的行业甚至是组织,成为一个有特定上下文的架构;而当我我得到了一个组织特定的架构后,可以通过使其泛化,去除掉组织特定或者行业特定因素,成为通用架构,以供重用。同样的转化方法也适用于解决方案。
在这幅图中,架构比较好理解,Togaf定义的4个架构域业务架构、数据架构、应用架构与技术架构都属于是架构的一种,此外还有我们平常常说但定义并不清晰的系统架构也可以认为是架构的一种。但是什么是解决方案呢。在Togaf中,解决方案被定义为架构的实施部分,也就是架构的实现。举个简单的例子,一个HR系统架构的解决方案就是这个HR系统本身。所以,架构是用来指导和支持解决方案的实现的。反过来说,对解决方案实施合理的抽象与提炼后,可以得到此解决方案对应的架构。这就是架构与解决方案的关系。
从基础的到组织特定的,Togaf把架构分成四层:
1. 基础(Foundation)
2. 通用系统(Common System)
3. 行业(Industry)
4. 组织特定(Organization-Specific)
理论上,架构上每一层都会存在与其匹配的解决方案:
下图很好的说明了各层架构与解决方案的关系:
不单单是这样,这幅图其实证明了不同层级的架构之间是可以相互转化的,不同层级的解决方案之间也是可以相互转化的,不但这样,不同层级的架构与解决方案之间也是可以相互转化的。事实上,这给我们提供了一个很强大的方法论支撑,让我们可以基于一个组织特定的解决方案,通过技术性的手段,不断的乾坤大挪移,推导出另外一个行业甚至是组织特定的架构,从而指导其解决方案的实现。这正是此次证明的本质所在。
下面实例化一个例子。
假设我是一名六菱宏光的汽车设计师,但是不务正业,老是捣鼓IT,某次偶然的机会得到了一个JBBC银行HR系统的源代码。我只是知道这个系统是基于一种叫做领域驱动设计的方法(DDD)构建出来的,其余的一无所知。强烈的求知欲激发了我的好奇心,我决定一探究竟。经过一番研究,终于弄明白它的架构,简单描述如下:
JBBC 银行HR 系统架构
1. 基于Spring Cloud的微服务架构
2. 6个微服务,分别是薪酬与绩效、招聘、培训、绩效、劳动关系、人力资源规划
3. 6个微服务分别交由6个团队开发(由于薪酬与绩效是同一个团队开发,所以二者归入同一个微服务)
4. 每个微服务中非常多的类都是继承自AggregateRoot、ValueObject、Entity三个类,这几个类协同工作实现具体的HR业务。以培训为例,存在一个RecruitmentAggregateRoot、RecruitmentCandidateEnity与RecruitmentStatusValueObject,分别表示整个招聘流程、应聘者与应聘所处状态。
5. 每个微服务中,暴露的API接口基本上最后都是通过AggregateRoot来实现具体的功能,ValueObject与Entity并不会暴露给外部API。
好,首先把特定组织的因素去掉,得到HR行业的系统架构:
HR系统架构
1. 7个模块,分别是薪酬、绩效、招聘、培训、绩效、劳动关系、人力资源规划(把薪酬与绩效分离)
2. 每个模块中非常多的类都是继承自AggregateRoot、ValueObject、Entity三个类,这几个类协同工作实现具体的HR业务
3. 每个模块中,对外暴露的API接口基本上最后都是通过AggregateRoot来实现具体的功能,ValueObject与Entity并不会暴露给外部API。
再进一步,把HR的因素去掉,抽象称为IT系统架构:
IT系统架构
1. 整个系统划分为不同的模块
2. 每个模块由AggregateRoot、ValueObject、Entity三个部分组成,这几个部分协同工作实现具体的系统业务
3. 每个模块中,对外暴露的API接口基本上最后都是通过AggregateRoot来实现具体的功能,ValueObject与Entity并不会暴露给外部API。
继续,把IT的因素去掉,抽象称为基础架构:
系统架构
1. 整个系统由不同的模块组成
2. 每个模块由AggregateRoot、ValueObject、Entity三个部分组成,这几个部分协同工作实现具体的系统业务
3. 每个模块中,对外暴露的接口基本上最后都是通过AggregateRoot来实现具体的功能,ValueObject与Entity并不会暴露给外部接口。
到了这一步,可以看出点端倪来了。基础架构总结起来其实就两点:
1. 系统内按照业务领域划分模块,职责分离
2. 模块内通过AggregateRoot、ValueObject、Entity的紧密合作高内聚,模块间通过AggregateRoot把握访问权限实现低耦合
看到了没,这其实就是DDD的基本方法论,可以说是元方法论。
现在开始往基础架构灌入汽车领域的因素。第一步是灌入出行工具的因素:
出行工具系统架构
1. 整个系统由动力、制动、转向三个核心控制系统模块组成
2. 每个控制系统由AggregateRoot、ValueObject、Entity三个部分组成,这几个部分协同工作实现具体的功能。
3. 每个控制系统中,对外暴露的接口基本上最后都是通过AggregateRoot来与人交互,ValueObject与Entity并不暴露给人。
然后灌入马车的因素,小试一把,成为马车的架构:
马车架构
1. 整个系统由动力,制动、转向三个核心控制系统组成
2. 每个控制系统由AggregateRoot、ValueObject、Entity三个部分组成,这几个部分协同工作实现具体的功能。
3. 每个控制系统中,对外暴露的接口基本上最后都是通过AggregateRoot来与人交互,人不能直接操纵ValueObject与Entity。对于马车来说,在动力系统这个上下文中,AggregateRoot就是缰绳,Entity就是马,具体的速度就是一个ValueObject,人通过缰绳鞭策马来实现加速。
同样的,我们灌入汽车的因素,称为汽车的架构:
汽车架构
1. 整个系统由动力,制动、转向、安全四个核心控制系统组成
2. 每个控制系统由AggregateRoot、ValueObject、Entity三个部分组成,这几个部分协同工作实现具体的功能。
3. 每个控制系统中,对外暴露的接口基本上最后都是通过AggregateRoot来与人交互,ValueObject与Entity并不暴露给人。对于汽车来说,在动力系统这个上下文中,AggregateRoot就是油门,Entity就是发动机,具体的速度就是一个ValueObject,人通过踩踏油门来实现加速。
高潮来了,我们是六菱宏光!
六菱宏光架构
1. 整个系统由动力,制动、转向三个核心控制系统组成(没错,安全不是我的核心域!能跑就行!)
2. …
经过上述的乾坤大挪移,我们终于可以拿着六菱宏光的架构去造一辆车拉,能跑就行!
整个证明到此结束。有人可能觉得好无聊啊,跟证明1+1=2同样无聊。但问题是又有多少人能看懂1+1=2的证明呢?反正我是看不懂。这都不是关键,关键的地方在于基础架构的核心其实是回归业务。这是整个证明过程中最核心的一点,也是最容易被忽略,最难坚守的一点。还是那句话,无业务不IT,无架构不解决方案。