"Ruby方式"(mixins和类重新开放)与依赖注入

Cha*_*son 18 ruby dependency-injection ruby-on-rails mixins

在研究mixins与依赖注入时,我经常听到"Ruby方式"这个短语.开发人员通常会说些什么

Ruby允许您重新打开类并重新定义方法意味着您可以在测试时轻松地将新引用"注入"代码中.

(见http://weblog.jamisbuck.org/2007/7/29/net-ssh-revisited#6)

但测试不是我主要关心的问题; 我担心的是课堂重用.我想要可以在多个企业级Rails应用程序中重用的类.

那么REUSING类会发生什么?使用mixins和重新打开类似乎并没有提供一种方法来编写类,使它们与特定于应用程序的细节分离,而无需额外的工作.但也许我错了.如果是的话,是否有人可以提供包含示例代码的文章的链接,该文章清楚地解释了如何使用mixins和重新打开类来正确地完成此操作?

例如,这里的类Foo耦合到类Logger:

class Foo
  def initialize
    @logger = new_logger
  end

  def new_logger
    Logger.new
  end
end
Run Code Online (Sandbox Code Playgroud)

是的,我可以重新打开Foo并重新定义new_logger,但我无法相信这被认为是编写可由多个Rails应用程序使用的可重用类的现实标准方法.

iaf*_*nov 9

实际上当我从Java世界来到ruby世界时,我感兴趣的第一件事是他们如何管理依赖关系.当时我在所有Java项目中使用Google Guice,我的灵感来自于其巧妙的设计和易用性.我在ruby中做的第一件事就是我自己的DI容器,与Google Guice具有大致相同的功能 - (它仍然在github上,但它已经过时了).

但是在使用Rails/Ruby两年后,我认为这里不需要DI.关于红宝石中DI的好文章是http://weblog.jamisbuck.org/2008/11/9/legos-play-doh-and-programming它实际上是一篇关于为什么其中一个作者不需要DI的文章.第一个用于红宝石的DI容器.绝对值得一读.


sko*_*rks 5

好吧,因为我们可以在Ruby中重新打开类并不意味着我们总是必须这样做,你可以把重新开放的类作为最后的方法.你有一个库可以完成你需要的一切,除了一个方法,而不是分支整个库修补它并使用你的分支,你可以简单地重新打开类,重新定义方法,你再次开展业务.这不是你不会做的事情,但有能力这样做是非常有用的.

说完所有这些,在Ruby中我们有一个概念几乎总是可以替代依赖注入 - 鸭子打字.由于没有类型检查,您可以将任何对象传递给函数,只要该对象具有该函数所期望的方法,一切都将正常工作.

让我们看看你的例子 - 它不是真正有利于依赖注入的类,你不会在Java中编写它,例如,如果你想注入一些依赖项.您只能通过构造函数或通过getter和setter注入.所以让我们以这种方式重写这个类:

class Foo
  def initialize(logger)
    @logger = logger
  end
end
Run Code Online (Sandbox Code Playgroud)

我们现在可以更好地将记录器注入/传入我们的Foo类.让我们添加一个方法,使用此记录器来演示:

class Foo
  def initialize(logger)
    @logger = logger
  end

  def do_stuff
    @logger.info("Stuff")
  end
end
Run Code Online (Sandbox Code Playgroud)

在java中,如果你想Foo用不同类型的记录器创建对象,那么所有这些记录器都必须在非常字面意义上实现相同的接口(例如public class logger implements Loggable),或者至少是子类.但是在Ruby中,只要对象有一个info接受字符串的方法,你就可以将它传递给构造函数,并且Ruby继续快乐地进行.让我们来证明:

class Logger
  def info(some_info)
  end
end

class Widget
  def info(some_widget_info)
  end
end

class Lolcat
  def info(lol_string)
  end
end

Foo.new(Logger.new).do_stuff
Foo.new(Widget.new).do_stuff
Foo.new(Lolcat.new).do_stuff
Run Code Online (Sandbox Code Playgroud)

通过Foo调用do_stuff方法的类的上述所有3个实例,一切都会正常工作.

正如你从这个例子中看到的那样,坚持OO设计的原则仍然很重要,但Ruby对它接受的内容的限制较少,只要正确的方法存在,一切都会好的.

根据你的看法,鸭子打字要么使依赖注入完全不相关,要么使它比以前更强大.


nes*_*983 1

我完全同意。动态语言不能替代依赖注入。没有什么可以阻止你为动态语言编写一个。这是 Smalltalk 的依赖注入框架:http ://www.squeaksource.com/Seuss.html