我试图在工作中引入依赖注入(DI)模式,我们的一位主要开发人员想知道:如果有的话,使用依赖注入模式的缺点是什么?

注意,如果可能的话,我在这里寻找一个详尽的列表,而不是关于这个主题的主观讨论。


澄清:我谈论的是依赖注入模式(参见Martin Fowler的这篇文章),而不是特定的框架,无论是基于xml的(如Spring)还是基于代码的(如Guice),还是“自滚动”的框架。


Reddit的subreddit /r/programming上正在进行一些深入的讨论/咆哮/辩论。


当前回答

依赖注入是一种技术或模式,与任何框架无关。您可以手动连接依赖项。DI帮助您实现SR(单一职责)和SoC(关注点分离)。DI会带来更好的设计。从我的观点和经验来看,没有坏处。就像任何其他模式一样,你可能会弄错或误用它(但在DI的情况下很难)。

如果您使用框架将DI作为原则引入到遗留应用程序中,那么您可能犯的最大错误就是将其误用为服务定位器。DI+框架本身是伟大的,只是让事情变得更好,我看到它!从组织的角度来看,每一个新的过程、技术、模式……都有共同的问题:

你必须训练你的团队 您必须更改您的应用程序(这包括风险)

一般来说,你必须投入时间和金钱,除此之外,没有任何负面影响,真的!

其他回答

这是我自己的第一反应:基本上任何模式都有同样的缺点。

学习是需要时间的 如果误解了,就会弊大于利 如果走到极端,工作量可能会超过收益

这更像是吹毛求疵。但是依赖注入的一个缺点是,它使开发工具更难推理和导航代码。

具体来说,如果你在代码中控制-单击/命令-单击方法调用,它将带你到接口上的方法声明,而不是具体的实现。

这实际上是松散耦合代码(由接口设计的代码)的缺点,即使不使用依赖注入(即,即使只是使用工厂)也适用。但是依赖注入的出现真正鼓励了松耦合代码的普及,所以我想我应该提到它。

而且,松散耦合代码的好处远远超过这一点,因此我称之为吹毛求疵。尽管我工作了很长时间,知道如果您试图引入依赖注入,可能会遇到这种情况。

事实上,我敢大胆地猜测,对于依赖注入的每一个“缺点”,您都会发现许多优点远远超过它。

我发现构造函数注入会导致构造函数又大又丑(我在整个代码库中都使用它——也许我的对象太细了?)此外,有时使用构造函数注入会导致可怕的循环依赖(尽管这种情况非常罕见),因此您可能会发现自己必须在更复杂的系统中拥有某种就绪状态生命周期,并进行几轮依赖注入。

然而,我更喜欢构造器注入而不是setter注入,因为一旦我的对象被构造,那么我就可以毫无疑问地知道它处于什么状态,它是在单元测试环境中还是加载到某个IOC容器中。这,以一种迂回的方式说,我觉得是setter注入的主要缺点。

(作为旁注,我确实发现整个主题相当“宗教”,但你的成就将随着开发团队的技术狂热程度而变化!)

基于构造函数的依赖注入(没有神奇的“框架”的帮助)是构造OO代码的一种干净而有益的方式。在我所见过的最好的代码库中,经过多年与Martin Fowler的其他前同事的相处,我开始注意到大多数以这种方式编写的优秀类最终都只有一个doSomething方法。

那么,主要的缺点是,一旦您意识到这只是一种笨拙的、冗长的OO方式,将闭包编写为类,以获得函数式编程的好处,那么您编写OO代码的动机就会迅速消失。

它可以增加应用启动时间,因为IoC容器应该以适当的方式解析依赖关系,有时需要进行多次迭代。