12

为了编写可测试的 C# 代码,我大量使用 DI。

然而最近我一直在搞乱 IronPython,发现你可以模拟任何方法/类/函数等......你喜欢,对 DI 的需求已经消失。

对于 Python 等动态语言,情况是否如此?

代替:

class Person(Address) {
...

你可以有:

class Person() {
...
    // Address initialised in here.

对于动态语言,因此根本不需要遵循动态语言的手动 DI。

对此有何建议?

4

4 回答 4

10

依赖注入也是关于如何将事物连接在一起——这与依赖对象的可模拟性无关。拥有一个Foo需要某种 -connection 的 -instance直接Bar实例化它和让它完全忽略它是如何获得该连接的,只要它拥有它,这是有区别的。

如果您使用依赖注入,您还将获得更好的可测试性。但反之则不然。通过覆盖任何东西来更容易测试并不会带来依赖注入的其他优点。正是出于这些原因,有许多用于 Python 的组件/DI 框架可用。

于 2009-12-24T01:02:21.017 回答
10

我强烈不同意您关于动态类型语言不需要依赖注入的说法。DI 有用和必要的原因完全独立于语言的打字规则。

主要区别在于动态类型语言中的 DI 简单且无痛:您不需要重量级框架和大量 XML 配置行。

例如,在 Ruby 中,只有两个 DI 框架。两者都是由 Java 程序员编写的。这两个框架都没有被单个项目使用。甚至不是那些框架的作者

但是,在 Ruby 中到处都在使用 DI。

Jamis Buck 是这两个框架的作者,他在 RubyConf 2008 上发表了一个名为Recovering from Enterprise的演讲,讲述了他如何以及为什么编写这些框架以及为什么这是一个坏主意,非常值得一看。如果您想阅读,还有一篇随附的博客文章。(每次他说“Ruby”时都替换为“Python”,一切都一样有效。)

于 2009-12-24T01:24:39.920 回答
0

我会再尝试。我的最后一个答案错过了这个问题,并且偏离了主题。

使用伪代码,依赖注入说:

class Person
  def Chat() { 
    someOperation("X","Y","Z")
  end
end
...
Person.new().Chat()

并与:

class Person
  initialize(a,b,c)
    @a=a
    @b=b
    @c=c
  end
  def Chat()
    someOperation(@a,@b,@c)
  end
end
...
Person.new("X","Y","Z").Chat()

,., 并且通常将对象和调用放入不同的文件以用于 SCM 目的。

“X”、“Y”或“Z”是否是可模拟的(......如果它们是对象......(!)......(!)......)与 DI 是否好完全无关. 真的。:-)

DI 在 Python 或 Ruby 中更容易,就像许多其他任务一样,因为有更多的脚本方法,就像 Jörg 说的那样;当然也少了一种文化和一种趋势,即常量和适配器将被填充到模型和全局常量中。

实际上,对我来说,DI 是将这些应用程序参数、API 常量和工厂分离到单独的文件中的第一步,以帮助使您的修订跟踪报告看起来不那么像意大利面条(“那些在 AppController 上额外签入以更改配置。 .? 或更新代码...?”)和更多信息,更易于阅读。

我的建议:继续使用 DI ... :-)

于 2009-12-27T20:39:14.617 回答
-2

我认为您提出的问题似乎与最佳实践有关,但实际上与运行时性能有关。

摆脱依赖注入?软件发布经理如何在晚上睡觉?

要执行的功能测试肯定会使程序减慢一到两次。

// my generic function entry point - IronPython
if func="a":
  ...
if func="b":
  ...
if func="c":
  ...

您可以将标准 Python 与类一起使用......或者您可以将函数指针分配给函数指针成员。到底是怎样的野兽……??我知道我知道。我认为 Python 很难定义,但我喜欢它。而且我喜欢并高度重视依赖注入,并不是说我长期以来一直想为这种做法分配如此冗长的名称。

于 2009-12-24T01:12:32.797 回答