自我理解的洋葱模型

洋葱模型解析与应用的深度理解

前言

要理解洋葱模型,首先需要对其结构有一个简单的了解。

正文

洋葱模型的结构如下图所示:

这是一种被称为ddd的洋葱模型。

最内层是领域模型。

为什么是领域模型呢?这是核心的业务逻辑模型。

领域模型的作用是实现我们的业务逻辑模型,这是非常重要的一环。

接下来看看领域服务(domain services)是什么?

当涉及多个领域模型时,就需要领域服务来进行关联。

每个领域模型就是一个聚合根。

领域模型和领域服务实现了我们的核心业务,也就是领域层。

实际上,我们的一个业务例子,应该调用一个领域模型或领域服务的方法,而不是调用多个。

因为领域层已经实现了核心领域逻辑业务,将多个领域逻辑业务组合在一起也是业务逻辑,因此应该不放在上层。

接着向上看,为什么上面还有一个应用服务(application service)呢?理论上领域层已经实现了业务逻辑。

应用服务是用于数据组装和校验的。

应用服务基本上做两件事:

  1. 单纯查询数据,当需要查询数据时,因为这不涉及领域业务。

有人可能会问,为什么查询不涉及领域业务呢?因为查询不会进行任何修改,本质上只是对数据库的查询,不涉及任何业务。

  1. 为领域层提供基本数据校验和数据查询

基本数据校验:

例如,如果需要修改用户A的姓名,那么应用服务层需要做的事情是检索用户A,验证该用户是否存在,如果不存在则抛出业务异常。

数据查询:

例如,领域层有一个需要修改用户电子邮件的方法:

void EditEmail(string email, string code)
{
   if(Code == code)
   {
      Email = email;
   }else
   {
     throw new Exception();
   }
}

该方法需要传入电子邮件和验证码,验证码是用于校验的。

可能应用服务方法是这样的。

void EditEmail(string email)
{
    1. 获取验证码
    2. 调用领域层EditEmail方法
}

这只是一个假设,也可能需要获取其他服务的信息。

有人可能会产生疑问,这是初学者的疑惑。

例如,业务案例是这样的,在修改电子邮件后,需要更新领域B的字段C,此时B领域在另一个B服务中。

这应该在应用服务中这样写吗?

void EditEmail(string email)
{
    1. 获取验证码
    2. 调用领域层EditEmail方法
    3. 调用服务B更新字段C
}

还是在领域层中:

void EditEmail(string email, string code)
{
   if(Code == code)
   {
      Email = email;
      // 调用服务B更新字段C
   }else
   {
     throw new Exception();
   }
}

这应该在领域层实现,因为这本质上是业务逻辑的一部分,涉及到修改,保持一致性和业务完整性。

是否放在领域层取决于它是否是该领域的业务逻辑。

在外部环就是具体的实现,例如具体的服务、数据库、作业等。

应用服务也只是数据的组装和校验,没有具体的实现,真正的实现在基础设施。

这几层构成了一个应用程序。

接着再向外看,就是Kibana等外部依赖服务了。

这实际上实现了控制反转。

业务核心逻辑处于最高层,具体的实现位于较低层,高层不依赖低层,而具体实现依赖高层。

为什么要这样做呢?因为我们开发项目的目的是解决业务问题,业务是核心逻辑。

当需要替换底层时,可以立即进行替换,而核心逻辑则无需更改。

当需要更改核心逻辑时,而又无需关心底层逻辑,因为高层不依赖低层。

最重要的一点是,洋葱模型就是洋葱模型,不要与微服务、cqrs、eventbus等挂钩,那是不同的事情。


简单的自我理解

未经允许不得转载:大白鲨游戏网 » 自我理解的洋葱模型