首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >领域驱动设计概念

领域驱动设计概念
EN

Stack Overflow用户
提问于 2012-09-07 17:27:14
回答 2查看 2K关注 0票数 3

在使用域驱动设计构建的应用程序中,我遇到了一些问题。

我有以下几层:

  • 应用程序
  • 域名
  • 基础设施

那么,让我们假设我有以下类:

  • Order
  • EmailService
  • OrderNotificationService
  • OrderApplicationService

显然,Order在域层,OrderApplicationService在应用层。EmailService是一种用于发送电子邮件的通用服务,并在基础设施层实现。OrderNotificationService是用于发送订单通知的特定实现。OrderNotificationService使用EmailService发送实际的电子邮件。

因此,我的第一个问题是:OrderNotificationService是作为域服务、应用程序服务还是基础设施服务实现的?

对于我的下一个问题,让我们假设以下对象:

  • Employee
  • SalesforceService

假设当员工被添加到系统中时,他们也应该被添加到Salesforce中。SalesforceService是一个使用Salesforce注册用户的服务。SalesforceService是作为域服务还是应用程序服务通过发送员工信息使用的通用基础设施服务来实现的呢?

谢谢你的建议。

EN

回答 2

Stack Overflow用户

发布于 2012-09-08 00:09:30

这听起来不像DDD

你的问题中并没有太多关于你的领域模型的内容。您提到了“员工被添加到系统和Salesforce中”,但除此之外,我对您的应用程序在业务上的意图没有真正的了解。我对“雇员”和“销售人员”的理解是基于对这些词的熟悉程度,而不是对它们在系统中的模型的解释。

我不太清楚“订单应用服务”在您的模型中应该代表什么。我得到了“订单”和“订单通知”。似乎是“客户”发出了“订单”,一些“订阅者”得到了“通知”,但很多这都是基于我对设计模式的先验知识。

--你应该能够描述业务领域模型,因为如果计算机不存在,它就能工作。如果你需要一个计算机术语来解释这个想法,那么它很可能是混合在模型之外的东西中。

显然,您需要将应用程序逻辑与域逻辑集成起来,但这不应导致混淆您的关注点。然而,有一些方法可以解决这个问题。

你怎么能修好它

  1. 可以使用接口而不是实现特定的类来对域层中的服务进行建模。这就是所谓的interface segregation principle。您的模型的一部分包括在客户下订单时通知负责的员工,这是有意义的。但是,不一定有任何理由将此通知的实现耦合到其建模目的。在拥挤的办公室里,可能有主管通过对讲机发出通知,也可能有一封电子邮件是由自动化系统发送的。这两个例子都具有相同的业务目的。与在域层中嵌入电子邮件服务不同,您可以拥有一个简单包含方法IOrderNotificationServicevoid NotifyOrderReceived(Order order);接口。这样,您就可以在域层中获得所需的所有业务逻辑,而无需引入不必要的关注点,如“电子邮件”实现或数据库持久性。我猜想这一点,但您的OrderNotificationServiceOrderApplicationService实际上是对同一事件的响应,但其中一个具有数据库依赖性,另一个具有SMTP依赖。两者都是基础设施方面的问题。

在许多情况下,针对单个接口进行编码就足够了。但是,存在一个问题,您的域对象现在依赖于注入的服务或全局变量。此外,这可能表明这些实体对其依赖性了解得太多了。客户可能不需要知道订单是如何处理的,但只需要知道订单已经处理,他们就会收到订单。类似地,员工可能不会加入销售团队,因为他在成为员工之前不知道这件事。他只知道他刚找到一份工作。

这个问题有一个很好的解决办法。

  1. 您可以使用“域事件”模式。基本思想是,域对象只知道刚刚发生了什么以及它们的状态是如何改变的,而不需要知道任何关于持久化或传播更改状态的信息。它们处理内部逻辑,然后引发“域事件”。这更像一个客户下了订单,然后大喊:“哟,我订购了这个产品!”或者是一名雇员被录用,然后大叫:“哟,我找到工作了!”采用这种方法将大大简化您的域逻辑,并使您能够实现更清晰的关注点分离。Udi Dahan有一系列出色的博客文章,他解释了利用域事件模式背后的逻辑,并提供了一个非常简单但非常有效的实现。以下是一些链接:

代码语言:javascript
复制
- [How to create fully encapsulated Domain Models](http://www.udidahan.com/2008/02/29/how-to-create-fully-encapsulated-domain-models/)
- [Domain Events – Take 2](http://www.udidahan.com/2008/08/25/domain-events-take-2/)
- [Domain Events - Salvation](http://www.udidahan.com/2009/06/14/domain-events-salvation/)

现在,如果您是那种喜欢在完全理解代码之前复制和粘贴代码的开发人员,我建议您从第三个帖子开始。他们记录了Udi Dahan的思想和经验与模式的演变。最合理的代码示例出现在第三篇文章中。理想情况下,您应该按照顺序阅读这三种方法,这样您就可以遵循他的逻辑,并真正理解如何从他的方法中获益,以及为什么它准确地表示“领域驱动设计”。

作为“领域事件模式”的补充,埃里克·埃文斯(Evans)2009年回顾了他写了一本开创性的书以来对领域驱动设计( Domain )的了解,他指出,在他的书中,领域事件是一个明显被忽视的核心构建块。他的演讲摘要是可用的here,指向演示文稿的链接是可用的here

其他一些可能帮助您成功应用此模式的资源包括Jimmy的文章“Strengthening your Domain: Domain EventsMartin Fowler's Domain Event article”。Bogard有链接到其他有用的DDD博客文章,从引用的链接。

总体而言,

如果您真的想尝试应用领域驱动的设计,那么通过真正了解您正在建模的内容以及实现什么目的,您将获得更大的成功。简单地使用您不熟悉的术语并将您的代码贴上标签是没有隐含价值的。DDD是非常有用的,但是如果你不花时间去理解你为什么要做出区别和设计决策,你最终会有很多不必要的抽象和一般的混乱。

票数 11
EN

Stack Overflow用户

发布于 2012-09-07 22:44:43

OrderNotificationService属于域层。如果您认为它是Order类的协作者,那么它应该靠近Order类。海事组织,我认为OrderNotificationService可以被称为OrderNotifier,它的职责是在订单状态发生变化时发布通知。它显然是一个接口,而不是一个具体的类。它可以由属于基础结构或应用层的OrderNotificatoinService实现。没有必要使OrderNotificationService成为一个接口。

这同样适用于SalesforceService。将其视为Employee类的协作者,它负责在创建员工时注册新员工信息。它属于域层。与前一种情况一样,您可以考虑将其重命名为EmployeeRegister或类似的名称,这些名称描述了它的角色,而不是它的实现。而是用SaleforceService实现它。

一个副作用是您的域对象(Order/Emplyee)间接地依赖于应用程序/基础结构层的类。如果域对象是由其他域对象实例化的,则在创建域对象时,您可能会发现很难注入第三方依赖项。这篇文章可能很有用。http://thinkinginobjects.com/2012/09/05/abstract-factory-in-domain-modelling/

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12322736

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档