我有一个应用程序服务 (AppService) 和一个从外部数据提供者读取数据的基础架构存储库 (InfraRepo)。AppService 调用 InfraRepo 并向客户端返回数据。我有以下需求:我有一些过滤条件和业务逻辑。为此,我创建了一个域服务 (DomainService) 并将其注入 InfraRepo。从外部数据提供者(在 InfraRepo 中)检索数据后,我调用域服务,将数据传递到那里,然后取回结果。然后我将结果返回给映射到 Dto 并返回给客户端的应用服务。在基础架构存储库中调用域服务是否正确。
2 回答
存储库实现驻留在较低的基础架构/持久性/数据/...层中。如果一个存储库实现调用域服务,则意味着您将这种决策委托给较低层。顺便说一句,您还可以完全合法地让另一个 Repo 实现完全不调用该服务。
这有点奇怪,因为在任何用例中,域层通常都是您总是想要调用的东西。让基础设施负责调用或不调用域可能超出了其范围。
域服务不是过滤逻辑的最佳场所。通常您将过滤器作为参数传递给存储库或查询服务方法。
业务逻辑可以在域服务中找到,但最好将其放置在相关的实体或值对象中。
长话短说,您可能可以在这里找到更好的职责分配。由于我们缺少您实际希望此域服务执行的操作的详细信息,因此很难准确说出哪一个。
与其讨论纯粹的 DDD,我们似乎可以在讨论中将几个概念放在一起来解决这个问题,并强调每个概念的好处。
根据您对 DDD 的熟悉程度,本文对 DDD 进行了很好的概述。它将 DDD 构建块称为:实体、值对象、聚合(根)、服务、存储库和工厂。在问题中讨论了服务和存储库。没有讨论实体或值对象;因此我不确定存储库返回的数据。
这些元素如何交互可以通过这里讨论的洋葱架构来解决. 在这种情况下,它声明域应该是核心,然后是域服务,然后是应用程序服务,最后是 UI、测试和基础设施的外层。在此模型中,数据访问(存储库)是基础设施。所以关键是依赖从外层流向内层;也就是说,域不依赖于自身以外的任何东西。这与传统的 3 层架构形成鲜明对比,在传统的 3 层架构中,一切都依赖于数据访问代码,业务代码位于 UI 和数据访问代码之间。Onion 架构会说存储库(InfraRepo)属于外层,应用服务属于下一层,域服务属于下一层。因此,AppService 永远不会调用 InfraRepo,因为控制永远不会流向外层,仅从外层进入。相反,AppService 会调用 DomainService,后者会调用 Domain(即业务逻辑)。域将利用它为数据访问定义的抽象(接口或纯虚拟类)。InfraRepo 将实现此抽象,理想情况下,域类将使用 IoC 容器来获取 InfraRepo 实例,同时只知道接口。也就是说,IoC 容器就像上面提到的 DDD 构建块中的工厂一样。InfraRepo 将实现此抽象,理想情况下,域类将使用 IoC 容器来获取 InfraRepo 实例,同时只知道接口。也就是说,IoC 容器就像上面提到的 DDD 构建块中的工厂一样。InfraRepo 将实现此抽象,理想情况下,域类将使用 IoC 容器来获取 InfraRepo 实例,同时只知道接口。也就是说,IoC 容器就像上面提到的 DDD 构建块中的工厂一样。
SOLID原则已经存在了一段时间,它处理类设计的更精细方面,以允许灵活和健壮的代码。在这种情况下,依赖倒置原则可以通过 IoC 容器作为其利用的附加参数来实现。此外,存储库接口的定义应牢记接口隔离原则。