你什么时候使用依赖注入?

时间:2008-08-26 15:55:44

标签: dependency-injection

我最近一直在使用StructureMap并且彻底享受了这种体验。但是,我可以看到如何通过连接所有内容轻松地将其带走,并最终获得将大量接口引入其构造函数的类。尽管当你使用依赖注入框架时,这确实不是一个大问题,但它仍然认为某些属性实际上不需要为了连接它们而被接口化。

你在哪里绘制关于界面的界限与仅仅向类中添加属性?

9 个答案:

答案 0 :(得分:22)

依赖注入的主要问题是,虽然它给出了松散耦合架构的外观,但它实际上并没有。

你真正在做的是将这种耦合从编译时移到运行时,但是如果A类需要一些接口B工作,仍然需要提供实现接口B的类的实例。

依赖注入只应用于需要动态更改的应用程序部分,而无需重新编译基本代码。

使用我认为对于反转控制模式有用的东西:

  • 插件架构。因此,通过制作正确的入口点,您可以定义必须提供的服务的合同。
  • 类似工作流的架构。您可以在其中连接多个组件,动态地将组件的输出连接到另一个组件的输入。
  • 每个客户端应用程序。假设您拥有各种客户,可以为项目的一系列“功能”付费。通过使用依赖注入,您可以轻松提供核心组件和一些“添加”组件,这些组件仅提供客户已支付的功能。
  • 翻译。虽然通常不会出于翻译目的,但您可以根据应用程序的需要“注入”不同的语言文件。这包括RTL或LTR用户界面。

答案 1 :(得分:9)

考虑一下你的设计。 DI允许您通过配置更改来更改代码的功能。它还允许您打破类之间的依赖关系,以便您可以更轻松地隔离和测试对象。你必须确定这有意义的地方和不合适的地方。没有轻拍的答案。

一个好的经验法则是,如果它太难测试,那么你就会遇到一些单一责任和静态依赖的问题。将执行单个函数的代码隔离到类中,并通过提取接口并使用DI框架在运行时注入正确的实例来中断静态依赖性。通过这样做,您可以轻松地分别测试这两个部分。

答案 2 :(得分:8)

  

依赖注入只应用于部分   需要动态更改的应用程序,无需重新编译   基本代码

DI应该用于将代码与外部资源(数据库,Web服务,xml文件,插件架构)隔离开来。如果您正在测试数据库上的DEPEND组件,那么在许多公司中,在代码中测试逻辑所需的时间几乎是令人望而却步的。

在大多数应用程序中,数据库不会动态更改(尽管可能),但一般来说,将应用程序绑定到特定外部资源几乎总是好的做法。涉及更改资源的金额应该很低(数据访问类应该很少在其方法中具有高于一的圈复杂度。)

答案 3 :(得分:2)

“只是在课程中添加属性是什么意思?”

我的经验法则是使类单元可测试。如果您的类依赖于另一个类的实现细节,则需要对其进行重构/抽象,以便可以单独测试类。

编辑:你在构造函数中提到了一大堆接口。我建议改用setter / getters。我发现从长远来看,它使维护更容易。

答案 4 :(得分:2)

只有当它有助于分离关注点时才会这样做。

就像跨项目一样,我会为我的一个图书馆项目中的实施者提供一个界面,实施项目会注入他们想要的任何具体实现。

但那是关于它的...所有其他情况它只是让系统不必要地复杂

答案 5 :(得分:1)

即使有了世界上所有的事实和过程......每一个决定都归结为一个判断电话 - 忘了我读到的地方
我认为这更像是一次体验/飞行时间的召唤。 基本上,如果您将依赖关系视为可能在不久的将来被替换的候选对象,请使用依赖注入。如果我将'classA及其依赖项'视为替换的一个块,那么我可能不会将DI用于A的代表。

答案 6 :(得分:1)

最大的好处是它可以帮助您理解甚至揭示应用程序的体系结构。您将能够非常清楚地看到您的依赖链如何工作,并能够对各个部分进行更改,而无需您更改不相关的内容。你最终会得到一个松散耦合的应用程序。这将推动您进入更好的设计,当您可以继续进行改进时,您会感到惊讶,因为您的设计将帮助您继续分离和组织代码。它还可以促进单元测试,因为您现在可以自然地替换特定接口的实现。

有些应用程序只是一次性使用,但如果有疑问,我会继续创建接口。经过一些练习后,这不是一个负担。

答案 7 :(得分:0)

我要解决的另一个问题是我应该在哪里使用依赖注入?你在哪里依赖于StructureMap?仅在启动应用程序中?这是否意味着所有实现必须从最顶层到最底层一直向下移动?

答案 8 :(得分:0)

我使用Castle Windsor / Microkernel,我没有其他任何经验,但我非常喜欢它。

至于你如何决定注射什么?到目前为止,以下经验法则对我有用:如果类非常简单,不需要单元测试,您可以随意在类中实例化它,否则您可能希望通过构造函数获得依赖。

至于你是否应该创建一个接口而不仅仅是使你的方法和属性成为虚拟的我认为你应该去接口路由,如果你或者a)可以看到该类在不同的应用程序中具有某种程度的可重用性(即记录器) )或b)如果由于构造函数参数的数量或者因为构造函数中存在大量逻辑,则该类很难被模拟。