在领域驱动设计中使用外部Web服务

13

我希望在我的领域驱动设计项目中使用外部第三方网络服务,但我不知道应该在哪个层面上访问外部网络服务。是否在领域服务中?但我认为不是,因为领域服务仅适用于领域对象。但我的要求是,基于来自外部网络服务的输入,我必须执行一系列操作,并在领域服务中执行另一个任务。我感到困惑。


解决问题的方法有很多,而且意见总是不一。也许你应该给你的原始问题添加更多细节?你想让DO在需要时访问数据,还是数据由其他触发器提供?请提供更多细节。 - Vijay Patel
4个回答

10
您可以在您的领域项目中以您的领域模型介绍所需服务的接口。每当您的领域中的类需要该服务时,您将向其传递一个实现此接口的参考。
然后,您创建一个“连接器实现”,该实现实现此接口并连接到您需要使用的 Web 服务。启动应用程序时,使用依赖注入框架为您的领域类提供此实现。
该连接器具有对您的领域模型和Web服务定义的引用。您的领域模型不引用连接器实现或Web服务 - 它仅知道在领域项目中定义的接口。这被称为控制反转。
通过这种方式,您的领域类不了解Web服务,只知道您在领域模型中定义的接口。因此,您的领域逻辑与“邪恶”的外部世界分离。

8
您需要新的基础设施服务来访问外部Web服务。如先前建议的那样,您将把服务实现注入到域对象中。
请参阅Eric Evans的《领域驱动设计》第105页。或者,查看我在这里的答案,了解DDD中不同类型的服务。

3
你让我创建应用程序服务,并将其注入到领域对象中。这可能吗?领域对象能够访问应用程序服务吗?如何实现?其他人告诉我在领域服务中完成。这里一团糟。 - chandra
@ Vijay 在我的领域中,我有广告主和发布者实体,我想允许广告主在他的余额中存入资金(从PayPal转账,在成功转账后我们增加他的余额),发布者实体也是如此。现在为了支持转账,PayPal需要各种参数,因此我创建了各种实体,例如:PaymentInfo,并将它们传递给PayPal或任何支付网关。那么我应该把所有这些实体放在哪里呢?我是在我的领域中创建Payment Aggregate并创建用于转账的领域服务,还是在应用程序层中创建? - chandra
这很不对,@chandra。依赖关系是从内部到外部的,而不是相反的。领域层永远不能使用应用程序服务,但是应用程序服务可以并且应该使用领域层,因为它们编排其执行。阅读一下Bob大叔的《Clean Architecture》,他讲得非常清楚。你可以做的一件事是从领域中启动领域事件,然后应用程序层中的相应事件处理程序会完成它们的工作。 - Gustavo Andrade Ferreira
根据您的另一条回答,这似乎是基于基础设施服务或领域服务,而不是应用程序服务。即使是写外部服务的消费者应用程序服务,而不是相反... - inf3rno
@inf3rno:感谢您指出这一点!那年我可能正在为圣诞节做准备(或者可能有些醉了)。 - Vijay Patel
@vijay 这个答案没有被接受为答案!为什么我不能直接将 IHttpClient 注入到我的应用程序服务中?为什么我必须将 IHttpClient 注入到 IExternalService(在我的基础设施服务层中),然后再将 IExternalService 注入到我的应用程序服务中?而且你给出的链接并没有明确回答这个问题! - bet

4
我会说有几个替代方案:
1)如前所述,创建一个表示某种领域服务的接口,并创建一个调用Web服务的具体实现。
2)如果只需要在发生某些事件时调用服务,例如确认订单时,则可以使用“领域事件”(参见http://www.udidahan.com/2009/06/14/domain-events-salvation/
让Order.Confirm()方法引发OrderConfirmed事件,并有一个事件处理程序响应该事件并从那里调用Web服务。事件处理程序和服务引用可以存在于消耗领域层的应用程序层中。
3)如果Web服务的结果可以被视为领域概念,则可以为该结果创建一个实体和一个从Web服务结果创建此实体的存储库,从而隐藏它是外部数据的事实。

1
实际上,我想为我的应用程序创建支付处理器,支持PayPal和Authorize.net。我已经创建了这个处理器,并且它还有很多实体,例如IPaymentMethod、PaymentInfo等。但是我无法得出结论,是否应该创建单独的聚合并将所有这些实体放在那里,并创建域服务,将填充数据的实体传递给PayPal或Authorize.net,并等待状态消息。我该怎么做?我无法确定支付处理部分是否属于我的域内部。请帮忙。 - chandra
1
在我看来,无论你选择哪种解决方案都可以,只要你的领域类不依赖于PayPal和Authorize.net。因此,付款处理可能是你的领域的一部分:如果是这样,请确保选择适当的抽象和接口,以便你可以使用PayPal/Auth.net实现。听起来你已经在正确的轨道上了;如果你能正确处理依赖关系,那就更好了。 - Marijn

3

从我的猜测来看,您需要使用外部的网络服务来执行一些操作。如果您所说的操作是指业务逻辑,我认为正确的位置应该在您的业务逻辑层中。在您的上下文中,您只需要使用它们。

如果您需要调用一个外部的dll来计算增值税以便计算产品价格,那么您会把它放在哪里呢?

希望这有意义:-)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接