iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 6
0
Modern Web

關於 Ruby on Rails,我想說的是系列 第 6

[Day 6] 猴子補丁 Monkey Patch

  • 分享至 

  • xImage
  •  

猴子補丁 (Monkey Patch)

Monkey Patch 是 Ruby 作為動態語言的一大特色,可以在程式運行時動態修改或擴充程式碼。今年Ruby TW conference 也多次提到這個技巧,當時我想不透Monkey(猴子!?) 跟Ruby的關係,後來才發現是我早已用到的open class技巧 。

讓我拿最愛的射雕三部曲說明:
首先用@novels來列舉這三部小說,主要角色輸出的是男角

class Novel
  @novels = 
    [{title: '射雕英雄傳', male: '郭靖', female: '黃蓉'},
     {title: '神鵰俠侶', male: '楊過', female: '程英'},
     {title: '倚天屠龍記', male: '張無忌', female: '趙敏'}]
     
  def self.main_role
   @novels.map{ |novel| novel[:male]}
  end
end

Novel.main_role #=> ["郭靖", "楊過", "張無忌"] 
Novel.methods.size #=> 189 

如果老闆緊急說要改輸出女角,可以在console下這段程式:

class Novel
  def self.main_role
   @novels.map{ |novel| novel[:female]}
  end
end

Novel.main_role #=> ["黃蓉", "程英", "趙敏"] 
Novel.methods.size #=> 189 

主要角色換成女角了,而Novel類別方法總數沒變,依然是189個

老闆又說要新增輸出書名方法book_title
老闆怎麼又改需求凸W凸

class Novel
  def self.book_title
   @novels.map{ |novel| novel[:title]}
  end
end
 
Novel.book_title   #=> ["射雕英雄傳", "神鵰俠侶", "倚天屠龍記"] 
Novel.methods.size #=> 190 

我們可以得到 Ruby 的 Monkey Patch 的特性:
1.不是把原本的程式碼都蓋掉 (像@novels後兩段程式碼沒給,但還是拿得到)
2.相同名字的方法會被替換掉
3.方法名稱不同,就新增一個新方法 (方法數從189變成190)

ps. Monkey Patch 就像把class打開,做完增刪改再蓋起來,又稱為 open class


什麼時候會用到 Monkey Patch

比方說NewNovel類別繼承自上面的Novel類別,但是book_title方法我想要修改,就可以使用Monkey Patch:

class NewNovel < Novel
  @new_novel = [{title: '翻雲覆雨'}, {title: '王道劍'}]
  
  def self.book_title
   @new_novel.map{ |novel| "書名是#{novel[:title]}"}
  end
end

NewNovel.book_title #=> ["書名是翻雲覆雨", "書名是王道劍"] 

也看過其他人分享,想要修改Gem的內容,但又不想直接更動Gem的檔案,找到Gem原始碼的Class或Module跟想修改的方法,再用Monkey Patch去修改。

注意事項

雖然 MetaProgramming 的技巧很好用,但是會增加debug的困難度,因為你不知道出問題的程式碼到底在哪一段?是原本的程式碼還是動態修補的程式碼? 如果可以還是少用。另外也建議,Monkey Patch 不要散落在專案的各個地方,應該集中放在一個資料夾下面,ex. app/extension,這樣debug 才會容易些。

豆知識:

猴子補丁這詞是怎麼來的?

游擊補強(Guerrilla patch)是指執行時期動態改變程式碼,因為英文上同音於猩猩修補(Gorilla patch),後來改稱猴子補丁(Monkey patch)聽來比較不嚇人一些。


ps.為什麼神鵰俠侶女角不選小龍女?

因為我更喜歡程英(๑•̀ㅂ•́)و✧


上一篇
[Day 5] 類別(class)與模組(module)
下一篇
[Day 7] Enumable 迭代方法
系列文
關於 Ruby on Rails,我想說的是23
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言