基于事件驱动架构构建微服务第2部分:领域对象和业务规则

Posted dotNET跨平台

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于事件驱动架构构建微服务第2部分:领域对象和业务规则相关的知识,希望对你有一定的参考价值。

原文链接:https://logcorner.com/building-microservices-through-event-driven-architecture-part2-domain-objects-and-business-rules/

在本文中,我将实现领域模型:

  • EduSync.Speech.Domain

这是包含核心域的最内层。它包含我们的领域对象和业务规则。并定义我们的外部接口。

不允许使用数据库、网络连接、文件系统、UI或特殊框架。

核心领域对自身以外的任何事物一无所知。

这些依赖项及其实现使用接口注入到我们的核心域中。

在上一步结束时,我们最终得到了一个贫血领域模型。所以让我们从丰富它开始。

充血领域模型

贫血领域模型是DDD世界中的一种反模式,因此在本节中,我将使用值对象将领域模型与数据契约分离。

贫血领域模型是一种领域模型,其中数据和对该数据的操作彼此分离。换句话说,只有属性的类和处理这些属性的方法位于另一个类中。

因此,这些其他类既可以读取数据,也可以修改数据。所以领域类必须有public setter。这是缺乏封装反模式。

让我们从验证Title开始。

我的第一个测试是:Title长度必须大于10个字符且小于60个字符:

测试将失败,因此让我们实现Title验证:

Title值对象

实体和值对象的主要区别在于如何识别它们。

实体由引用相等和标识相等标识。

值对象由引用相等和结构相等来标识。

  • 引用相等:如果两个对象引用内存中的同一个对象,则它们相等

  • 标识相等:如果两个对象具有相同的标识,则它们相等

  • 结构相等:如果两个对象的所有成员都相等,则两个对象相等

实体具有Id字段并且是可变的,而值对象没有Id字段并且是不可变的。

值对象没有实体就没有意义,它必须属于一个实体。

考虑以下情况:

  • 2辆相同型号、相同颜色、相同年龄等的车辆……总是2辆不同的车辆,因为每辆车都有自己的标识:车辆是一个实体。

  • 2个所有字段都相等的地址(相同的街道号码、相同的城市、相同的国家,等等)是完全相同的地址:地址是一个值对象。

Title的第一个实现如下所示:

请记住,值对象由引用相等和结构相等来标识.

所以右键单击Title类并选择生成 Equals和GetHashCode。

Title只有一个值,因此选择它并单击确定

Title现在是一个值对象,它的最终实现看起来像这样

这是Title值对象的单元测试。如果它们具有相同的值,我应该验证2个标题是否相等,如果不是,则不同

URL值对象

验证Url的所有逻辑都在名称为UrlValue的值对象中实现

Type值对象

验证SpeechType的所有逻辑都在名称为SpeechType的值对象中实现

Speech领域对象如下所示:

实体和聚合

请记住,实体由引用相等和标识相等标识并具有Id字段。因此,让我们创建一个基本实体类:Entity,并在Id字段上生成Equals和GetHashCode。如果2个实体E1和E2具有相同的id,则 E1==E2应该返回true

DDD聚合是可以作为单个单元处理的领域对象的集群。例如订单及其订单项,它们将是单独的对象,但将订单(及其订单项)视为单个聚合非常有用。

聚合应该始终处于有效状态,并且每个聚合都有一个根是一个实体,不属于该聚合的类只能引用聚合根。

因此,让我们创建一个继承自Entity的基类AggregateRoot,我将其设为泛型,因为T是Id字段的类型,并且它可以根据这些实体而变化 

领域事件

领域事件通过避免直接调用来实现有界上下文之间的通信。所以一个有界上下文B1引发一个事件,一个或多个有界上下文B2…Bn对此事件的子订阅方应该处理该事件以使用它。

因此,让我们创建一个基类DomainEvent 

但是在这里,由于我实施事件溯源的策略,我的有界上下文产生的所有事件都将保存在我的事件存储中。对这些事件感兴趣的其他有界上下文、服务或其他程序将必须订阅服务总线。

比如我每次创建一个新的Speech,然后我都会创建一个SpeechCreatedEvent事件

SpeechCreatedEvent类必须从DomainEvent基类继承 

聚合根的最终实现将如下所示: 

因为Speech实体是聚合根,所以让我们继续从AggregateRoot继承它,Speech实体的Id字段是一个 Guid

让我们添加一些测试来覆盖 domainEvents 

LogCorner.EduSync.Speech.Application和LogCorner.EduSync.Speech.Domain是100%的代码覆盖率 

欢迎关注我的个人公众号”My IO“

以上是关于基于事件驱动架构构建微服务第2部分:领域对象和业务规则的主要内容,如果未能解决你的问题,请参考以下文章

基于事件驱动架构构建微服务第1部分:应用程序特定的业务规则

基于事件驱动架构构建微服务第9部分:处理更新

基于事件驱动架构构建微服务第11部分:持续集成

基于事件驱动架构构建微服务第15部分:SPA前端

基于事件驱动架构构建微服务第3部分:Presenters, Views和Controllers

基于事件驱动架构构建微服务第14部分:查询API