域服务是域模型的一部分吗?

时间:2017-08-03 22:20:08

标签: domain-driven-design

根据DDD,服务是否是域模型的一部分?如果我们谷歌搜索“ddd洋葱架构”,我们通常可以看到最内层被称为“域模型层”,第二层是“域服务”,例如http://tidyjava.com/onion-architecture-interesting/。但是在https://en.wikipedia.org/wiki/Domain-driven_design和DDD书中我们看到实体,价值对象和服务都表达了模型并且是模型元素。如果实体,价值对象和服务都是域模型的一部分,我们应该如何调用这两层洋葱:模型(实体+价值对象)和服务(我有时会这样做)?但如果所有这些都是域模型的一部分,那么这种命名似乎并不准确。

2 个答案:

答案 0 :(得分:4)

  

域名服务是域模型的一部分吗?

是的,但也没有。

the blue book中,域服务在第五章中描述;紧跟实体和价值类型之后。埃文斯写道

  

在某些情况下,最清晰,最实用的设计包括概念上不属于任何对象的操作。我们可以遵循问题空间的自然轮廓,而不是强制解决问题,并在模型中明确包含服务....

     

服务是作为一个独立于模型中的接口提供的操作,不包含任何状态....

     

接口是根据域模型的其他元素定义的。

但域服务的实现并不总是存在于域模型本身中。

在某些情况下,域服务实际上充当服务提供者,需要连接到基础架构以执行其角色(例如,将消息发送到另一个进程)。因此,域模型定义了提供者接口,该接口的实现被传递给它(例如,作为聚合根上的方法的参数),然后模型决定是否/何时调用该接口上的方法。

  

实体和值对象是否可以在域服务的接口上具有编译时依赖性?它们(域服务的实体,值对象和接口)是否在域模型的同一层中?

是的,是的。例如,这是第7章中的运送应用程序的an online sample

public interface RoutingService {
    List<Itinerary> fetchRoutesForSpecification(RouteSpecification routeSpecification);
}

现在,此特定演示恰好将域服务保留在与模型不同的命名空间中,并使用application service to bridge the two

return routingService.fetchRoutesForSpecification(cargo.routeSpecification());

但是,将这部分责任作为模型

同样正确
return cargo.fetchRoutes(routingService);

查询为您提供了一些空间,因为您不必担心允许模型保护自己的不变量。使用命令,后一种方法提供了更好的封装

order.updateSalesTax(taxCalculatorService);

答案 1 :(得分:1)

  

根据DDD,服务是否属于域模型?

它是域层的一部分。域服务封装了无法自然建模为值对象或实体的域逻辑。

在洋葱架构中,所有依赖关系都面向内部。值对象和实体不应该对域服务有任何依赖性。域服务依赖于实体和值对象。架构的核心是域层(值+实体+服务)。这是DDD,它是业务/问题域的抽象视图。此层不依赖于数据库,Web服务调用,smtp和其他基础结构相关服务。

上面的一层是依赖于域层的应用层。应用程序层由应用程序服务组成,这些服务包含用于编排业务用例的应用程序逻辑。

下一层是基础设施层,负责技术实现存储信息,日志记录,安全性,通知以及与其他有界上下文的集成。该层还允许通过Web服务或消息端点使用应用程序层。

为避免这些层之间的紧密耦合,较高层必须适应较低层的消息类型。在这些图层之间,您可以使用数据传输对象(DTO),这样您就不会跨越边界传递域对象(实体)。另外,为了避免与特定技术(例如数据库)的紧密耦合,层通过接口进行通信。