2011-03-09 57 views

回答

2

的問題,恕我直言,是

  • 你會忘了變化。
  • 你會複製粘貼從互聯網上的一個片段,這將觸發一個錯誤的行爲改變,你會撓頭,直到你得到無毛的補丁。
  • 另一位開發人員會在你遇到一個錯誤3個月之後,直到他發現它在一個猴子補丁中。他會去人力資源部門,得到你的地址,並告訴你爲什麼不做猴子補丁。

現在,有時你需要猴子補丁一個類(即使在覈心庫,爲什麼不)。我的建議是

  • 把所有的猴子補丁放在一個源文件夾中。
  • 第二件事你在「你好我的名字是......」之後對新開發者說的是該文件夾的位置以及每個猴子補丁的詳細解釋。
+0

嘿,謝謝你的答案!我還有一個相關的問題:這個改變的範圍是什麼?重新定義類的代碼會影響什麼? – RubyDosa 2011-03-09 11:07:12

0

你說的是猴補丁,並根據wikipedia

馬馬虎虎寫

或不好 由於以下原因,是危險的記錄猴子補丁會導致 問題:

  • 他們當修補程序假定 不再是 爲真的修補對象時,可能會導致升級問題;如果您更改了 的產品隨新版本發生了變化,那麼很可能會破壞您的補丁。因爲這個原因, 猴子補丁通常會有條件地生成 ,並且只有在 適用時才適用。
  • 如果兩個模塊嘗試猴子修補同法, 其中一個(哪一個跑最後一棒)「勝」 和其他補丁沒有效果, 除非monkeypatches是書面 圖案像alias_method_chain
  • 它們在磁盤上的原始源代碼和可能是 觀察到的行爲之間產生差異,這對於不知道 補丁存在的任何人而言是非常混亂的。

即使不使用猴子打補丁, 一些人認爲與 可用性功能的問題,因爲使用猴子打補丁的 編程語言 能力是不兼容的 與執行強有力的封裝, 如對象能力 模型所要求的,在對象之間。

有猴 修補紅寶石2未來的一個更安全的方式講叫 refinements

+0

我正在使用JRuby,但它尚不支持Ruby 2.0。 – RubyDosa 2011-03-09 11:16:47

+0

其實ruby 2.0還沒有出來:) – Dty 2011-03-09 11:24:15

+0

哦..:| |我明白了......感謝您的信息!根據維基百科,^^ – RubyDosa 2011-03-09 11:31:20

1

我喜歡其他的答案。儘管如此,我必須補充一點:

有時您可能只想爲某些實例重新定義方法。你可以做到這一點,這使得它在某種程度上更不是改變功能爲某一類的所有對象控制 - 只要適當的調試器用於調試:

class << object_instance 
    def method_redefinition 
    return "method_redefinition" 
    end 
end 
object_instance.method_redefinition => "method redefinition" 

的文件檔案化管理功能集,也可以封裝在一個mix-in,以避免過多的嵌套和混亂的「執行代碼裏面的代碼定義」:

module M 
    def method_redefinition 
    "method_redefinition" 
    end 
end 
object_instance.extend M 
object_instance.method_redefinition => "method_redefinition" 
+0

這是一個整潔的功能。將來可能會有用。謝謝! – RubyDosa 2011-03-09 11:49:45

2

我沒有做太多的Monkeypatching自己,但我聽說,而不是做

class String 
    def improved_method 
    # teh codes 
    end 
end 

這是更好地把新方法爲一個模塊,然後包括模塊

module ImprovedString 
    def improved_method 
    # teh codes 
    end 
end 

class String 
    include ImprovedString 
end 

它可以更容易找到其中一個方法已經定義,而老版本仍然無需做別名存在鏈接。

+0

這真的很酷。我也喜歡「teh codes」哈哈。 – Dty 2011-03-09 23:20:10

0

如果您發現自己遇到了猴子補丁問題,那麼這個小寶石可能會很有用:(https://github.com/gnovos/ctx)。我最初編寫它是爲了創建更具表現力的DSL,允許對基礎對象進行更改,而不會在其他地方造成過多的損害,但它可以用於任何用途。它通過將方法重新定義爲任意上下文來解決一些猴子修補問題,這些上下文可以根據需要進行交換。

如果我想重新定義一些核心類中的方法(例如,在String等中),我使用ctx_define而不是「def」,然後將應該使用新定義的代碼段包裝在ctx中塊,像這樣:

class ::String 
    ctx_define :dsl, :+ do |other| 
    "#{self[0].upcase}#{self[1..-1]}#{other.capitalize}" 
    end 
end 

puts "this" + "is" + "normal" + "text" + "concatination" 
# => thisisnormaltextconcatination 

ctx(:dsl) { puts "this" + "is" + "special" + "text" + "concatination" } 
# => ThisIsSpecialTextConcatination 

我只在幾分鐘內把它扔在一起,所以我不能讓這件事是在任意數量的複雜局勢如何穩健任何保證,但它似乎工作的優良簡單需要。看看你是否感興趣,看看它是否有幫助。 :)