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

Posted

技术标签:

【中文标题】在域驱动设计中使用外部 Web 服务【英文标题】:Consuming external webservices in domain driven design 【发布时间】:2011-05-28 17:03:29 【问题描述】:

我想在我的域驱动设计项目中使用外部第三方 Web 服务,但我无法理解我应该在哪一层访问外部 Web 服务。在域服务中,但我不这么认为,因为域服务仅适用于域对象。但我的要求是,我必须根据来自外部 web 服务的输入执行操作列表,我必须在域服务中执行另一项任务。我很困惑。

【问题讨论】:

解决一个问题的方法有很多种,总会有不同的意见。也许您应该在原始问题中添加更多细节?您希望 DO 在需要时访问数据,还是由其他触发器提供数据?请提供更多详细信息。 【参考方案1】:

据我猜测,您需要使用外部 Web 服务来执行某些操作。如果对于操作,您的意思是您的业务逻辑,我认为正确的位置应该在您的业务逻辑层。在您的上下文中,您只需要使用它们。 如果您需要它来计算产品价格,您会在哪里调用计算增值税的外部 dll?

我希望这是有道理的:-)

【讨论】:

【参考方案2】:

您可以做的是,根据您的领域项目中的领域模型,为所需服务引入一个接口。每次您域中的类需要该服务时,您都会将引用传递给该接口的实现。

然后您创建一个“连接器实现”来实现此接口并连接到您需要使用的 Web 服务。当你启动你的应用程序时,你会为你的域类提供这个实现,例如使用依赖注入框架。

此连接器引用了您的域模型和 Web 服务定义。您的域模型没有对连接器实现或 Web 服务的引用——它只知道域项目中定义的接口。这称为控制反转。

这样,您的域类对 Web 服务一无所知,而只对您在域模型中定义的接口一无所知。因此,您的域逻辑与“邪恶”的外部世界保持分离。

【讨论】:

【参考方案3】:

我想说有几个选择:

1) 如前所述,创建一个表示某种域服务的接口,并创建一个调用该 Web 服务的具体实现。

2) 如果服务只需要在发生某些事情时调用,例如确认订单后,您可以使用“域事件”(参见http://www.udidahan.com/2009/06/14/domain-events-salvation/)

让 Order.Confirm() 方法引发 OrderConfirmed 事件并有一个事件处理程序来响应该事件并从那里调用 Web 服务。 事件处理程序和服务引用可以存在于使用领域层的应用层中。

3) 如果 web 服务的结果可以被认为是一个域概念,您可以为结果创建一个实体,并从 web 服务结果创建该实体的存储库,从而隐藏它是外部数据的事实.

【讨论】:

实际上我想为我的应用程序 paypal,authorize.net 创建支付处理器。我创建了它,它还有很多像 IPaymentMethod、PaymentInfo 这样的实体。但我无法断定我是否创建单独的聚合并将所有这些实体放在那里并创建域服务,这些服务将获取数据填充的实体并将它们传递给 paypal 或 authorize.net,并等待状态消息。我做的事。付款处理部分是否在我的域内部,或者我无法得出结论。请帮忙。 IMO,无论您选择哪种解决方案都可以,只要您的域类不依赖于 paypal 和 authorize.net。因此可能支付处理是您领域的一部分:如果是这样,请选择适当的抽象和接口,您可以使用 paypal/auth.net 实现来实现。听起来您走在正确的轨道上;如果你得到正确的依赖,更是如此。【参考方案4】:

您需要一个新的基础设施服务来访问外部网络服务。如前所述,您可以将服务实现注入到您的域对象中。

参见 Eric Evans 的“领域驱动设计”第 105 页。或者,请参阅我的回答 here 以了解 DDD 中不同类型的服务。

【讨论】:

您告诉我创建应用程序服务,并将其注入到域对象中。那可能吗 ?域对象能否访问应用服务。如何 ?其他人告诉我在域服务中做。这里一团糟。 @ Vijay 在我的域中,我有广告商和发布商实体,我想允许广告商将资金存入他的余额中,这是广告商的一部分(从 PayPal 转移资金,成功转移后我们会增加他的余额)与 draw 和来回 Publisher 实体相同。现在支持转账 Paypal 需要各种参数,为此我创建了各种实体,这些实体会被填充 例如 -: PaymentInfo,我们将它们传递给 PayPal 或任何支付网关。那么我应该将所有这些实体放在我的域中的什么位置。我是否创建支付聚合并创建域服务以进行转移或在应用层中。 这是非常错误的@chandra。依赖关系从内部到外部,而不是相反。域永远不能使用应用程序服务,但是,应用程序服务可以并且应该在它们或请求其执行时使用域。阅读鲍勃叔叔关于清洁建筑的更多信息,他说得很清楚。您可以做的一件事是从域中启动域事件,然后应用层中的相应事件处理程序执行它们的工作。 根据您的其他答案,看起来像基础设施服务或域服务,绝对不是应用程序服务。即使这样写外部服务消费者应用程序服务,而不是其他方式...... @inf3rno:感谢您指出这一点!那年我一定是为了圣诞节而放松(或者可能喝醉了)。

以上是关于在域驱动设计中使用外部 Web 服务的主要内容,如果未能解决你的问题,请参考以下文章

领域驱动设计中的层

领域驱动设计:服务和聚合中的领域规则

[国嵌攻略][164][USB驱动程序设计]

使用 Spring 创建“Hello, World”超媒体驱动的 REST Web 服务

领域驱动设计核心思想

MVC Web 应用程序的域驱动设计与数据库驱动设计