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


我特别指的是这个问题: DDD - 如何实施工厂

选定的答案说明:

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

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


5725
2017-11-17 20:32


起源

有关: stackoverflow.com/questions/4835046/... - Steven
不同意声明“工厂不应该依赖于依赖注入,因为域对象不应该有依赖注入它们。”聚合,实体和值对象不应与依赖注入相关联。但工厂和存储库可以。 - Hippoom
您是在询问有关在工厂或域实体中注入deps的问题吗? - MikeSW
根据该声明,我假设“域对象”是域层中的任何构建块(即实体,工厂,repos ..)。我错了。我的问题特别涉及实体,但是我更关心的是语句是TRUE还是FALSE。为什么? - n3wb


答案:


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

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

Factory是一种隔离对象构造逻辑的模式。这也是DDD推荐的一个好习惯,但在所有情况下都不是真正需要的。

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


3
2018-06-17 05:05



域对象可以是表示域实体的域对象,但是将它们视为哑值对象,没有正确的行为提取该行为以仅分离服务(据我理解您的语句)不是DDD。对我来说,DDD就像分解一个人:你有一个名为“人类”的聚合根,其中包含“Body”,“LeftArm”,“RightArm”,“LeftLeg”,“RightLeg”和一个“Head”,它们本身可以有行为( Left / RightLeg.moveForward(),Left / RightHand.makeAFist())然后可以通过将行为委托给某些肌肉来实现。 - Matthias Hryniszak
@MatthiasHryniszak域对象是实体,值对象,域服务和聚合根的混合。你应该读一下这些内容究竟是什么。但是,它们一起封装了所有业务数据,以及需要修改业务数据的所有业务行为。应对它们进行建模,以尽可能接近他们正在建模的业务领域中常见的真实姓名,动词和关系。对不起,如果我不够清楚。 - Didier A.
@MatthiasHryniszak捕获行为的位置并不重要。您可以将行为作为方法放在实体,值对象,聚合根和域服务上。虽然只有聚合根和域服务可以用作域模型外部的接口API。所以在你的例子中,我只能得到一个人类,我必须做Human.moveLeftArmForward();但现在你意识到,在商业领域,没有人要求你这样做,相反,他们说让他挥手。所以你意识到Aggregate应该是Human.wave(),它在内部可以调用arm.move - Didier A.
@MatthiasHryniszak如果做OOP,建模的好方法可能是将Positions作为值对象。位置有一个moveUp,Left,Right等方法,它返回一个新的不可变位置。 Arm是一个实体,它有一个名称,一个位置和一个模型。人是聚合体,其实体是根。它暴露了波浪。它有两个武器,腿和一个身体以及一个名字。它有关于人体原理图的数据,因此它知道如何修改Arm的位置,使其看起来像挥动动画,并且它还保证手臂始终与身体保持连接,并且它不会奇怪地带。 - Didier A.
@MatthiasHryniszak我刚刚注意到你也拒绝了我的回答,但如果你仔细阅读它,我想你会发现你没理解它。如果有一个特定的部分,你要我澄清,请提及,我会尽量让它更清楚。 - Didier A.


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

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

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

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

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

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

依赖性倒置==依赖性


7
2018-05-19 21:16



a)不是“依赖倒置”而是“控制倒置”,b)您正在描述插件架构,c)我同意域可以定义其他人可以用来丰富域的扩展点这一事实(这是插件架构的用途)和DI应该能够帮助它)以及域应该能够解耦自身的部分并使用DI根据需要将它们重新组合在一起这一事实。 - Matthias Hryniszak
我认为您在答案中将“域对象”与“域名服务”混为一谈。这里“域对象”指的是实体(或模型),在域驱动设计中,它们不应该注入依赖关系。 - Maxime Rossini