自从学习(和热爱)自动化测试以来,我发现自己几乎在每个项目中都使用了依赖注入模式。在使用自动化测试时,使用这种模式总是合适的吗?有什么情况需要避免使用依赖注入吗?
发布于 2012-02-21 11:11:52
基本上,依赖注入对对象的性质做出了一些(通常但并非总是有效的)假设。如果这些都是错误的,DI可能不是最好的解决方案:
new
而忘记它要痛苦得多。所有这些,再一次解决一个可能没有问题的地方。
发布于 2012-02-20 16:39:56
在依赖注入框架之外,依赖注入(通过构造函数注入或setter注入)几乎是一个零和游戏:您减少了对象A与其依赖项B之间的耦合,但现在任何需要A实例的对象现在也必须构造对象B。
您已经稍微减少了A和B之间的耦合,但是减少了A的封装,增加了A和任何必须构造A实例的类之间的耦合,方法是将它们耦合到A的依赖项。
因此,依赖注入(没有框架)同样有害,因为它是有用的。
然而,额外的成本通常是合理的:如果客户端代码比对象本身更了解如何构造依赖项,那么依赖注入确实减少了耦合;例如,Scanner不知道如何获得或构造要解析输入的输入流,或者客户端代码希望解析输入的源,因此构造函数注入输入流是显而易见的解决方案。
为了能够使用模拟依赖项,测试是另一个理由。这应该意味着添加一个只用于测试的额外构造函数,该构造函数允许注入依赖关系:如果您将构造函数更改为总是要求注入依赖项,那么突然之间,您必须了解依赖项的依赖项,才能构造直接依赖关系,并且无法完成任何工作。
这可能很有帮助,但是您应该明确地问自己每个依赖项,测试的好处值得花费吗?我真的想在测试时模拟这种依赖吗?
当添加依赖注入框架,并且依赖关系的构造不是委托给客户端代码,而是委托给框架时,成本/效益分析就会发生很大的变化。
在依赖注入框架中,权衡有一点不同;注入依赖关系所失去的是,您能够轻松地知道您所依赖的实现,并将决定您所依赖的依赖项的责任转移到某些自动解决过程(例如,如果我们需要一个@ injecting‘’ed,必须有某种东西“提供Foo,其注入的依赖项是可用的)”,或者是一些高级配置文件,该文件规定了每个资源应该使用什么提供程序,或者是这两者的某个混合体(例如,对于依赖项可能会有一个自动解决过程,如果必要的话,可以使用配置文件)。
在构造函数注入中,我认为这样做的好处同样与这样做的成本非常相似:您不需要知道是谁提供了您所依赖的数据,如果有多个潜在的提供程序,您不需要知道首选的检入提供程序的顺序,确保每个需要对所有潜在提供者进行数据检查的位置,等等,因为所有这些都是由依赖注入平台在较高级别上处理的。
虽然我个人对DI框架没有太多的经验,但我的印象是,当查找您需要的数据或服务的正确提供者时,当您需要的数据或服务的正确提供者遇到麻烦时,当某些事情失败时,无法立即知道本地是什么代码提供了错误的数据,导致您的代码出现故障时,它们带来的好处大于成本。
在某些情况下,在DI框架出现时,已经采用了一些模糊依赖关系的模式(例如服务定位器)(也许也证明了它们的价值),而采用DI框架是因为它们提供了一些竞争优势,例如需要更少的样板代码,或者在需要确定实际使用的提供者时,更少地掩盖依赖关系的提供者。
发布于 2012-02-20 14:09:02
不要使用服务定位器作为依赖注入替代,它是反模式的,更多信息:http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx
https://softwareengineering.stackexchange.com/questions/135971
复制