何时使用依赖注入

Cod*_*key 48 dependency-injection

在过去的几天里,我有一种感觉,依赖注入应该被称为"我无法下定决心" - 模式.我知道这可能听起来很愚蠢,但实际上这是为什么我应该使用依赖注入(DI)的原因.通常据说我应该使用DI来实现更高水平的松散耦合,并且我得到了那个部分.但实际上......一旦我的选择落在MS SQL或MySQL上,我多久更换一次数据库.很少这么做对吗?

有没有人有一些非常令人信服的理由为什么DI是要走的路?

Jas*_*orn 50

两个字,单元测试.

DI最令人信服的原因之一是允许更轻松的单元测试而无需访问数据库并担心设置"测试"数据.

  • 单元测试根本不需要DI.如果你需要替换"真正的"数据库实现,那么设置一个mock/fake实现并测试...当然,对于某些语言(例如,C++)或某些模拟工具,这并不总是可行的,但是事实上它通常是可行的意味着单元测试本身并不总是一个正当理由. (21认同)
  • 无需点击真正的数据库,您的测试运行速度会快得多.此外,当您测试特定情况时,您可以更轻松地在模拟对象中设置这些特定情况,而不必担心测试数据库是否处于正确状态. (7认同)
  • 对不起,我不认为这个答案是完整的.在本文中通过"嘲弄"替换DI会更有意义.DI对于更多场景非常有用,因为它鼓励组件之间的松散耦合. (6认同)
  • 所以你在谈论解耦数据库,并"伪造它",通过使用一些虚假的对象,而不是在我的单元测试期间更改我的数据库...嗯......听起来真的是一个合理的论点! (3认同)
  • 如果您正在使用TDD开发(并且您应该!),那么您每30秒运行一次测试套件.那么你不能承受超过几秒钟的运行时间. (2认同)

Mic*_*ick 12

DI对于解耦系统非常有用.如果您正在使用它是为了将数据库实现与应用程序的其余部分分离,那么您的应用程序非常简单,或者您需要对问题域进行更多分析并发现问题域中的哪些组件是最有可能改变的,以及系统中具有大量耦合的组件.

当您的目标是代码重用,多功能性和对问题域中的更改的稳健性时,DI最有用.

与项目的相关程度取决于代码的预期寿命.根据您正在进行的工作类型,对于您正在编写的大多数代码,从一个项目到下一个项目的零重用实际上可能是完全可以接受的.

使用DI的一个示例是创建一个应用程序,该应用程序可以使用DI为客户端部署多个客户端进行部署,也可以将其描述为GOF策略模式.使用DI框架可以促进许多GOF模式.

DI与企业应用程序开发更相关,在这种应用程序开发中,您拥有大量代码,复杂的业务需求以及期望(或希望)系统将维护多年或数十年.


fro*_*h42 7

即使您在开发阶段没有更改程序的结构,您也会发现需要从程序的不同部分访问多个子系统.使用DI,您的每个课程都需要提供服务,而您无需手动提供所有连线.

这真的有助于我专注于软件设计中的事物的互动,而不是"谁需要随身携带,因为其他人以后需要它".

此外,它还节省了大量编写样板代码的工作.我需要一个单身人士吗?我只是将一个类配置为一个.我可以用这样的"单身人士"进行测试吗?是的,我仍然可以(因为我只是将它配置为仅存在一次,但测试可以实例化替代实现).

但是,顺便说一句,在我使用DI之前,我并没有真正理解它的价值,但尝试它对我来说真是让人大开眼界:我的设计比以前更加面向对象.顺便说一句,在目前的应用程序中,我不进行单元测试(糟糕,糟糕的我),但我仍然不能再使用DI了.移动事物并保持简单的课程变得更加容易.


Jam*_*ers 5

虽然我在数据库示例中与您达成一致意见,但我发现有助于使用DI的大事之一是帮助我测试我在数据库之上构建的层.

这是一个例子......

你有你的数据库.

您拥有访问数据库并返回对象的代码

您有业务域对象,它们接受前一项的对象并使用它们执行某些逻辑.

如果将数据访问权限与业务域逻辑合并,则域对象可能难以测试.DI允许您将自己的数据访问对象注入到域中,这样您就不依赖于数据库进行测试或可能进行演示(运行一个演示,其中一些数据是从xml而不是数据库中提取的).

抽象第三方组件和这样的框架也会对您有所帮助.

除了测试示例之外,还有一些地方可以通过"按合同设计"方法使用DI.您可能会发现创建一个类型的处理引擎是合适的,这些引擎会调用您注入其中的对象的方法.虽然它可能不会真正"处理它",但它会运行在您提供的每个对象中具有不同实现的方法.

我看到了一个这样的例子,其中每个业务域对象都有一个"保存"功能,它被注入处理器后被调用.处理器使用配置信息修改组件,Save处理对象的主要状态.实质上,DI补充了符合接口的对象的多态方法实现.