使用依赖注入和IoC容器有什么好处?


62

我打算就依赖注入和IoC容器进行一次演讲,并且正在寻找一些使用它的良好论据。

使用此技术和这些工具的最重要好处是什么?


1
这里这里的StackOverflow的答案,并在这里对国际奥委会良好的全部文章。而且,如果您想反对它以进行比较,请前往此处
Jesse C. Slicer

14
不要成为屁股...但是如果您不知道为什么要使用DI / IOC,您为什么要谈论它?打赌?;-)
史蒂文·A·劳

2
@Steven,他的老板可能已经要求他这样做。

1
@Steven,我已经一直在使用DI(有些人会经常说:-D),我只是在寻找一些好的论据来让其他人使用它。
安迪·洛瑞

2
人们很少谈论过度使用 DI。如果您延迟每个决定,则将创建与意大利细面条代码等效的OO。具有连贯的设计需要在某个时候做出真正的决定。
Macneil 2010年

Answers:


47

对我而言,最重要的是使其易于遵循“ 单一责任原则”

DI / IoC使我可以轻松地管理对象之间的依赖关系。反过来,这使我更容易将一致的功能分解为自己的合同(接口)。结果,自从我了解DI / IoC以来,我的代码已进行了更加模块化。

这样做的另一个结果是,我可以更轻松地了解支持开放式封闭原理的设计。这是最令人鼓舞的技术之一(仅次于自动化测试)。我怀疑我是否会足够拥护开放式原则的优点。

DI / IoC是我编程生涯中为数不多的“改变游戏规则”的事情之一。有一个巨大的质量差距代码之间我以前和学习DI /国际奥委会后写道。让我再强调一点。 大幅提高代码质量。


3
为什么开放式原则如此重要?如果您觉得需要更改API /接口,为什么不呢?
Arne Evertsson

@ArneEvertsson听Robert C. Martin谈开放原则。你会开悟的。
Alternatex

@AmeEvertsson当您的代码作为模块提供给他人使用时,@ AmeEvertsson非常重要,因为它使您的代码更易于使用,而无需他们回复您进行更改
James Ellis-Jones

2
DI并没有使管理依赖项变得简单,因为它比简单地为具体类创建依赖项要复杂得多。但是,它确实提供了灵活性,但是除非您进行“适当的”单元测试,否则通常就不需要这种灵活性。所描述的两个关键优势也适用于服务定位器,它更简单。
James Ellis-Jones

1
几年前,我否决了这个答案。这里有一些说明:1)实际上,DI的广泛使用往往会不利于 SRP,因为程序员只是继续向其注入的“控制器”,“服务”,“ DAO”等添加方法,而不是为新功能。您通常会在使用某些DI框架或容器的Java和C#.NET项目中看到这种情况。2)开闭原则仅仅是Bertrand Meyer对类(实现)继承的有用性的幻想;如果您在他的1400多页的书中对其进行搜索,您会明白我的意思-这真是愚蠢。
罗杰里奥(Rogério)

9

真正使我大开眼界的示例正在看到如何以这种方式轻松地对创建的对象进行单元测试。在此之前,我在尝试隔离对象以进行单元测试时遇到了麻烦。我经常会编写测试来与更大的系统进行交互。这确实很难,因为与单个组件相比,整个系统的可预测性要差得多,并且更容易更改。


3

依赖项注入的优点是:

  1. 您的代码干净且可读性强。
  2. 代码是松散耦合的。
  3. 由于实现是在XML文件中配置的,因此具有更高的可重用性,可以在不同的上下文中使用它。
  4. 可以使用不同的模拟实现轻松测试代码。

1

我认为实际收益比技术收益更具政治意义。DI只是Service Locator模式的替代品,仅此而已。就其本身而言,遵循SRP或OCP之类的原理或分离层并不会更容易。国际海事组织(IMO)在这里的其他受访者都在混淆不同的概念和技术。

通过使用服务定位器,或者在适用的情况下(大多数时候)直接直接实例化依赖关系,就可以实现高内聚和低耦合的相同目标。

现在,我知道许多人将不同意这种观点。我将很高兴讨论具体示例。


2
但是直接调用服务定位器或实例化具体的依赖关系通常会硬性连接您的依赖关系,或者至少是依赖关系来自何处。那似乎打败了DI的目的。您仍然还必须注入服务定位器。
Matt H 2010年

使用Service Locator不会硬连接任何东西,除非使用Service Locator类本身,通常不会“注入”。在不需要外部配置的情况下,实例化一个具体的实现类就很好了(例如,程序员通常直接实例化ArrayList类而不是使用DI-这会太过分了)。
罗杰里奥(Rogério)2010年

1
您提到“低耦合”,然后再说服务定位符对应用程序的耦合级别没有影响。直接在代码上实例化协作者的方法相同,我想不出一种将对象与其依赖关系耦合的更完美的方法。您如何对两种情况进行单元测试?我谨完全不同意你所说的一切。
克林特·伊斯特伍德

@Jonathan然后,您应该阅读介绍DI文章。作者的结论是,DI和ServiceLocator大致相等,后者则具有“轻微优势”。重要的耦合在一个组件和可能具有多个实现的其他组件之间;ServiceLocator是仅具有一个实现的基础结构服务,因此可以。注意我写了“ 在适用时实例化依赖关系”;当然,如果您需要将配置与使用分开,则不会这样做。
罗杰里奥2015年

1
@Jonathan关于单元测试,实例化协作者阻止创建此类测试是一个神话。有一些众所周知的模拟工具可以完成将类与依赖项实现隔离的工作,无论它们是否被注入。
罗杰里奥2015年

-1

当使用DI暴露内部对象以进行测试时,该模式已被滥用。


1
“内部对象”是什么意思?在实际的 OOP中(请注意,可能只有1%的程序员知道这实际上意味着什么),有些对象通过发送消息(即方法调用)相互通信。从这个意义上讲,每个对象都必须负有单个责任,没有比其他对象“更重要”的对象……每个单个对象都负有单一职责,并且它们相互协作以实现整个系统提供的功能。以隔离的方式测试每个对象非常重要,因此我们知道我们绝不会错过任何情况,这就是DI真正擅长的。
克林特·伊斯特伍德

我忘了。
托马斯·彼得
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.