DDD的事件风暴第三个阶段“领域建模”时,我们会根据场景分析过程中产生的领域对象,比如命令、事件等之间关系,找出产生命令的实体,分析实体之间的依赖关系组成聚合,为聚合划定限界上下文,建立领域模型以及模型之间的依赖。
本阶段的
- 输入: 上阶段DDD事件风暴 - 业务场景分析的业务领域知识和场景分类清单
- 产出物:聚合模型和限界上下⽂地图
如果说场景分析是一个发散的过程,各种角色各抒己见,大家一起分析用户旅程;那么领域建模就是一个收敛的过程。
在这一步中,会由对DDD有足够了解的架构师、开发人员来主导完成。而且见仁见智,收敛的结果很可能因人而异,不过建模结果并没有绝对的好坏,只要能适应当前场景,而且模型还会在后续的知识循环、迭代中不断完善,最终不断逼近最优解。
领域建模可以按这三个步骤进行:
- 找出实体、值对象等领域对象;
- 将这些领域对象形成聚合,确定聚合根;参考“理解DDD中的实体、值对象、聚合根”
- 根据业务、语义边界等因素,定义限界上下文;参考“理解DDD中的限界上下文”
本文用到的图例如下:
案例一:请假业务场景 领域建模
1、找出领域对象
场景分析梳理出了事件、命令,接下来就要分析并找出产生这些命令、领域事件的实体和值对象。
下图为在请假、审批系统找出的实体、值对象(图中都是绿色):
2、定义聚合
定义聚合前,先找出聚合根,聚合根可以管理聚合中的实体,所以可以将请假单、人员作为两个聚合根;
然后找出与聚合根紧密依赖的实体和值对象,请假单聚合根下包含审批意见、审批规则,人员聚合根下包含组织关系。
那么剩下的刷卡明细、考勤明细、考勤统计该怎么办呢,这也是一类典型的场景,即几个实体、值对象之间相互独立,找不出聚合根,却又共同完成一项功能,具有很高的业务内聚性。对于这种情况,仍然可以采用DDD的分析设计方法,将这些实体、值对象组成一个没有聚合根的聚合,但由于没有聚合根,实体的管理就交给领域服务了。
于是现成了请假、人员、考勤三个聚合:
- 请假聚合中,可以将审批规则作为值对象,因为它是来自人员聚合的副本;
- 人员聚合中,人员和组织关系都作为实体,没有值对象;
- 考勤聚合也没有值对象。
3、定义限界上下文
- 人员组织关系聚合和请假聚合共同完成请假的业务功能,所以可以将两者划分为请假限界上下文;
- 考勤聚合单独构成考勤限界上下文。
案例二:用户中台 领域建模
1、找出领域对象
用绿色贴纸表示实体。
通过分析用户中台的命令和事件等行为数据,提取了产生这些行为的用户、账户、认证票据、系统、菜单、岗位和用户日志七个实体。
2、找出聚合根
根据聚合根的管理性质从七个实体中找出聚合根,比如,用户管理用户相关实体以及值对象,系统可以管理与系统相关的菜单等实体等,可以找出用户和系统等聚合根。
然后根据业务依赖和业务内聚原则,将聚合根以及它关联的实体和值对象组合为聚合,比如系统和菜单实体可以组合为“系统功能”聚合。
按照上述方法,用户中台就有了系统功能、岗位、用户信息、用户日志、账户和认证票据六个聚合。
3、划定限界上下文
-
根据用户域的上下文语境,用户基本信息和用户日志信息这两个聚合共同构成用户信息域,分别管理用户基本信息、用户登录和操作日志。
-
认证票据和账户这两个聚合共同构成认证域,分别实现不同方式的登录和认证。
-
系统功能和岗位这两个聚合共同构成权限域,分别实现系统和菜单管理以及系统的岗位配置。
根据业务边界,我们可以将用户中台划分为三个限界上下文:用户信息、认证和权限。