# DDD 建模 —— 架构师总说的风暴模型是什么?

作者:小傅哥
博客:https://bugstack.cn (opens new window)

沉淀、分享、成长,让自己和他人都能有所收获!😄

大家好,我是技术UP主小傅哥。

四色建模(风暴事件)是整个 DDD 这套软件设计方法中用于工程拆分界限上下文的非常重要的实践手段。通过建模过程快速识别业务领域中的关键事件和核心流程,也是在这个过程中设计出领域对象的,为后面详细设计和代码开发做指导。

你可以把整个过程理解为,为工程开发提供面向对象设计,涵盖;领域拆分、界限串联、功能聚合。所以相比Service + 数据模型的贫血开发方式,DDD 前期需要付出更多的设计成本,但对于软件的长周期迭代,这样的好处是非常大的。

# 1. 建模目的

工程的建模的目的是为了我们做工程开发时提供指导方案,就像一栋大楼的设计蓝图一样,也像一个超市中会有不同品类的货架,需要提前规划好。所以你需要在工程开发时所需的各类核心内容,都会在建模中体现,如:分几个包、有哪些核心对象、要串联什么流程、有哪些核心业务要实现、过程中与外部服务的交互。

为了达成讨论的共识,避免每个人都有不同的标准和词汇,我们通常会使用 DDD (领域驱动设计)提供的专门建模方法和统一的名词进行设计。DDD 的统一建模语言不涉及具体的技术编码,具有较强的通用性,因此可以让产品、研发、测试、架构师等人员一起参与讨论建模过程,促进跨职能的沟通和协作。如:领域、领域模型(实体、聚合、值对象)、领域服务、端口适配器、仓储、界限上下文、领域编排等名词。这在上一节已经做了相关的解释。

# 2. 如何建模

DDD 的建模过程,是以一个用户为起点,通过行为命令,发起行为动作,串联整个业务。而这个用户的起点最初来自于用例图的分析。用例图是用户与系统交互的最简表示形式,展现了用户和与他相关的用例之间的关系。通过用例图,我们可以分析出所有的行为动作。

在 DDD 中用于完成用户的行为命令和动作分析的过程,是一个四色建模的过程,也称作风暴模型。在使用 DDD 的标准对系统建模前,一定要先了解 DDD 的操作手段,这样才能让产品、研发、测试、运营等了解业务的伙伴,都能在同一个语言下完成系统建模。

上图是整个四色建模的指导图,通过寻找领域事件,发起事件命令,完成领域事件的过程,完成 DDD 工程建模。

  • 蓝色 - 决策命令,是用户发起的行为动作,如:开始签到、开始抽奖、查看额度等。
  • 黄色 - 领域事件,过去时态描述。如:签到完成、抽奖完成、奖品发放完成。它所阐述的都是这个领域要完成的终态。
  • 粉色 - 外部系统,如你的系统需要调用外部的接口完成流程。
  • 红色 - 业务流程,用于串联决策命令到领域事件,所实现的业务流程。一些简单的场景则直接由决策命令到领域事件就可以了。
  • 绿色 - 只读模型,做一些读取数据的动作,没有写库的操作。
  • 棕色 - 领域对象,每个决策命令的发起,都是含有一个对应的领域对象。

👩🏻‍🏫敲黑板 综上,上图左下部分的示意图表达的是:“一个用户,通过一个策略命令,使用领域对象,通过业务流程,完成2个领域事件,调用1次外部接口”的过程。我们在整个 DDD 建模过程中,就是在寻找这些节点。

# 3. 超市举例

我们先通过一个真实场景的案例,代入下 DDD 四色建模的术语,这样可以更有益大家对四色建模理解。这个场景是一个在超市购物的场景。想象下,一个男人,得到了老婆的"命令",去大超市拿着空的购物车,推进去一圈圈的走,最终完成购物打车回家。

  • 脑子中的想法,是媳妇给下达的指令。我们可以理解为决策命令。行为人带着决策命令来到超市。
  • 购物车是一种实体,需要填充数据的实体。行为人,带着实体,进入到超市中从各个货架选购商品,装入购物车。选购商品为业务流程,装满的购物车为领域事件。也就是最终态,完成媳妇交代的任务。而手里的烟,则是另外一个领域事件。也就是说,一次的行为动作可以完成多个领域事件。
  • 最终购物完成后,打车回家。则是下一个领域流程。通过把从加入出门、做地铁、进超市、采购、打车回家,一整条领域串联起来就是领域编排。

综上,DDD 的领域建模过程,就是一种真实的场景头脑风暴过程,所以可以让更多人同时讨论,拆分出各项领域的边界和领域模型。

# 4. 业务案例

接下来,我们在以一个真实的业务场景来分析系统的四色建模过程:

# 1. 产品诉求

如图,是一个复杂的营销抽奖场景玩法需求,涵盖了;活动配置签到&奖励活动账户抽奖策略「责任链+规则树」库存扣减抽奖满N次后阶梯抽奖等。面对这样的复杂系统,非常适合使用 DDD 落地。

分析需求;

  1. 整体概率相加,总和为1或者分值计算,概率范围千分位
  2. 抽奖为免费抽奖次数 + 用户消耗个人积分抽奖
  3. 抽奖活动可给用户分配可抽奖次数,通过点击签到发放
  4. 活动延伸配置用户库存消耗管理,单独提供表配置各类库存 用户可用总库存、用户可用日库存
  5. 部分抽奖规则,需要抽奖n次后解锁,才能有机会抽取
  6. 抽奖完成增加(运气值/积分值/抽奖次数)记录,让用户获得奖品。
  7. 奖品对接,自身的积分、内部系统的奖品
  8. 随机积分,发给你积分。
  9. 黑名单用户抽奖,则给予固定的奖品。

# 2. 用例图

根据业务需求画系统用例图;

  • 用例图(英语:use case diagram)是用户与系统交互的最简表示形式,展现了用户和与他相关的用例之间的关系。通过用例图,人们可以获知系统不同种类的用户和用例。用例图也经常和其他图表配合使用。
  • 用例图,也可以等同于是用户故事(英语:User story)(软件开发和项目管理中的常用术语),主旨是以日常语言或商务用语撰写句子,是一段简单的功能表述。以客户或使用者的观点撰写下有价值的功能、引导、框架来与使用者进行互动,进而推动工作进程。可以被认为是一种规格文件,但更精确而言,它代表客户的需求与方向。以该用户故事来反应对象在组织内的其工作职责、范围、需要进行的任务等。用户故事在敏捷开发方法中用来定义系统需要提供的功能和实现需求管理。
  • 尽管用例本身会涉及大量细节和各种可能性,用例图却能提纲挈领地让人了解系统概况。它为“系统做什么”提供了简化了的图形表示,因此被誉为“搭建系统的蓝图”。

# 3. 寻找领域事件

接下来,大量的时间,都是在挖掘领域事件。这个过程就是一堆人头脑风暴的过程,避免错失流程节点。

  • 根据产品 PRD 文档,一起开会梳理有哪些领域事件。其实大多数领域事件一个人都可以想到,只是有些部分小的场景和将来可能产生的事件不一定覆盖全。所以要通过产品、测试、以及团队的架构师,一起讨论。
  • 像是整个大营销的抽奖会包括如图所列举的事件。在列举这个阶段,你用在乎格式。也可以是每个人准备好黄色便签纸,想到一个就贴到黑板上一个,只是穷举完成。—— 实际做DDD中,也是这样用便签纸贴黑板,所以用不同的颜色做区分。

# 4. 识别领域角色和对象

在确定了领域事件以后,接下来要做的就是通过决策命令串联领域事件,并填充上所需要的领域对象。这块的操作,新手可以分开处理,如先给领域事件添加决策命令、执行用户和领域对象,最后再串联流程。就像 事件风暴定义 中的示意一样。

  • 首先,通过用户的行为动作,也就是决策命令,串联到对应的领域事件上。并对复杂的流程提供出红色的业务流程。
  • 之后,为决策命令添加领域对象,每一个领域在整个流程中都起到了至关重要的作用。

# 5. 划分领域边界

有了识别出来的领域角色的流程,就可以非常容易的划分出领域边界了。先在事件风暴图上圈出领域边界,之后在单独提供领域划分。

# 5.1 圈出领域

# 5.2 领域边界

  • 到这步咱们就可以获得整个项目中 DDD 的领域边界划分了。之后再往下就是具体的每个领域对象的详细设计和流程设计。