DDD 领域驱动设计落地实践系列:战略设计和战术设计(二)
业务分析
1、事件风暴
通过事件风暴的方法可以实现快速分析和分解复杂的业务领域,分析并提取出对应的领域模型。事件风暴是早 2013 年提出来的,通过组织领域专家、以及项目团队成员在一起通过头脑风暴的方式,通过梳理业务领域中所有的领域事件以及领域事件的参与者以及输入。
参与者
主要包括领域专家、DDD 专家、架构师、产品经理、项目经理、开发人员以及测试人员等
实际活动
当把参与者集合在一起之后,大家需要通过头脑风暴的方式梳理当前的业务域问题。比如某个业务动作或者行为是否会触发下一个业务动作,这个动作(领域事件)的输入和输出是什么,是谁(实体)发出的什么动作(命令),触发了这个动作,这些我们都需要梳理清楚。
我们以大家最熟悉的电商系统来举个栗子,在电商业务中有一个重要的环节就是物流。因此物流是电商业务的重要业务子域。当用户下完订单之后,在仓储领域就需要生成对应的货物拣货单,系统根据拣货单中的货物给不同分区的仓内作业人员生成对应的拣货任务,作业人员根据对应的拣货任务进行货品的拣取,并放入相应的货物容器中。最终将所有订单商品在拣货完成后进行合流,进行校验,最终形成包裹再进行后续的配送流程。
那么在这个流程当中,我们就会涉及到的实体就有订单、拣货单、拣货任务、用户、容器等,对应的值对象为地址信息。领域事件为拣货单生成、拣货任务生成。
领域建模
在我看来,领域建模实际上是整个DDD领域驱动设计中最重要的环节。对上,好的领域模型说明对业务流程的梳理以及业务领域的抽象做得好。对下,高内聚低耦合的领域模型可以直接决定微服务设计的质量和水平。
1、找出实体和值对象
经过全盘的业务梳理之后,我们可以在业务对象中找到对应的实体以及值对象,这里面就会牵扯到哪些领域对象设计为实体,哪些领域对象设计为值对象。主要还是根据实际的业务特征来决定。
2、构建聚合
通过业务梳理,我们找到了业务下所有的实体以及值对象,接下来我们就要构建聚合了。在构建聚合之前,我们需要先从实体集合中找到聚合根,这就好比打仗的时候讲究擒贼先擒王,王擒到了之后,归属于下面的小兵就会乖乖就范了。
那么我们应该怎么判断一个实体它就是聚合根呢?主要是看这个实体是不是有专门的模块来进行维护,自身是不是有完整的独立的生命周期以及是不是有全局的唯一ID。通过这几个判断条件我们很容易找到对应的聚合根,如下图所示,在仓内进行作业的任务,其中拣货单就是一个聚合根,满足上述的几个条件,同时可以将和其有业务关联的实体例如货物、拣货容器等归并到拣货单,最终形成拣货聚合。
3、划分聚合到边界上下文
首先我们需要将之前梳理出来的领域事件,事件流转的触发命令都全部罗列出来,在这个过程中提取出产生业务行为的对象,就是前文所说的实体。如前面所说的物流域,库存、容器。在这个过程中我们需要找出对应的实体以及值对象,同时在这些实体中找出聚合根,将存在存在紧密业务逻辑关系的聚合根、实体以及值对象划分到一起形成聚合,再根据之前划分的边界上下文将多个聚合划分到限界上下文中。
战术设计
不同于战略设计的高屋建瓴,战术设计是从实际的技术角度出发,它更加侧重于领域模型的技术实现,按照领域模型完成微服务的开发以及落地。从某种意义来说,战略设计实际就是战术设计的输入。在战术设计中会有聚合、聚合根、实体、值对象、领域服务、领域事件的代码实现,通过将这些领域对象映射到代码中实现设计以及系统的落地。在这个阶段,我们需要梳理微服务的边界以及边界内的领域对象以及它们之间的关系,并且可以实际的将这些领域模型确定在哪些代码模块中以及微服务分层中的具体位置。
通过DDD按照一定的规则对业务领域进行细分,可以将问题范围限定在指定的边界中,因此我们可以在这个边界内建立领域模型,而后再通过代码实现领域模型,从而解决相应的业务问题。
因此在战术设计阶段,我们有个重要的事项需要去完成,一个是微服务的领域对象分析与边界划分,另一个是微服务的结构分层。
微服务领域对象分析与边界划分
在战略设计阶段,我们已经构建的业务领域模型,领域模型中包含了实体、值对象、聚合根。在上文中我们实际已经根据一些业务域进行了聚合的划分,那么在此处我们需要根据不同的聚合以及已有的限界上下文继续划分微服务。有的微服务会包含多个聚合,有的微服务只有一个聚合。
微服务结构分层
在传统的工程代码结构中,大都采用MVC的工程结构。但是随着微服务时代的来临,传统的工程结构不能满足快速变化的业务需求。另外随着DDD领域驱动设计的落地,需要对于微服务的工程结构有更进一步的进化和升级。
Eric Evans在《领域驱动设计:软件核心复杂性应对之道》文中提出了传统的四层结构,但是实际上存在一定的问题。在DDD领域驱动设计中,领域层应该是核心层,但是传统的四层结构中基础层却处在核心位置,有点本末倒置的感觉。所以应该采用以领域层为核心的新的四层结构的方式优化原有的结构,实现对于基础层的解耦。
基础层:实际就是未微服务的其它层提供基础的通用技术支撑,如Redis、MQ以及数据库等,常见的就是数据库持久化可以放在这层当中。
用户接口层:负责向用户展示信息以及转化用户请求意图,在前后端分离的当下,可以实现在后端服务不变的情况下适配不同的用户前端的作用。
应用层:可以理解为实现领域对象以及多个聚合的服务编排以及组合,不应该有过多的业务逻辑。
领域层:领域层实际就是整个微服务的核心,在这其中涉及到领域对象的㛑状态变化以及领域规则。领域层主要包括实体、值对象、聚合根以及领域服务等。
当然实际上还有其他的分层结构比如五层分层结构、六边形分层结构。
总结
本文主要围绕DDD领域驱动设计落地时间的三大过程进行了阐述,详细说明了战略设计阶段以及战术设计阶段的输入和输出。希望对于大家怎么去实施DDD领域驱动设计有一个方向的指引,后面的文章将继续深入阐述DDD具体落地实践的细节和一些建议。
文章转自公众号:慕枫技术笔记