4

有人说最好使用依赖注入。这是为什么?

我认为最好有几个全局的、易于访问的类,而不是庞大的构造函数。

它是否以任何方式影响应用程序速度?

这两者的混合可能是最好的。

4

4 回答 4

5

主要优点是解耦,这将有助于单元测试。这种类型完全取决于您如何编写这些“易于访问的类”。

这个想法是这样的。一个类通过仅依赖于契约( ) 来从实现( ) 依赖中解耦。在您的实际环境中,您可能永远不会提供新的实现类,但在您的测试环境中,您很可能会提供(无论是手工制作的存根,还是来自模拟框架的模拟类)。classinterface

应用程序速度需要分析,但是使用 DI 框架可能会产生一些开销,而不是直接与你知道的单例对话。重要的问题:这是开销问题吗?只有性能预期和分析可以告诉您这一点。根据我的经验,好处远远超过了可忽略不计的性能损失。

于 2012-05-01T08:57:10.807 回答
4

您可能会使用static类和方法作为全局变量。它们对性能没有任何影响。但是,静态类不适合可测试性

静态方法的缺点是什么?

此外,一旦您的代码与静态类(全局)紧密耦合,您将来将无法用替代实现替换它们。因此,除非在非常简单的情况下使用,否则 Globals 可能不是好的设计。

请注意,静态类和方法是编译时绑定,而DI 是运行时绑定帮助您保持类松散耦合

于 2012-05-01T08:56:48.847 回答
1

使用“全局变量”和 DI 之间存在巨大差异。首先,路径通常不是定向的,因为您可能会逐步通过单例服务定位器. 今天,两者都被认为是一种反模式。原因是我们应该设计可测试的代码,这在我们需要更改代码库以进行维护或满足新需求时为我们提供了很大的优势。如果代码解耦,可测试性很容易实现。正如您猜测的那样,全局行为无助于解耦,例如,如果您有代码加入静态单例,要测试这样的代码,您需要单例本身,您不能模拟它,这很糟糕,因为您不能随心所欲地给你的系统施加压力。服务定位器乍一看似乎更好:如果您需要测试,您可以模拟服务定位器,但您必须:

  • 提前知道被测系统将向定位器询问哪些服务
  • 始终创建一个“递归模拟”,因为您可能也会模拟返回的服务。

构造函数上的 DI 是代码解耦的好方法,因为您非常清楚地说明了对象需要运行什么,并且您可以一眼决定要模拟什么,存根等等。请注意,只要您确保 DI 内核不会作为依赖项在您的代码中运行,DI 就会起作用并为您提供帮助:这会将 DI 转换为反模式(您将代码解耦,但将其绑定到容器),所以记得学习并真正实现组合根模式,这将真正帮助您编写更好和可测试的代码。

于 2012-05-01T09:15:39.990 回答
1

我认为关于这个主题的顶帖对 DI 以及如何正确使用它有一个很好的总结:Dependency Inject (DI) "friendly" library

如果您想更深入地研究该主题,我可以推荐 Mark Seeman 的书“.NET 中的依赖注入”。

于 2012-05-02T11:20:24.207 回答