我一直在印象中,monkeypatching属于快速和肮脏的hack类别,而不是标准的良好编程习惯。虽然我不时使用修复第三方库的小问题,但我认为这是临时性的修复,因此我会向第三方项目提交适当的补丁程序。
但是,我已经将该技术用作主流项目中的“常规方法”,例如在Gevent的gevent.monkey
模块中。
Monkeypatching是否已成为主流,正常且可接受的编程实践?
我一直在印象中,monkeypatching属于快速和肮脏的hack类别,而不是标准的良好编程习惯。虽然我不时使用修复第三方库的小问题,但我认为这是临时性的修复,因此我会向第三方项目提交适当的补丁程序。
但是,我已经将该技术用作主流项目中的“常规方法”,例如在Gevent的gevent.monkey
模块中。
Monkeypatching是否已成为主流,正常且可接受的编程实践?
Answers:
不,但是有时候monkeypatch的危害较小(比破坏代码:))。我对红宝石中的猴子补丁的一般规则是:
有一个非常好的猴子补丁原因(临时的关键修补程序是一个很好的原因。除非您使用ActiveSupport,否则to_s方法的格式不是很好)
使它们尽可能透明:将它们放在代码库中的特定位置并分离文件,编写描述Monkeypatch原因的文档(这里是一个示例)。
易于删除-文档应包含有关删除以及注意事项的信息。许多猴子补丁是临时的,因此应该易于删除。
是的,monkeypatching非常有用!
不知何故,名字似乎对人们的看法影响很大。称其为“ monkeypatch”,听起来很糟糕,称其为“热修复”或“即时修复”,听起来不错。
独立于此,我认为在运行时更改方法/属性/功能的功能是非常有用的。即使是javascript人,也可能整天都在不知不觉中使用它。
例如:
button.onclick = function(e) { ...}
这条简单的线说明了您更改按钮行为的事实。它是按这种方式设计的。同样,您可以更改所有其他功能,但是这样做很愚蠢。
现在,关于以这种方式交付补丁的问题……嗯……为什么不呢?您只需要下载一个小补丁而不是一个大版本。哎呀,您甚至可以在不停止服务器的情况下修补服务器,太好了!然后,有一天,您还可以获取最新版本以进行更大的更新。很公平。所以,是的,我投票赞成“运行时修补程序”是一件好事。
有趣的是,有些语言(例如Erlang)甚至是围绕这个概念而建立的。动态更新服务器的能力。
当然,最后,与其他所有内容一样,这取决于您如何使用它。您可以制作出色的OO东西和糟糕的东西,都是一样的。
编辑:
无论您是要修补自己的库还是第三方库,让我添加一些区分大小写的功能。
...基本上,您对此类补丁所做的工作是修复您自己或第三方库的错误。无论哪种情况,它都很有用。就您自己而言,它使您能够即时提供修复程序。对于第三方,要么等待(几个月?),直到他们自己修复它,要么现在就自己完成。(您仍然可以向他们提交补丁,以便他们将其修复在自己的身边)。当他们发布修复了问题的下一个lib版本时,如果您要更新库并删除补丁,则仍然可以。
当然,现在,如果您使用补丁程序来更改lib的行为并使其脱离工作目的/方式,那么显然这就是灾难的根源。我希望,即使是猴子也能看到。;)
一般而言,修补是最后的选择,猴子修补更是如此。问题主要是可维护性之一。
很久以前,我的linux内核已应用了3个单独的补丁,这对于我的视频卡驱动程序和我拥有的两个专有应用程序是必需的。他们中的两个有冲突的更改,这意味着我需要第4个补丁来解决它们之间的差异。现在,每当上游内核中解决安全问题时,我要么必须等待这3个补丁的供应商发布对新内核版本的更新,这需要一个到六个月的时间,要么我必须手动维护上游安全补丁,直到其他补丁厂商赶上来。
几年后,供应商设法将其包含在上游内核源代码中,我能够停止这种平衡,但是您可以看到它在此期间是一团糟。除非必须这样做,否则不要对您的程序员造成影响。
否。这不是软件开发的标准技术。它仍然是解决严重问题的解决方法,并且具有明显的缺点。我想到违反《里斯科夫换人原则》。猴子补丁使人们很难对程序进行推理。对于您自己的程序,应将代码放在其所属位置。对于第三方库,您将始终处于危险之中,即您的补丁程序无法与该库的下一版本一起使用。
当然,如果您知道自己在做什么并且没有时间实施SOLID解决方案,则猴子修补非常有用。但是你永远都不要视为标准技术,并在猴子补丁上构建猴子补丁。
顺便说一句,您是否曾经为猴子补丁编写过单元测试?