DDD:用 “四色原型” 进行 “聚合设计”
四色原型
在企业应用的上下文中,四色原型是领域模型的一种原型,原型的意思是指领域中的任何模型及其关系都可以抽象为“四色原型”。
四色原型可以用这句话进行描述:某个人(Party)的角色(PartyRole)在某个地点(Place)的角色(PlaceRole)用某个东西(Thing)的角色(ThingRole)做了某件事情(MomentInterval)。
图片示意
名词解释
- PartPlaceThing:简称PPT,用淡绿色表示,常见的PPT有:部门、岗位、人员、地点、物品等。
- Description:简称Des,用淡蓝色表示,主要用来对PPT进行描述,常见的Des有:部门类型、岗位层级、人员类型、地点区域、物品分类等。
- Role:用淡黄色表示,主要表示PPT在某个场景下扮演的角色,常见的角色有:财务类部门、管理类岗位、请假者、销售点、产品等。
- MomentInterval:简称MI,用淡红色表示,主要表示在一刻或一段时间内发生的一件事情,常见的MI有:部门移动、岗位移动、员工离职、产品销售等。
- MomentInteval:简称MIDetail,用淡红色表示,主要表示MI的明细,常见的MIDetail有销售明细、入库明细、出库明细等。
出差管理示例
根据四色原型进行聚合设计(四步曲)
第一步:识别模型
根据四色原型很容易识别出领域模型(见上图)。
第二步:识别关联
根据四色原型同样很容易识别出领域模型之间的关系(见上图)。
第三步:划分聚合
- MI和MIDetail是一个聚合,MI是聚合根。
- PPT是一个聚合,PPT是一个聚合根。如果Des只“描述”PPT,那么这个Des会作为一个值对象隶属于属于PPT所在的聚合。
- Des是一个聚合,Des是一个聚合根。前提你想“跟踪”Des关联的PPT。
- Role不属于聚合,Role是一个带状态的领域服务,Role采用装饰器模式装饰PPT。
划分结果
第四步:精简关联
- 去掉MI和Role之间的关联,改为仓储查询,根据需要让MI关联一个Role的快照(发生时刻Role的状态)。将关联改为仓储查询的理由是这样更加灵活,一个请假人有1W个请假单,没有必要设置这样的关联。让MI关联一个Role的快照的理由是MI很多情况要记录下发生时刻Role的状态,如:出差单要记录下发生时刻请假人的组织信息,而不是现在的组织信息。
- PPT和DES之间的关联可以根据自己的爱好酌情保留,我喜欢用仓储查询,这样更灵活。
- 去掉PPT和Role之间的关联,改为仓储查询。比如:用仓储查出PPT,然后将这个PPT实例注入到Role中。
精简结果
为什么销售单和销售单明细是一个聚合,而文章和评论不是一个聚合呢?
因为销售单是MI,销售单明细是MIDetail,因此他们是一个聚合;而文章是MI,评论也是MI,所以他们不是一个聚合。
备注
四色原型可以帮助我们做聚合设计,我相当于把聚合设计问题踢给四色原型分析了,本文还没有详细讨论如何识别领域中的四色原型。当然了,聚合设计还有其他规律可循,后面慢慢讨论吧。时间有限,后面我会用HappyFramework写个Demo。
今天还没有过多的谈“职责分配”的问题,四色原型可以完美的补充DDD关于职责分配的各种模式,我会放到下一个主题讨论。