Design patterns 使用依赖注入的缺点是什么?
我试图将DI作为一种模式引入工作中,我们的一位主要开发人员想知道:使用依赖注入模式的缺点是什么 请注意,我在这里寻找一个——如果可能的话——详尽的列表,而不是关于这个主题的主观讨论Design patterns 使用依赖注入的缺点是什么?,design-patterns,dependency-injection,Design Patterns,Dependency Injection,我试图将DI作为一种模式引入工作中,我们的一位主要开发人员想知道:使用依赖注入模式的缺点是什么 请注意,我在这里寻找一个——如果可能的话——详尽的列表,而不是关于这个主题的主观讨论 澄清:我说的是依赖注入模式(见Martin Fowler),而不是一个特定的框架,无论是基于XML(如Spring)还是基于代码(如Guice)还是“自滚式” 编辑:这里正在进行进一步的讨论/咆哮/辩论 我自己的初步反应是:基本上任何模式都有相同的缺点 学习需要时间 如果被误解,可能弊大于利 如果把它发挥到极致
澄清:我说的是依赖注入模式(见Martin Fowler),而不是一个特定的框架,无论是基于XML(如Spring)还是基于代码(如Guice)还是“自滚式”
编辑:这里正在进行进一步的讨论/咆哮/辩论 我自己的初步反应是:基本上任何模式都有相同的缺点
- 学习需要时间
- 如果被误解,可能弊大于利
- 如果把它发挥到极致,它可能会比证明其好处的工作更多
- DI增加了复杂性,通常是通过增加类的数量来实现的,因为职责分离得更多,这并不总是有益的
- 您的代码将(在某种程度上)耦合到您使用的依赖注入框架(或者更一般地说,您决定如何实现DI模式)
- 执行类型解析的DI容器或方法通常会产生轻微的运行时惩罚(可以忽略不计,但确实存在)
通常,解耦的好处是使每个任务更易于阅读和理解,但会增加编排更复杂任务的复杂性。如果您有一个自主开发的解决方案,那么在构造函数中,依赖关系就在您面前。或者作为方法参数,同样也不难发现。尽管框架管理的依赖关系,如果走到极端,可能会开始像魔术一样出现 然而,在太多的类中有太多的依赖项是一个明显的迹象,表明您的类结构是错误的。因此,在某种程度上,依赖项注入(自主开发或框架管理)有助于解决隐藏在黑暗中的突出设计问题
为了更好地说明第二点,这里有一段摘自()的内容,我衷心相信这是构建任何系统的根本问题,而不仅仅是计算机系统 假设你想设计一个大学校园。你必须把一些设计委托给学生和教授,否则物理大楼对物理专业的人来说就不好用了。没有一个架构师足够了解人们自己需要做什么。但是你不能把每个房间的设计都委托给它的居住者,因为那样你会得到一大堆瓦砾 如何在保持整体设计的一致性和协调性的同时,将设计责任分配到大型层次结构的所有级别?这是亚历山大试图解决的建筑设计问题,但也是计算机系统开发的一个基本问题
DI解决了这个问题吗否。但是,如果你试图将设计每个房间的责任委托给居住者,这确实有助于你清楚地看到。我认为不存在这样的列表,但是请阅读以下文章:
与Mark Seemann的回答类似,底线是你要花时间成为一名更好的开发人员,而不是把代码拼凑在一起,然后扔出大门/投入生产。您的企业更愿意选择哪一种?只有你能回答这个问题。控制反转最大的“缺点”(不完全是DI,但足够接近)是,它倾向于去掉单一点来查看算法概述。不过,这基本上就是当您使用解耦的代码时会发生的情况-在一个地方查看的能力是紧密耦合的产物。我发现构造函数注入可能会导致大而丑陋的构造函数(我在整个代码库中都使用它-也许我的对象太细粒度了?)。此外,有时构造函数注入会导致可怕的循环依赖(尽管这是非常罕见的),因此您可能会发现自己必须在更复杂的系统中进行几轮依赖注入,从而获得某种就绪状态生命周期 然而,我更喜欢construtor注入而不是setter注入,因为一旦构建了我的对象,我就毫无疑问地知道它处于什么状态,不管它是在单元测试环境中还是加载在某个IOC容器中。以一种迂回的方式,我认为这是塞特注射的主要缺点
(作为旁注,我确实觉得整个主题非常“宗教化”,但您的里程数将随开发团队的技术狂热程度而变化!)DI是一种技术或模式,与任何框架都不相关。您可以手动连接依赖项。DI帮助您完成SR(单一责任
void Say_Hello_World ()
{
std::cout << "Hello World" << std::endl;
}
void Say_Something (const char *p_text)
{
std::cout << p_text << std::endl;
}
Public Class MyClass
Private ReadOnly mExLogHandlerService As IExceptionLogHandlerService
Public Sub New(exLogHandlerService As IExceptionLogHandlerService)
Me.mExLogHandlerService = exLogHandlerService
End Sub
...
End Class