Monkeypatching 有时可能是“最无害的”——大多数情况下,当您需要测试代码时,该代码使用的子系统设计的可测试性不佳(不支持依赖注入 &c)。在这些情况下,您将在您的测试工具中进行猴子补丁(非常暂时,幸运的是),并且几乎总是使用模拟或假货进行猴子补丁以隔离测试(即,使它们成为单元测试,而不是集成测试)。
这种“糟糕但可能更糟糕”的用例似乎不适用于您的示例——它们都可以通过编辑应用程序级代码来调用您的适当包装函数(例如,myos.chown
而不是裸函数os.chown
)并放入您自己的中间模块(例如myown
)中的包装器函数位于应用程序级代码和标准库(或您因此包装的第三方扩展——在这方面标准库没有什么特别之处)之间。
当“应用程序级代码”并非真正在您的控制之下时,可能会出现一种问题情况——它是您不想修改的第三方子系统。尽管如此,我发现在这种情况下,修改第三方子系统以调用包装器(而不是直接调用标准库函数)从长远来看效率更高——当然,您将更改提交给第三方的维护者有问题的子系统,他们将您的更改滚动到其子系统的下一个版本中,每个人的生活都会变得更好(包括您在内,因为一旦您的更改被接受,他们将定期得到维护和其他人的测试!-)。
(作为旁注,这样的包装器也可能值得作为差异提交给标准库,但这是不同的情况,因为标准库的发展非常缓慢和谨慎,特别是在 Python 2 行将永远不会再发展,因为 2.7 是该行的最后一行,并且已被冻结)。
当然,所有这些都以开源文化为前提。如果出于某些神秘的原因,您正在使用封闭源代码的第三方子系统,因此您无法维护,那么您处于另一种情况,猴子修补可能是较小的邪恶(但这只是因为失去战略控制的邪恶通过信任您无法维护的代码来进行开发本身就是一个更大的邪恶;-)。我从来没有发现自己在这种情况下使用了一个既封闭源代码又本身用 Python 编写的第三方包(如果后一种情况不支持你的猴子补丁对你没有好处;-)。
请注意,这里“闭源”的工作定义非常严格:例如,即使是微软 12 多年前也分发了库的源代码,例如带有 Visual C++ 的 MFC(当时他们的产品被称为)——闭源是因为您无法重新分发他们的资源,但是,您手头确实有资源,所以当您遇到一些可怕的限制或错误时,您可以修复它(并将更改提交给他们以供将来发布,以及将您的更改发布为一个差异,只要它绝对不包含他们受版权保护的代码——不是微不足道的,而是可行的)。
Monkeypatching 远远超出了这种方法是“最不邪恶”的严格限制,这是动态语言用户经常犯的错误——小心不要自己落入这个陷阱!