《实现领域驱动设计》读书笔记摘抄(7)—— 领域服务

Administrator 564 2022-03-23

第7章 领域服务

本章学习路线图

  • 学习如何在领域模型中使用领域服务
  • 学习什么时领域服务
  • 学习何时应该使用领域服务
  • 从SaaSOvation项目的两个例子中学习如何对领域服务进行建模

领域中的服务表示一个无状态的操作,它用于实现特定于某个领域的任务。当某个操作不适合放在**聚合(10)**和值对象(6)上时,最好的方式便是使用领域服务了。

什么是领域服务

当领域中的某个操作过程或转换过程不是实体或者值对象的职责时,我们应该将该操作放在一个单独的接口中,即领域服务。请确保该领域服务和通用语言是一致的;并且保证它是无状态的;并且能够明确地表达限界上下文中的通用语言(1)。通常来说,领域模型主要关注于某个特定于某个领域的业务,同样,领域服务也具有相似的特点。

  • 执行一个显著的业务操作过程
  • 对领域对象进行转换
  • 以多个领域对象作为输入进行计算,结果产生一个值对象

需要明确最后一点,这是领域服务很常见的应用场景,它可能需要多个聚合作为输入。

请不要将领域服务和应用服务混杂在一起。在应用服务中并不会处理业务逻辑,但是领域服务恰恰是处理业务逻辑的。简单来讲应用服务是领域模型的客户方,进而也是领域服务的客户方。

例如通过RPC、MoM实现的SOA服务等这些远程客户端与某个业务系统交互的场景,都不是领域服务。

请确定你是否需要一个领域服务

请不要倾向于将一个领域概念建模成领域服务,而是只有在有必要的时候才这么做。过度地使用领域服务将导致贫血领域模型,即所有的业务逻辑都位于领域服务中。

书中以“系统必须对User认证,并且只有当Tenant处于激活状态时才能对User进行认证”为例,逐步给出使用领域服务要优于将认证操作放在实体中。

UserDescriptor userDescriptor = DomainRegistry
    .authenticationService()
    .authentication(aTenantId, aUsername, aPassword);

最终使用上述方式,将所有的认证细节放在领域服务中,而不是应用服务。在需要的情况下,领域服务可以使用任何领域对象来完成操作,包括对密码进行加密。客户端不需要知道任何认证细节。

建模领域服务

本章节以前一章节中用户认证服务为线索,给出了具体的实现过程,并给出了充分的解释以及这种方法的好处(如解耦、扩展和依赖注入),建议结合书中代码阅读

测试领域服务

我们希望那个从客户端的角度对领域服务进行建模,同时我们也希望测试能够反映出领域服务的使用方式。

书中对上一章节认证服务的实现进行充分测试,建议结合书中代码阅读