Ruby 组织猴子补丁

Ruby 组织猴子补丁,ruby,oop,monkeypatching,Ruby,Oop,Monkeypatching,我读了一篇文章,其中建议给你的猴子补丁命名,这样它们就可以很容易地查看和包含 例如: module CoreExtensions module DateTime module BusinessDays def weekday? !sunday? && !saturday? end end end end 将进入:lib/core\u extensions/class\u name/group.rb文件 它可以通过模

我读了一篇文章,其中建议给你的猴子补丁命名,这样它们就可以很容易地查看和包含

例如:

module CoreExtensions
  module DateTime
    module BusinessDays
      def weekday?
        !sunday? && !saturday?
      end
    end
  end
end
将进入:
lib/core\u extensions/class\u name/group.rb
文件

它可以通过
模块#include
实例方法包含在DateTime类中(类继承该方法是因为
模块

我的问题是include语句去哪里了?有会议吗

例如:

module CoreExtensions
  module DateTime
    module BusinessDays
      def weekday?
        !sunday? && !saturday?
      end
    end
  end
end
我有以下猴子补丁:

# http://www.justinweiss.com/articles/3-ways-to-monkey-patch-without-making-a-mess/
module CoreExtensions
  module String
    module Cases
      def snakecase
        return self if self !~ /[A-Z]+.*/
        # http://rubular.com/r/afGWPWLRBB
        underscored = gsub(/(.)([A-Z])/, '\1_\2')
        underscored.downcase
      end

      def camelcase
        return self if self !~ /_/ && self =~ /[A-Z]+.*/
        split('_').map{ |e| e.capitalize }.join
      end
    end
  end
end
它位于
lib/core\u extensions/string/cases.rb
文件中

我应该把我的
String.include CoreExtensions::String::Cases
语句放在哪里

同样需要说明的是,这只是一个ruby项目,这会有什么不同吗

我试着把它放在
lib/device.rb

require 'devify/version'
require 'devify/some_dir'
require 'devify/scaffold'
require 'devify/tree_cloner'
require 'devify/renderer'
require 'devify/project'

require 'devify/tasks/some_task'
require 'devify/tasks/bootstrap'

require 'core_extensions/string/cases'

module Devify
  String.include CoreExtensions::String::Cases
end
这是可行的,这也解释了它为什么有效。这是因为我的整个应用程序都位于
Devify
模块或名称空间中

这种方法也很好,因为我没有污染全局名称空间,对吗?因为我是唯一一个住在
device
里面的猴子补丁
String
s


只是不确定这样做是否正确。

尽管ruby提供了许多动态更改类或方法内容的方法,但是猴子补丁可能会导致大问题和奇怪的bug。我读了这篇文章()关于为什么使用猴子补丁是个坏主意

总之,他说的很多话都有道理。当您创建一个monkey补丁时,您假设它只在该项目中起作用,并且,当有更多具有类似用途的库放在一起时,您可能会产生冲突和不可见的副作用

在某些情况下,猴子补丁的好处是惊人的,比如ActiveSupport通过使用
ago
from\u now
方法,或者作为
到\u json
的方法,对Fixnum类进行猴子补丁来处理日期操纵。但是,应避免使用猴子修补

要点是:Ruby是一种面向对象的语言,您可以使用对象组合或任何其他模式来实现您的目标。在某种程度上,Monkey patching会将您引向与面向对象哲学相反的方向,因为您会为一个预先存在的类添加更多的职责,并增加它的公共接口以提供新的功能

此外,该类的行为和可用的公共方法并不明确。通过查看类定义,您无法知道它是什么,它在系统中的角色是什么,以及它如何与其他对象交互。它使一项简单的任务最终变得更加困难


显然,猴子补丁使一切都变得更小、更简单,但避免它会使代码更易于维护、更易于调试、阅读和测试,并且更优雅,因为它符合“OOP”模式。

include
调用放在何处并不重要

调用
String.include
将始终对整个对象空间中所有字符串所使用的
String
类进行猴子补丁。因此,最好将指令放在顶层,以免误导代码的读者

猴子修补总是全球性的

这是一个强大的功能,可以长期使用

如果您正在编写gem,请注意您正在与其他人共享一个全局名称空间。顶级模块甚至gem名称也是如此。共享名称空间只是共享代码的现实

如果您正在寻找词汇范围的monkey补丁,请查看Ruby 2引入的新细化功能

改进是从Smalltalk的类框中提取的想法。然而,改进并非没有自身的问题,例如,它们缺乏对内省和反思的支持。因此,从本质上说,它们是隐形的,不适合生产使用


如果您只想将猴子补丁限制到某个字符串对象,请考虑子类<代码>字符串或在实例上调用<代码>扩展< /代码>。< /p>如果您编写“代码>字符串”,请包含< /代码>您正在污染全局命名空间的任何地方。您可以通过将该调用放入一个方法来延迟它。但是,一旦调用该方法,所有字符串都将被修补。仔细阅读作为一个不太干扰的替代方案的改进。我添加了几个例子。顺便说一下,这个文件命名约定对于Ruby编程来说是一个很好的实践。它可以帮助自动加载依赖项-例如,如果您正在使用该模式,您可以说

Dir.glob(“./***/.rb”)。按{path{124; path.count(“/”)对u进行排序。每个{124; path{124;都需要path}
,它将加载所有文件,按照文件名中
/
的计数排序(考虑您的常量层次结构)