域对象是否应该注入依赖项?

时间:2013-11-17 20:33:00

标签: dependency-injection domain-driven-design

我特别指的是这个问题: DDD - How to implement factories

所选答案已说明:

“工厂不应该依赖于依赖注入,因为域对象不应该将依赖注入其中。”

我的问题是:无法向您的实体注入依赖项的原因是什么?或者我只是误解了这个陈述?请有人澄清一下吗?

3 个答案:

答案 0 :(得分:12)

有点旧,但我真的想解决这个问题,因为我已经遇到过这个问题,并对此表达了我的看法:

我经常听说Domain Objects不应该“依赖”东西。这是事实。我经常看到人们推断这意味着我们不应该东西注入域对象。

这与依赖意味着相反。域名不应该依赖于其他项目,这是事实。但是,域可以定义自己的接口,然后其他项目可以实现,然后可以将其注入域中。众所周知,这就是所谓的依赖倒置(DI)。

字面上与依赖相反。不允许DI进入域完全限制了你准确建模域名的能力,迫使奇怪的SRP违规,并且几乎杀死了域服务的可用性。

我真的觉得我必须在这里疯狂,因为我觉得每个人都读到“域必须没有任何依赖”,然后认为“注入某些东西意味着你依赖它”并得出结论“因此我们无法将依赖关系注入域中。

这给我们留下了很好的逻辑:

依赖性倒置==依赖

答案 1 :(得分:4)

域对象不是工厂,回购等。它们只是实体,值对象,域服务和聚合根。也就是说,它们必须是封装业务域使用的数据,它们之间的关系以及域可以对该数据执行的行为(读取修改)的类。

存储库是一种抽象出您正在使用的持久性基础架构的模式。它在DDD中,因为它使您的应用程序与数据库分离,但并非所有DDD应用程序都需要甚至应该使用存储库。

Factory是一种隔离对象构造逻辑的模式。这也是DDD建议的一个好习惯,但并非在所有情况下都需要。

域对象不应该依赖于其他任何东西,因为它们是您应用的核心。一切都取决于他们。因此,保持它们不受其他依赖关系的影响会产生明确的单向依赖关系链,并减少依赖关系图。它们是不变量,模型,基础。改变它们,你可能需要改变很多东西。所以改变其他事情不应该迫使他们改变。

答案 2 :(得分:1)

域对象不应具有很多依赖关系。

根据Fowler的“不要问价”原则(https://martinfowler.com/bliki/TellDontAsk.html),您希望域对象尽可能多地执行。包括具有依赖性。但是在“干净代码”(鲍勃叔叔)的第6章中,它提到通过过程/函数类(服务)对数据结构进行操作可能是一个很好的设计。只要您没有将简单的getter / setter和更复杂的“不要问”操作结合在一起的混合对象即可。

Fowler不赞成使用瘦模型,并将其称为反模式-AnemicDomainModel。 https://www.martinfowler.com/bliki/AnemicDomainModel.html

我不同意福勒。我强烈同意另一篇文章中有关胖模型问题的以下引用:“遵循这种逻辑,基本上每个行为都会在模型类中结束。根据经验,这是一个坏主意。成百上千挤在一个类中的代码行是灾难的根源。服务对象正是从这种沮丧中成长出来的。” -https://tmichel.github.io/2015/09/14/oo-controversies-tell-dont-ask-vs-the-web/

我们实际上有一个带有胖域模型的项目,该项目存在这个确切的问题。随着需求随时间的变化和代码变得更加复杂,巨大的胖模型对于执行不同的操作和处理新的需求是相当不灵活的。不必添加对同一简单数据模型有不同作用的新服务工作流路径(类),您必须对庞大而复杂的域模型进行昂贵且困难的重构。它封装了数据并防止任何人以意外的方式修改数据,但与此同时,这使得新的工作流确实很难以新的方式来操纵数据。