【问题标题】:Are domain services part of domain model?域服务是域模型的一部分吗?
【发布时间】:2018-01-11 17:18:41
【问题描述】:

根据 DDD,服务是域模型的一部分吗?如果我们搜索“ddd onion architecture”,我们可以看到最里面的一层叫做“Domain Model Layer”,第二个是“Domain Services”,例如[dead link, NSFW now]。但是在https://en.wikipedia.org/wiki/Domain-driven_design 和 DDD 书中,我们看到实体、值对象和服务都表达了模型并且是模型元素。如果实体、值对象和服务都是领域模型的一部分,我们应该如何称呼这两个洋葱层:模型(实体 + 值对象)和服务(就像我有时做的那样)?但如果都是领域模型的一部分,这个命名似乎并不准确。

【问题讨论】:

    标签: domain-driven-design


    【解决方案1】:

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

    是的,但也不是。

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

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

    服务是作为接口提供的操作,在模型中独立存在,不封装任何状态....

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

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

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

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

    是的,是的。例如,这是第 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);
    

    【讨论】:

    • 对,依赖倒置,我喜欢你的回答(但蓝皮书没有提到这句话)。但是如果域服务是域模型的一部分,实体和值对象是否可以对域服务的接口有编译时依赖?它们(领域服务的实体、值对象和接口)是否在领域模型的同一层?
    【解决方案2】:

    根据 DDD,服务是域模型的一部分吗?

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

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

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

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

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

    【讨论】:

    • 感谢您的回答。您说域服务是域层的一部分。但是实体和值对象也是领域层的一部分。但是你说实体和值对象不应该对域服务有任何依赖。也就是说域层是由两层(子层)组成的,对吧?
    • 是的。为了澄清我的观点,假设您有两个项目。 Domain.Entities 包含您的域实体和值对象。另一个项目 Domain.Services 包含域逻辑。 Domain.Services 项目将依赖于 Domain.Entities 项目。
    • 谢谢。所以实体和值对象的通用名称是实体。也许我们可以找到一个不那么令人困惑的名字?我会说实体与值对象相反,您将它们都称为实体(例如您的项目名称)。
    • 通用名称为 Domain.Models
    • 但正如您所说,域服务也是域模型的一部分,它们不在您的 Domain.Models 项目中。
    猜你喜欢
    • 1970-01-01
    • 2013-10-06
    • 1970-01-01
    • 2018-05-14
    • 2012-02-04
    • 2017-07-24
    • 2021-12-20
    • 2011-08-17
    • 2020-08-05
    相关资源
    最近更新 更多