领域驱动的设计理念

use*_*977 3 architecture oop domain-driven-design separation-of-concerns object-oriented-analysis

我正在使用域驱动设计构建的应用程序中的一些概念遇到一些麻烦.

我有以下几层:

  • 应用
  • 基础设施

所以,我们假设我有以下类:

  • Order
  • EmailService
  • OrderNotificationService
  • OrderApplicationService

显然,Order进入域层并OrderApplicationService进入应用层.这EmailService是用于发送电子邮件的通用服务,并在基础结构层中实现.这OrderNotificationService是发送订单通知的具体实现.该OrderNotificationService用途EmailService发送实际的电子邮件.

所以,我的第一个问题是:是否OrderNotificationService将实现为域服务,应用程序服务或基础结构服务?

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

  • Employee
  • SalesforceService

假设当员工加入系统时,他们也应该被添加到Salesforce.这SalesforceService是一个使用Salesforce api注册用户的服务.请问SalesforceService可以实现为域服务或通用的基础设施服务,应用服务将通过向员工信息使用?

感谢您的建议.

sma*_*man 11

这听起来不像DDD

您的问题中没有太多关于您的域模型的讨论.您提到"员工被添加到系统和Salesforce",但除此之外,从商业意义上讲,我并不真正了解您的应用程序的目的.我对"员工"和"Salesforce"的理解是基于对单词的熟悉程度,而不是基于对系统中模型的解释.

我真的不知道"订单应用服务"应该代表您的模型.我收到了"订单"和"订单通知".似乎"客户"制作了"订单",而某些"订购者"获得"通知",但其中很多都是基于我之前对设计模式的了解.

您应该能够描述业务域模型,因为如果计算机不存在,它将起作用. 如果你需要一个计算机术语来解释这个想法,它可能混合了模型中外在的东西.

显然,您需要将应用程序逻辑与您的域逻辑集成,但这不应该使您的问题混淆.但是,有办法解决这个问题.

你如何解决它

  1. 您可以使用接口而不是特定于实现的类来为域层中的服务建模.这被称为界面分离原理.有意义的是,您的模型的一部分包括在客户下订单时通知负责的员工.但是,没有必要将此通知的实施与其建模目的相结合.可能有主管在拥挤的办公室中通过对讲机发布通知,或者可能有自动系统发送的电子邮件.这两个示例都用于相同的业务目的.您可以拥有一个IOrderNotificationService只包含方法的界面,而不是在您的域图层中嵌入电子邮件服务void NotifyOrderReceived(Order order);.这样,您就可以在域层中获得所需的所有业务逻辑,而不会引入诸如"电子邮件"实现或数据库持久性等不必要的问题.我猜这个,但你OrderNotificationServiceOrderApplicationService真的在同一事件响应的,但是数据库的依赖和其他具有SMTP依赖.两者都是基础设施问题

在许多情况下,针对单个接口进行编码就足够了.但是,存在一个问题,即您的域对象现在依赖于注入的服务或全局变量.此外,这可能表明这些实体对其依赖性了解太多.客户可能不需要知道订单如何处理的内部工作方式,而只需知道订单处理完毕,他们将收到他们订购的订单.同样,员工可能不会将自己添加到Salesforce,因为他在成为员工之前不了解它.他所知道的只是他找到了一份工作.

这个问题有一个非常好的解决方案......

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

现在,如果您是那种喜欢在完全理解之前复制并粘贴代码的开发人员,我建议您从第三篇文章开始.他们记录了Udi Dahan对这种模式的思考和体验的演变.最完善的代码示例出现在第三篇文章中.理想情况下,您将按顺序阅读所有这三个,以便您可以遵循他的逻辑并实际了解如何从他的方法中获益以及为什么它准确地表示"领域驱动设计".

作为"领域事件模式"的理由,Eric Evans在2009年撰写他的开创性着作后对领域驱动设计所学知识的回顾表明,Domain Events在他的书中是一个被忽视的核心构建块.他的谈话的摘要可在这里,并链接到演示文稿,请点击这里.

可能有助于您成功应用此模式的其他一些资源包括Jimmy Bogard的文章" 强化您的域名:域事件"Martin Fowler的域名事件文章.Bogard从引用的链接中链接到其他有用的DDD博客帖子.

一般来说,

如果您真的想尝试应用域驱动设计,那么通过真正了解您的建模内容以及为实现目的而实现的内容,您将会更加成功.简单地使用您不熟悉的术语并标记代码就没有任何隐含的价值.DDD可以提供非常有用的帮助,但是如果你没有花时间去理解为什么要做出区别和设计决策,你最终会得到很多不必要的抽象和一般的混淆.