ruby - 修补 Ruby 的基类(例如 Fixnum)是否可以接受?

标签 ruby monkeypatching

我对 Ruby 还是很陌生(通读 Pickaxe 并将大部分时间花在 irb 上),现在我知道可以在 Ruby 中修补类,我想知道什么时候这样做是可以接受的,特别是修补 Ruby 的基类是否可以接受。例如:我回答了另一个 Ruby 问题 here张贴者想知道如何从 DateTime 中减去小时数。由于 DateTime 类似乎没有提供此功能,因此我发布了一个答案,将 DateTimeFixnum 类作为可能的解决方案进行了修补。这是我提交的代码:

require 'date'

# A placeholder class for holding a set number of hours.
# Used so we can know when to change the behavior
# of DateTime#-() by recognizing when hours are explicitly passed in.

class Hours
   attr_reader :value

   def initialize(value)
      @value = value
   end
end

# Patch the #-() method to handle subtracting hours
# in addition to what it normally does

class DateTime

   alias old_subtract -

   def -(x) 
      case x
        when Hours; return DateTime.new(year, month, day, hour-x.value, min, sec)
        else;       return self.old_subtract(x)
      end
   end

end

# Add an #hours attribute to Fixnum that returns an Hours object. 
# This is for syntactic sugar, allowing you to write "someDate - 4.hours" for example

class Fixnum
   def hours
      Hours.new(self)
   end
end

我修补了这些类,因为我认为在这种情况下,它会产生一种清晰、简洁的语法,用于从 DateTime 中减去固定的小时数。具体来说,您可以根据上述代码执行类似这样的操作:

five_hours_ago = DateTime.now - 5.hours

这看起来相当不错,也很容易理解;但是,我不确定弄乱 DateTime- 运算符的功能是否是个好主意。

对于这种情况,我能想到的唯一替代方案是:

<强>1。只需即时创建一个新的 DateTime 对象,在调用 new 时计算新的小时值

new_date = DateTime.new(old_date.year, old_date.year, old_date.month, old_date.year.day, old_date.hour - hours_to_subtract, date.min, date.sec)


<强>2。编写一个接受 DateTime 和要从中减去的小时数 的实用程序方法

基本上,只是方法 (1) 的包装器:

def subtract_hours(date, hours)
  return DateTime.new(date.year, date.month, date.day, date.hour - hours, date.min, date.sec)
end


<强>3。向 DateTime 添加新方法,而不是更改 #-()

的现有行为

也许是一个新的 DateTime#less 方法可以与 Fixnum#hours 补丁一起使用,以允许这样的语法:

date.less(5.hours)

但是,正如我已经提到的,我采用了修补方法,因为我认为它会产生更具表现力的语法。

我的方法有什么问题吗,或者我应该使用 3 种备选方案中的一种(或我没有想到的另一种)来做到这一点?我感觉修补正在成为我解决 Ruby 问题的新“锤子”,所以我想就我是否以“Ruby 方式”做事获得一些反馈。

最佳答案

我的个人答案,简而言之:the core-class patching hammer should be at the bottom of your toolbox .您还可以使用许多其他技术,而且在几乎所有情况下,它们都足够、更干净,而且更多sustainable .

不过,这实际上取决于您编写代码的环境。如果这是个人项目 - 当然,随心所欲地打补丁!当您与一大群程序员长期在大型代码库上工作时,问题就开始出现了。在我工作的组织中,有超过 100KLOC 的 Ruby 代码库和 20 名左右的开发人员,我们已经开始严厉打击猴子补丁,因为我们已经看到它会导致令人头疼、浪费工时的行为太频繁了。在这一点上,我们几乎只能容忍它临时修补尚未合并或不会合并我们的源补丁的第三方代码。

关于ruby - 修补 Ruby 的基类(例如 Fixnum)是否可以接受?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/238878/

相关文章:

ruby-on-rails - 为 ruby​​ gem 的唯一性验证添加范围

django - 将 Django 的默认小部件更改为自定义小部件

ruby-on-rails - 在聚合函数之前对 ActiveRecord 对象执行行操作

ruby - 在 Ruby 中动态生成多维数组

ruby - RubyGems 创建的 gem 批处理文件是错误的还是我遗漏了什么?

javascript - rails 上的 ruby : How to send an AJAX request to rails controller from login popup along with user given credentials

python - 如何猴子修补静态方法?

python - 使用 Pytest 测试 Python 程序

python - 在所有 python 对象上注入(inject)辅助函数?

ruby - 如何在 Ruby 中使用键进行深度转换值?