14.构造块领域模式介绍

2022-08-19  本文已影响0人  鸿雁长飞光不度

如何创建领域模型并和分析模型绑定,DDD使用了包含若干构造块的模式的语言,来实现领域模型,这是一种采用面向对象的方式,是第5章里面提到领域模型实现方式的一种,其他的方式可以按实际情况采用。

image.png

上图展示了领域模型中的许多概念和它们的关联关系,下面是详细介绍。

1. 领域建模相关

下面概念表示了问题域的逻辑,表述了模型对象的关联关系。

  1. 实体:表示领域中的概念,由身份而不是特性来定义,是业务中承担行为的对象,比如产品、订单。

[图片上传中...(image.png-a82323-1660748013800-0)]

这里提到用一个实体定义一个基类,提供默认的构造方法、相等比较方法(比较id)、hashcode方法,其他的实体集成并重载部分方法。

  1. 值对象:用于描述领域实体的特性,具有不变性,没有唯一身份标识、

案例:『数字』,『日期』,『邮寄地址』,这是用于度量或者描述领域中某件东西的概念。比如年龄(出生了多少年)、名字(称呼)。

image.png

值对象和实体的选择(描述,是,是,不是的回答用值对象)

是领域的一个东西,还是只是描述或者度量东西?
如果是描述,能否满足值对象的特征?
将该概念建模成实体是不是只是持久化机制考虑?
如果建模成实体是不是因为拥有唯一标识,需要关注实体的个体性,并需要在声明周期跟踪变化。?

  1. 领域服务

表示一个无状态的操作,用于实现某个特定的领域任务,某些操作不适合放在聚合和值对象上就用领域服务,比如计价、身份认证。

过度使用领域服务导致领域贫血模型:表现现象为所有的业务逻辑都在领域服务中,而不是实体和值对象中

4.模块

image.png

通过模块(包或者命名空间实现)将领域模型的不同领域对象分组,实现高内聚低耦合,让不同部分可以被单独理解。

2.生命周期模式

1.聚合

image.png

业务中实体和值对象组合用于描述领域模型中复杂的关联关系,比如上图,我们很难同时保持上述复杂关联关系的并发性和一致性,比如我们不能仅仅因为一个较早的订单状态发生变化,就阻止用户更新账户的地址,因为这两个行为不相关,没有必要保持并发和一致性,我们可以把不同实体按照相关性和关联性划分成聚合,每次都通过聚合根修改数据,多个聚合之间用聚合根id引用,而不能直接引用聚合的数据。

image.png

比如两个人同时要修改同一个产品的颜色和尺寸,产品是聚合根,这里要保证并发和一致性,不能丢失数据,可以提前对产品id加锁的方式解决,也可以在更新数据的时候通过数据库的乐观锁形式比如update xx where id = 1 and color = before_color这样的断言,更新行数为0提示更新失败。

聚合的划分不能仅仅通过入口,通过入口划分后要考虑不变条件

image.png

这里再次划分成为电子钱包地址簿聚合,这样修改地址和信用卡可以同时进行,修改信用卡比如通过电子钱包这个聚合根实现。

在举一个例子:申请单和申请明细条目,比如创建了一个申请单,在申请单状态是等待审核之前或者被驳回时是可以修改申请内容的,正在审核中或者审核完成是不能修改的,这里修改申请明细就需要通过申请单这个聚合根来修改。

聚合必须总是处于一致性状态,相当于原子单元、聚合根会充当入口点,聚合外部的对象不能保留对聚合内部对象的引用

2.工厂

对象或者值对象创建比较复杂时,应该使用工厂,工厂确保对象创建之前满足所有的不变性条件,不复杂的时候使用简单的构造器方法。

3.存储库

聚合内部是原子操作保持一致性,需要将聚合变更的数据持久化,聚合和存储库用ORM框架可以关联做到数据存储和读取。

image.png

3.显露模式

1.领域事件

当聚合或者实体发生变化的时候,可以将事件发布,其它方可以根据自己需要监听,比如购物车发生加购或者减购的时候要为用户推荐不同的菜,加减商品就可以作为领域事件发布,推荐系统去监听。领域事件也可以作为聚合之间通信的手段。

2.事件溯源

比如对于订单状态来说,订单状态已创建、已付款、已发货、配送中,可以将每次订单变化的事件都记录下来,有利于做分析溯源,比如订单为什么减少了?

上一篇 下一篇

猜你喜欢

热点阅读