“混蛋注射剂”和“穷人注射剂”的真正区别是啥
Posted
技术标签:
【中文标题】“混蛋注射剂”和“穷人注射剂”的真正区别是啥【英文标题】:What is the real difference between "Bastard Injection" and "Poor Man's Injection"“混蛋注射剂”和“穷人注射剂”的真正区别是什么 【发布时间】:2011-10-29 06:56:18 【问题描述】:从Dependency Injection in .NET 一书中,我知道应该在应用程序的Composition Root
创建对象图,当您使用IoC Container
时,这对我来说很有意义。
在我尝试使用 DI 时看到的所有应用程序中,总是有两个构造函数:
以依赖项为参数和 “默认”一个没有参数,反过来又调用另一个“更新”所有依赖项然而,在前面提到的书中,这被称为“Bastard Injection 反模式”,这就是我以前所知的“Poor Man's Injection”。
现在考虑到这一切,我会说“穷人的注射”只是不使用IoC Container
,而是在上述Composition Root
上手动编码所有对象图。
所以我的问题是:
-
我是正确理解这些概念还是完全偏离了轨道?
如果您仍然需要在 IoC 容器中注册所有依赖项,而不是在完全相同的 Composition Root 中手动编码,那么使用 IoC 容器的真正好处是什么?
如果我误解了“穷人的注射剂”到底是什么,有人可以澄清一下吗?
【问题讨论】:
听起来像是术语的不同。这两个术语听起来像是书作者试图引起轰动的同义词。 我真的不认为作者像你这样称呼他是耸人听闻的,他确实提出了一个令人信服的论点,如果在空构造函数中创建的默认实例是在单独的程序集中定义的,那么你刚刚将这两个依赖项耦合得非常紧密。有了这个论点,除非默认值属于同一个程序集,否则我完全可以理解为什么“Bastard Injection”会是一种反模式。 关于混蛋注射,另见:***.com/questions/6733667/… 【参考方案1】:在 DI 方面,有很多相互矛盾的术语使用。 Poor Man's DI 一词也不例外。对某些人来说,它意味着一件事,而对另一些人来说,它意味着不同的东西。
我想做的一件事是为 DI 提供一种一致的模式语言。当涉及到所有这些使用冲突的术语时,我有两个选择:想出一个全新的术语,或者选择最流行的用法(根据我的主观判断)。
总的来说,我更喜欢重复使用现有的术语,而不是编造一种全新的(因此是外来的)模式语言。这意味着在某些情况下(例如Poor Man's DI),您对名称的概念可能与书中给出的定义不同。图案书经常会出现这种情况。
至少我觉得这本书似乎已经完成了准确解释穷人的 DI 和混蛋注射的工作,因为 O.P. 中给出的解释是正确的。
关于 DI 容器的真正好处,我建议您参考这个答案:Arguments against Inversion of Control containers
附注2018-04-13: 我想指出,我多年前就开始承认,Poor Man's DI 这个词在传达原则的本质,所以多年来,现在,我已经instead called it Pure DI。
P.P.S. 2020-07-17: 我们从 second edition 中删除了 Bastard Injection 一词。在第二版中,我们简单地使用更通用的术语 Control Freak 来指定您的代码“在组合根以外的任何地方依赖于易失性依赖。”
【讨论】:
好了,没有比作者本人更好的答案了。 感谢马克的回答和您的书。我即将开始一个绿地项目,这些知识将被证明是无价的!span> 最后它没有回答问题:P【参考方案2】:问题第 2) 部分的一些注释。
1234563在每个类的每个“混蛋注入”构造函数上,因此在您的代码库中分布着许多“组合根”如果您仍然需要在 IoC 容器中注册所有依赖项,而不是在完全相同的 Composition Root 中手动编码,那么使用 IoC 容器的真正好处是什么?
无论您是否有依赖关系树,使用 IoC 容器都可以省去键入一些代码的时间。想象一下,你有 20 个不同的类,它们依赖于同一个 IDependency
。如果您使用容器,您可以提供一个配置,让它知道要为IDependency
使用哪个实例。您将在一个地方进行此操作,并且容器将注意在所有依赖类中提供实例
容器还可以控制对象的生命周期,这是另一个优势。
除了 DI 提供的其他明显优势(可测试性、可维护性、代码解耦、可扩展性......)之外,所有这些
【讨论】:
【参考方案3】:我们发现,在重构遗留应用程序和解耦依赖项时,通过两步流程完成事情往往会更容易。该过程包括“穷人”和正式的 IoC 容器系统。
首先:设置接口并建立“poor mans ioc”来实现它们。
这可以在不增加开销(和学习 曲线)的正式 IoC 设置。 这也减少了对现有遗留代码的干扰。没有什么比引入另一组要调试的问题更好的了。 开发团队成员的专业知识或理解水平永远不同。所以它节省了大量的实施时间。 这也为测试用例提供了基础。 这也为以后的正式 IoC 容器系统建立了标准。 这可以由许多人逐步实施。其次:每个 IoC 系统都有优点和缺点。
现在应用标准已经建立,一个有根据的决定 可以在选择 IoC 容器系统时进行。 实施 IoC 系统变成了将“可怜的人”代码与 新的 IoC 系统。 这可以随着时间的推移逐步实现,并与“穷人”并行。最好由一个人负责。【讨论】:
以上是关于“混蛋注射剂”和“穷人注射剂”的真正区别是啥的主要内容,如果未能解决你的问题,请参考以下文章
“head”和“header”标签之间的真正区别是啥? [复制]
“constinit”和“constexpr”之间的真正区别是啥? [复制]
Thread.Sleep() 和 await Task.Delay 之间的真正区别是啥? [复制]