【问题标题】:To monkey-patch or not to?猴子补丁还是不猴子?
【发布时间】:2010-09-29 18:27:05
【问题描述】:

这是一个比特定语言更普遍的问题,尽管我在玩 python ncurses 模块时遇到了这个问题。我需要显示语言环境字符并将它们识别为字符,所以我只是快速地从 curses 模块中修补了一些函数/方法。

这就是我所说的快速而丑陋的解决方案,即使它有效。而且变化相对较小,所以我希望我没有搞砸任何事情。我的计划是找到另一个解决方案,但是看到它有效并且运作良好,你知道它是怎么回事,我继续解决我必须处理的其他问题,我确定如果没有错误,我永远不会让它变得更好。

不过,在我看来,更普遍的问题是——显然某些语言允许我们在类中对大块代码进行猴子补丁。如果这是我自己用的代码,或者改动很小,没关系。如果其他开发人员使用我的代码怎么办,他看到我使用了一些众所周知的模块,所以他可以假设它像以前一样工作。然后,这种方法突然表现得与它应该的不同。

那么,非常主观,我们是否应该使用猴子补丁,如果是,何时以及如何使用?我们应该如何记录它?


编辑:为@guerda:

Monkey-patching 是一种在执行时动态更改某些代码的行为的能力,而无需更改代码本身。

Python 中的一个小例子:

import os
def ld(name):
    print("The directory won't be listed here, it's a feature!")

os.listdir = ld

# now what happens if we call os.listdir("/home/")?
os.listdir("/home/")

【问题讨论】:

  • 能否请您简短地为新手解释一下“猴子补丁”?谢谢!
  • +1 这是主观的和有争议的,就像关于 SO 的大多数好问题一样

标签: oop language-agnostic monkeypatching


【解决方案1】:

我会说不要。

每个猴子补丁都应该是一个例外并被标记(例如带有 //HACK 注释),以便它们易于追溯。

众所周知,将丑陋的代码留在原处很容易,因为它可以工作,所以为什么要花更多时间在它上面。所以丑陋的代码会长期存在。

【讨论】:

    【解决方案2】:

    我认为这个问题不能用一个明确的是-否/好-坏答案来解决 - 必须考虑语言及其实现之间的差异。

    在 Python 中,需要考虑是否可以对一个类进行猴子补丁(参见SO question 进行讨论),这与 Python 的稍微少一点的 OO 实现有关。所以我会很谨慎,并倾向于在猴子补丁之前花一些精力寻找替代品。

    在 Ruby 中,OTOH 被构建为 OO 到解释器中,无论类是用 C 还是 Ruby 实现的,都可以修改。甚至 Object(几乎是所有东西的基类)也可以修改。因此,在该社区中,猴子修补作为一种技术被更热情地采用。

    【讨论】:

      【解决方案3】:

      不要!

      尤其是对于免费软件,您可以尽一切可能将您的更改纳入主发行版。但是,如果您的本地副本中存在薄弱记录的黑客攻击,您将永远无法发布该产品,并且升级到下一个版本的 curses(任何人都可以进行安全更新)的成本将非常高。

      请参阅this answer,了解外国代码库的可能性。 linked screencast 真的值得一看。突然间,肮脏的 hack 变成了有价值的贡献。

      如果您出于某种原因确实无法将补丁安装到上游,至少创建一个本地 (git) 存储库来跟踪上游并将您的更改放在单独的分支中。

      最近我遇到了一个问题,我不得不接受猴子修补作为最后的手段:Puppet 是一段“到处运行”的 ruby​​ 代码。由于代理必须在 - 可能经过认证的 - 系统上运行,因此它不需要特定的 ruby​​ 版本。其中一些具有可以通过在运行时中修补选择方法来解决的错误。这些补丁是特定于版本的,包含的,并且目标被冻结。我认为没有其他选择。

      【讨论】:

        【解决方案4】:

        我同意 David 的观点,因为猴子修补生产代码通常不是一个好主意。

        但是,我相信对于支持它的语言,猴子补丁是一个非常有价值的单元测试工具。它允许您隔离需要测试的代码片段,即使它具有复杂的依赖关系 - 例如无法注入依赖关系的系统调用。

        【讨论】:

          猜你喜欢
          • 2011-01-14
          • 2016-09-01
          • 2012-09-16
          • 2012-12-18
          • 2020-01-09
          • 1970-01-01
          • 1970-01-01
          • 2021-04-04
          • 2011-04-15
          相关资源
          最近更新 更多