首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当使用依赖项注入时,如何在运行时创建I/O类型(例如文件)

当使用依赖项注入时,如何在运行时创建I/O类型(例如文件)
EN

Stack Overflow用户
提问于 2014-04-16 23:36:09
回答 1查看 51关注 0票数 0

即使使用DI,我们的业务/服务类型也需要在它们的方法中创建一些传递对象。这些传递对象总是值类型(代表纯数据)或I/O类型(表示外部状态)。值类型可以新建,但是我们希望在测试中模拟/存根的I/O类型,所以我们不能直接创建它们。

我看到的常见解决方案是给类某种IOFactory依赖:在生产过程中,我们为生成真实I/O对象的类提供一个工厂;在测试中,我们为生成假I/O对象的类提供一个工厂。

我不喜欢的是,不仅要创建模拟/存根I/O类型,还要为真正的类型及其替代品创建工厂。这感觉很累人,特别是在像JS这样的动态语言中,我常常可以轻松地为每个测试创建我的模拟/存根。

我想到的另一种方法是使用注射器,有点像服务定位器.

代码语言:javascript
复制
var file = injector.inject(File, '/path');  // given type, returns new instance of that type

...such --在生产中,注入器被配置为提供一个真正的文件,而在测试中,它被配置为返回一个模拟/存根。我们可以将注入器看作一个特殊的全局,但可以说,注入器现在是每个需要使用它的业务类型的依赖项,因此应该像任何其他依赖项一样注入它。

我所看到的支持这一观点的主要论点是,在许多情况下,喷油器可以减少工厂样板(代价是额外的工厂配置工作)。反对的理由是什么?工厂是否更好,因为它们更具体地声明了类需要什么,从而充当文档?还是正确的解决方案完全不同?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-04-17 18:53:13

如何使用injector作为服务定位器

服务定位器有时被描述为反模式,因为:

  • 错误地使用它会导致难以维护的代码。
  • 它很容易被错误地使用。

(一些开发人员提出异议称其为反模式,但仍然普遍认为它有特定的用途,而且经常被滥用。)

您所描述的injector是反模式的主要示例。有了它,您的对象现在将有一个隐藏的所需的依赖项--它的构造函数中没有声明该依赖项。

如果在对象使用时未配置注入器,则会发生运行时错误。可能有人没有意识到,为了使对象正常工作,需要这种配置(您甚至可能是6个月后的某个人)。

依赖注入背后的思想是,对象非常明确地说明它需要什么才能按预期行事。其基本原理与接口maxim:容易正确使用;难以正确使用使用的原理相同。

您说得对,有时需要引入工厂才能动态实例化对象,这是非常麻烦的--但很多这种样板通常植根于许多OO语言冗长的语法中,而不一定是依赖注入的概念。

因此,为了短期的方便使用Service方法是可以的(就像任何其他全局变量一样)只要您意识到这是它在这种情况下真正提供的全部功能。

至于替代方法,请不要忘记,所需的依赖项不一定需要作为构造函数参数传递。

与将工厂传递给类的构造函数不同,有时使用工厂法方法是有意义的。也就是说,强制派生类提供依赖关系,而不是期望它来自对象的创建者。

如果可以使用有意义的默认依赖项(例如空对象)初始化SUT,则可以考虑在setter方法中注入该依赖项。

在C/C++中,开发人员有时甚至依赖链接器来处理依赖注入。詹姆斯·格伦宁在他的书“嵌入式C的测试驱动开发”中写道:

要打破对生产代码的依赖,只考虑协作者的接口。..。接口由头文件表示,实现由源文件表示。LightScheduler SUT在链接时绑定到生产代码实现。 单元测试通过提供替代实现来利用link。(临120)

最后,问问你希望从依赖注入中得到什么。如果它的好处并不超过实现它所涉及的工作,那么它可能是不必要的。但不要为了在短期内节省一点时间而回避它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23122074

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档