Monkey Patching

對於常寫直譯式語言的人來說,這個名詞可能不陌生。Monkey Patching 簡單來說,就是允許程式在動態執行時,才改變原有的行為。這裡的行為除了可以是類別裡的變數之外,連類別裡的函式也可以修改。例如以下的範例 (Python)

>>> import math
>>> math.pi
3.141592653589793
>>> math.pi = 3
>>> math.pi
3

上面這個是 wiki 上面所寫的例子。可以看到對於已被匯入的 math 庫,任意修改了裡面的 pi 這個值並且隨意使用。這裡再示範一個網路上常提到的例子。

class Foo:
def go(self, number):
print('Your number is ' + str(number))
def go():
print('Your number is 1234')
foo = Foo()
foo.go = go
foo.go()
>>> Your number is 1234

上面是另一個足以代表 monkey patching 威力的例子。從此例中可以發現,即使是已經實體化了 foo 物件,也依然可以置換裡面的 go 函式,達成真正的 動態修改 的目標。


雖然 monkey patching 看起來似乎將動態執行變得非常彈性,但是對於這樣樣的使用方式,仍然有正反兩方不同的看法。我在看完這篇文章之後,也是非常贊同作者的理念。深深覺得還是盡可能的不要使用這樣的物件操作,因為極有可能造成開發上的困難還有潛在的地雷問題。


缺點示例

當你拿到了某人修改過的 String 類別物件,你能夠確保它對於字串的處理仍然跟以前一樣嗎?
當此類別物件需要初始化的時候,你確定你可以正確的給它參數然後保證它不會發生執行時期的例外錯誤?
當你的程式無法正常運作時,有沒有可能是這些對於 monkey patching 的操作行為導致程式在執行上的非預期錯誤? 而此舉會不會造成你在解決問題時需要花費更多的時間?

優點示例

當今天客戶有急迫需求且程式過大無法從架構下手的錯誤,若能利用 monkey patching 解決,是否可以省下更多的時間?
當今天有客製化需求,而現今已存在一個接近你功能的套件,是否可以利用此物件操作方法來快速修改此套件以達到你的目的?
對於程式有單元測試需求,然而需要測試資料時,是否可以利用此方法針對每個部份快速給予初始值,以區分每一個測試環節的相關性?


上面是我在研究完 monkey patching 後自己的心得,但是若我真的拿到這樣的程式,我想我應該還是會非常生氣,除非程式文件做得非常的好,不然光瞭解程式的來龍去脈可能就要花費超多時間了,還不包括可能會踩到的雷。

Like what you read? Give Jemmy Lin a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.