DDD:在哪里放置域服务的实现

Posted

技术标签:

【中文标题】DDD:在哪里放置域服务的实现【英文标题】:DDD: Where to put implementation of domain services 【发布时间】:2017-01-29 09:00:42 【问题描述】:

Domain Service 实现应该驻留在 DDD 项目结构中的什么位置? 如果我们有 IDomainInterfaceDomainInterface 实现,DomainInterface 实现应该驻留在解决方案/项目的基础架构或核心/域部分吗?

【问题讨论】:

【参考方案1】:

领域服务接口及其实现可能驻留在领域层。但是,如果域服务实现依赖于基础架构问题,那么通过应用依赖倒置原则,实现将存在于基础架构层,同时依赖于域中定义的接口。

大多数领域服务将不需要依赖于基础设施问题,并将用于对无法在现有聚合中找到自然归宿的用例进行建模,但某些领域服务会。

存储库是最常见的领域服务,需要基础架构知识,因此您会发现它们的实现存在于基础架构层,但还有其他示例。

例如,在 IDDD 的身份和访问有界上下文中,EncryptionService 接口存在于域中,而MD5EncryptionService 具体实现存在于基础架构中。

【讨论】:

域服务与基础设施无关 仅关注基础设施,例如存储库,将在基础设施层实现。域服务及其与存储库的交互将在域层中实现。来自Implementing Domain-Driven Design 的AuthorizationService 就是这样一个例子。 @AlexeyZimarev 当您在域中定义服务合同时,您是关注 UL 还是关注基础架构问题?我当然希望你专注于 UL。例如,如果您的企业正在发送通知,并且如果您实现EmailService,那么通知是通过电子邮件发送的(基础架构问题),我理解您为什么要将其称为基础架构服务,但如果您确实实现了NotificationService相反,它与您的 UL 一致,那么我不明白您为什么不将其视为域服务。 @Robert 好吧,我不认为他们是合理的,但基本上他们不认为需要基础设施细节的服务是域服务,他们称之为基础设施服务。因此,他们说我的示例和 cmets 中的存储库或 NotificationServiceEncryptionServiceCollaboratorService 都是基础架构服务。对我来说这没有任何意义,因为这些服务的接口存在于域中,并且应该在考虑 UL 的情况下进行定义。 在向您解释了这一点后,我更加确定他们错了。 定义服务类型的是接口所在的位置,而不是实现。例如,您不会在域中拥有应用程序服务接口。【参考方案2】:

洋葱或六边形架构表示基础设施层依赖于内部层。 如果合约存在于领域层,那是因为它代表了一些业务需求,代表了无处不在的语言,因此我将其视为领域服务。

如果域服务实现需要某种特定技术(例如数据库访问、SMTP 服务器访问等),则其实现必须位于基础架构层。域根本不关心实现,如果业务专家谈论某事并且我们决定将这个“某事”作为合同,它必须存在于域层中。一切都与领域语言有关。

根据定义,基础设施服务不应位于域层中。如果它与基础设施有关,那么我怀疑它与无处不在的语言有关。我希望看到基础设施服务合同存在于应用层,因为根据定义,应用层是帮助领域的编排层。如果实施需要一些特定的技术,同样,实施将在基础设施层。

所以,总结和回答这个问题: 将域服务实现放在哪里?这取决于:

如果实施不需要来自应用程序或特定技术的任何内容。将实现放在领域层。 (示例:计算的订单号) 如果实现需要来自应用层的任何东西(例如,它需要访问在我看来位于应用层的聚合存储库),则将实现放在应用层中。 如果实施需要特定技术(例如访问 SMTP 服务器或具体的 http 客户端),则将其放置在基础架构层中。

最后,重要的是,在域中我们关心无处不在的语言,在应用程序中,我们编排域,实现取决于它们的依赖关系(域不能依赖任何东西,应用程序只能取决于域)。

【讨论】:

以上是关于DDD:在哪里放置域服务的实现的主要内容,如果未能解决你的问题,请参考以下文章

在哪里放置需要从数据库中获取数据的域逻辑

我在哪里可以找到一些 DDD 的好例子? [关闭]

在 DDD 架构中,我应该将与按角色用户过滤数据相关的查询逻辑放在哪里

DDD:在哪里生成实体的 url slug?

图片上传 - 使用 CQRS 和 DDD 放置代码的位置

如果涉及访问外部API(域驱动设计),我应该在哪里放置值对象创建逻辑]] << [