DDD

DDD系列(三)领域对象及建模

Posted by YaPi on March 3, 2022

实体和值对象

实体和值对象都是领域对象的一部分。

  • 实体:主要由标识定义的对象被称为实体(entity),简单来说就是有id(不完全对)
  • 值对象:用于描述领域的某个方面而本身没有概念标识的对象

需要以ID来跟踪状态变化的对象为实体,否则为值对象。

资源库与持久化

什么是资源库?

为每种需要全局访问的对象类型创建一个对象,这个对象相当于该类型的所有对象在内存中的 一个集合的替身,通过一个众所周知的全局接口来提供访问。

简单来说,就是带有必要管理管理功能(增、删、查、改)的领域对象容器。

意义:

  • 提供了一个管理领域对象的简单模型
  • 使领域模型和持久化技术解耦
  • 屏蔽存储层的技术细节

对于java来说,可以简单看作对mapper层的封装。提供对外的数据管控功能,这样在替换持久层的时不会对 原始应用层产生影响

聚合

什么是聚合和聚合根? 聚合就是一组相关对象的集合,我们把它作为数据修改的单元。每个聚合都有一个根和一个边界。聚合根是聚合所 包含的一个特定的实体。对聚合而言,外部对象只可以引用根,而边界内部的对象之间则可以互相引用。

比如现实世界中的汽车。发动机、邮箱、轮胎可以看作是内部包含的对象。而汽车这个实体,可以看作是一个聚合根。 内部对象状态是具有关联性的,比如方向盘往左打,轮胎就会往左转,这个更改是一致的,也只能通过汽车这个 实体去更改,而不能直接去修改轮胎的状态。

也即是说,聚合是拥有事务一致性(强一致性)的领域对象组合。

聚合内的实体适用事务一致性,聚合之间适用最终一致性,不能脱离聚合根修改聚合内部对象。 聚合根有全局唯一标识,聚合内部实体只有局部标识。聚合根可以从资源库中获取,聚合内部实体不能。

如何判断实体是否属于同一个聚合?判断实体的状态是否是同步更改的。

领域服务

当领域中的某个重要的过程或转换操作不是实体或值对象的自然职责时,应该在模型中添加一个作为独立接口的 操作,并将其声明为领域服务。领域服务是无状态的。

简单来说,领域服务包含的是业务逻辑,与业务逻辑无关的操作不能放在领域服务,比如:事务处理、鉴权等。 并且,业务逻辑不属于实体或值对象。

应用层

定义软件要完成的任务,并且指挥表达领域概念的对象来解决问题。这一层也是与其他系统的应用层进行交互的必要 渠道。应用层要尽量简单,不包含业务规则或者只是,而只为下一层中的领域对象协调任务,分配工作,使它们 互相协作。

类比:现实生活的汽车。对于汽车这个领域对象来说,它有开门、关门、启动、加速等业务逻辑。但是它不能理解 “从家开到公司”这个需求。而司机能够协调处理这个需求。所以,应用层可以类比司机的作用。

可以包含非业务逻辑。比如:事务控制、鉴权控制、任务等

适配层

mvc中的controller、事件监听、远程服务调用

领域事件

什么是领域事件?

  • 领域中发生的任何领域专家感兴趣的事情
  • 领域事件一般由聚合产生
  • 领域事件不是技术概念

事件风暴建模法

事件风暴是一种快速,轻量级且未得到充分认可的群体建模技术。在DDD框架中,就像我们平时开发前要先出需求方案、技术方案一样,有一件必须的流程,就是事件风暴,但它与需求方案、技术方案又是不同的

  • 需求方案是业务人员提出,产品人员设计,开发人员去理解
  • 技术方案是开发人员设计,然后产品去理解

事件风暴呢,就是业务方,产品、技术人员,一起设计,把所有的命令、实体、规则、事件列出来,达成共识,使产品开发的整个过程,相关人都有参与进来

一般我们把事件风暴划分为3个流程

  1. 事件风暴
  2. 划分聚合
  3. 寻找限界上下文

事件风暴是一个团队活动,领域专家和项目团队成员通过头脑风暴的形式,罗列出领域中所有的领域事件,这时我们就得到了一个领域事件集合,然后为每一个事件标注出导致该事件的命令,再为每一个事件标注出命令的发起方的角色。 命令可以是用户发起,也可以是第三方系统调用或者定时器触发等。最后对事件进行分类,整理出实体、聚合、聚合根以及限界上下文等,在限界上下文边界内构建领域模型

参考

https://www.bilibili.com/read/cv9263091/