如何使用域驱动设计来表示此场景

时间:2015-03-31 00:44:06

标签: architecture domain-driven-design

我一直在阅读领域驱动设计,他们所谈论的内容似乎与我过去十年所做的完全相反。像普通开发人员一样,我认为以下是一个很好的干净架构

  

客户端应用 - >远程门面 - >服务层 - >数据存储。   域是在所有不同层之间共享的东西

所有DDD专家似乎都强烈反对这个想法。我试图将DDD应用于下面解释的简单问题

让我们说域名是人力资源部门

域名(他们称之为无处不在的语言)将包含

之类的内容
  

员工,经理,薪酬,奖金,奖励,工作时间等

一个商店(在我的情况下是相关的),其中包含与上述域名相对应的表格

  

表员工,表格管理员,表奖金

使用这些域对象进行计算

  

CalculateBonus,CalculateWorkHours,CalculateSalary,ProcessPay,CalculateVacationLeft等。

当然还有UI,用户(他/她可以做的是基于角色)可以做到

  

登录,添加新员工,成为员工经理,添加激励   经理等。

据我所知,我把这些东西都放了出来。考虑到这个特定的背景,这是我的问题

  1. DDD讨论了存在于一起的域和业务逻辑。这是否意味着像Employee和Manager这样的Domain对象应该包含像(calculateDiscount或calculateVacationLeft)这样的逻辑?我总是把这些逻辑分成某种服务,这是个坏主意吗? (有些人甚至认为CRUD也可以成为域名的一部分_

  2. 此方案中的业务逻辑是什么? CalculateBonus()是业务逻辑还是应用程序逻辑?它应该在哪里居住?

  3. 是否应该使用DDD来解决一个简单的问题?

  4. 我希望这是一篇短文,但结果很长。我希望围绕这个

    进行一次很好的讨论

    由于 凯

2 个答案:

答案 0 :(得分:2)

  1. 您应该始终尝试将业务逻辑放在与其相关的聚合根目录中。如果您对此规则有一些例外,它涉及多个实体,并且不仅仅适用于其中一个实体,那么请使用域服务。如果您的所有逻辑都在域服务中,那么您就拥有了所谓的贫血域模型,其中您的实体只是属性包。查看一个名为double dispatch的概念,以指导如何在实体方法中合并复杂逻辑。

  2. CalculateBonus()对我来说听起来像是商业逻辑。如果域专家谈到一个概念,那么它很可能属于域层。应用程序层主要用于协调域实体以执行系统所需的用例。

  3. 每当您不在协作环境中时(例如用户编辑自己的个人资料),无法访问域专家,或主要进行CRUD时,我会避免使用DDD正在执行的业务不变量。同样重要的是要记住,DDD不是一个全有或全无的概念。您可以在系统中的任何有意义的地方使用它。

答案 1 :(得分:2)

  1. 只影响单个实体根(或AR)的逻辑可以放在该实体(或AR)中。如果它影响该单个实体和另一个实体,则逻辑应该进入域服务。您的应用程序服务是您的应用程序的驱动程序,可以在您的域中编排特定的工作流程,用例等。

  2. CalculateBonus()听起来像是对某种实体的操作,可能涉及其他实体。它可能属于域模型中的服务。如果你把你列出的对象作为你的域名,那么这些对象中的一些作为实体应该是其他实体的孩子(制作聚合根)。当在贫血模型中列为对象/表格时,这些都会消除任何领域知识,例如通过查看贫血模型列表,我无法看到它们如何相互作用或组合成聚合。

  3. 对于简单的问题,特别是CRUD样式的管理界面,可能不值得应用DDD。应用DDD需要更多时间。总体而言,DDD的好处是能够更加密切地反映/记录域名的系统。说这个,可以从DDD中学到很多可以应用于任何应用程序的东西。

  4. 有趣的是,你提到DDD专家认为在所有层中共享一组域实体作为反模式。我与许多尝试这样做的团队合作,他们发现自己处于巨大的混乱状态,只有最简单的应用程序。特别是当他们滥用为ORM生成或通过ORM生成的实体时。

    尝试使用DDD执行此操作时,这会将与您的域无关的数据库实现详细信息带到您的域模型中。它还会通过各层提供过多的信息,当您通过网络(通过Web服务,队列,消息总线等)或通过UI发送此数据时,您不仅会玩弄它们许多非必需的数据,但通常是敏感数据,然后在顶部进行黑客攻击,以规避UI中出现的敏感数据。您最终遇到的情况是,未来的开发人员很容易意外地将敏感信息添加到像Employee这样的对象,并且没有意识到这一点,然后这些信息突然被序列化为JSON,并且在UI后面的JavaScript中显示为不受保护(但隐藏)。

    然后是有限的背景污染。员工实体在人力资源,运输,计费,销售等有限背景下看起来会有所不同。试图制作一个适合所有有界环境的一体适用的实体(但实际上不适合并且没有捕获任何领域知识)是一种巨大的反模式。我每天都在与我合作的团队中看到这一点,这仍然是开发人员犯下的一个巨大错误。像有界上下文这样的东西可能是DDD最大的东西之一,它可以完全改变你编码的方式。

    与DDD的另一个常见误解是它是某种架构模式。虽然Eric Evans的书中有关于上游和下游团队/系统,共享内核以及与架构相关的其他内容的模式,但DDD本身是一组善良/模式,可以简单地帮助设计更好地反映域名的系统。 #39;重新尝试建模。