组织猴子补丁

时间:2017-01-06 01:03:19

标签: ruby oop monkeypatching

我读了一个blog post,建议为你的猴子补丁命名空间,以便轻松查看和包含它们。

例如:

setVisible

将放入:public final BooleanProperty tableHiddenProperty() { return this.tableHidden; } public final boolean isTableHidden() { return this.tableHiddenProperty().get; } public final void setTableHidden(final boolean value) { this.tableHiddenProperty().set(value); } 文件。

它可以包含在具有module CoreExtensions module DateTime module BusinessDays def weekday? !sunday? && !saturday? end end end end 实例方法的DateTime类中(由于lib/core_extensions/class_name/group.rbModule#include而继承了一个类)

Class

我的问题是包含语句在哪里?有会议吗?

例如:

我有以下猴子补丁:

Module

它存在于# Actually monkey-patch DateTime DateTime.include CoreExtensions::DateTime::BusinessDays 文件中。

我应该在哪里发表# 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_extensions/string/cases.rb

String.include CoreExtensions::String::Cases

这是有效的,它的工作原理是有道理的。这是因为我的整个应用程序都位于lib/devify.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

不确定这是不是正确的方法。

2 个答案:

答案 0 :(得分:2)

您拨打include电话的位置无关紧要。

调用String.include将始终修补整个对象空间中所有字符串使用的一个String类。所以最好把指令放在顶层,不要误导读者的代码。

Monkey修补始终是全局的。

这是一个强大的功能,可以很好地使用。

如果您正在创作gem,请注意您与其他人共享全局命名空间。对于顶级模块甚至是宝石名称也是如此。共享命名空间只是共享代码的现实。

如果您正在寻找词法范围的猴子补丁,请查看Ruby 2中引入的新细化功能。

改进是从Smalltalk的类盒中获取的想法。虽然改进并非没有自己的问题,例如他们缺乏内省和反思的支持。因此,基本上使它们隐身,不适合生产使用。

如果您希望仅将猴子补丁限制为某个字符串对象,请考虑在实例上继承String或调用extend

答案 1 :(得分:0)

尽管ruby提供了许多动态更改类或方法内容的方法,但猴子修补可能会导致大问题和奇怪的错误。我读了这篇文章(http://www.virtuouscode.com/2008/02/23/why-monkeypatching-is-destroying-ruby/),了解为什么使用猴子修补是一个坏主意。

总之,他说的许多事情都有意义。当您创建猴子修补时,您假设它只适用于该项目,并且,当更多具有相似目的的库被放在一起时,您可能会创建冲突和不可预见的副作用。

有些情况下,猴子修补的好处很棒,比如ActiveSupport通过使用agofrom_now方法修补Fixnum类来处理日期操作的方式,或者作为方法to_json。但是,应该避免使用猴子补丁。

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

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

猴子修补使一切变得更小,更简单,但是避免它会使你的代码更加可维护,更容易调试,读取和测试,并且更加优雅,因为它符合“OOP”模式。 / p>