7

我是一名 Ruby 程序员。对我来说,monkeypatching 是在运行时更改外部项目中的类或模块方法。我感兴趣的是,您有什么机制可以保护您免受某些对该功能的滥用。接下来是我遇到的一些场景,monkeypatching 咬了我一口。

虽然我根本不了解 Smalltalk,但这种语言早在 Ruby 之前就已经存在了。我做了一些研究,看看 Smalltalk 是否以及如何解决其中的一些问题,但在 Google 上没有找到太多。所以我在这里,询问 Smalltalkers 是否可以分享他们的智慧。

场景 A:错误修复冲突

项目 A 和 B 依赖于项目 C。项目 C 有一个错误。项目 A 和 B 版本包含对项目 C 的修复。

如果你的代码使用项目 A 和 B,你怎么知道补丁不会冲突?

场景 B:过时的错误修复

项目 C 发布了他们项目的固定次要版本。

如果您加载项目 A,是否仍会应用补丁,但可能会损坏?我很想知道是否存在某种机制,例如,如果代码已修复,则不加载补丁。

场景 C:冲突的扩展

项目 A 和 B 使用项目 C 的类 Foo。两者都向 Foo 添加了一个实用方法,例如 #toDate。A 的 toDate 版本返回一个日期字符串,而 B 的一个返回 Date 对象。

如果您加载两个项目(使用 C dep),是否有一种机制可以警告/防止冲突?或者您是否必须等到运行时由于方法中的错误期望而引发错误?

关于问题更新

阅读答案,我意识到我的问题过于广泛和模糊。所以这里是它的重写版本。

4

5 回答 5

7

在 Smalltalk 中,我们传统上称之为覆盖。根据您在 Smalltalk 中使用的版本控制工具,您可以:

  • 创建最初拥有相关类/方法的包的新版本
  • 创建一个新包,该包将拥有相关类/方法的覆盖

在 VisualWorks 和 ObjectStudio(我最熟悉的 Smalltalk)中,使用的是后一种方法。在使用 Envy 的 VA Smalltalk 中,采用了前一种方法。我相信 Squeak 会使用 Monticello 遵循后一种方法,但我并不完全确定。

在大多数 Smalltalk 实现中,很容易看到被覆盖代码的原始版本和当前安装的覆盖。

在客户端应用程序中,只有当您从供应商(或 Squeak 团队等)更新到新版本的 Smalltalk 时,覆盖才会真正影响您。对于服务器应用程序,多个应用程序可能驻留在服务器中,您需要更加谨慎地决定要做什么。

覆盖(或称为猴子补丁)是一个强大的工具,但您需要注意如何使用它们 - 如果您确实使用它们,您应该重新检查您是否仍然需要定期使用它们。在我的开源新闻聚合器BottomFeeder中,我删除了很多我最初设置的覆盖。

于 2009-05-18T22:00:33.810 回答
1

它说“是的!去吧!”

整个概念很可能首先出现在 Smalltalk 中。

在类浏览器中进入根类,你可以将所有方法添加到你喜欢的图像中。

不过,请记住,Smalltalk 与其他常用语言的世界图景截然不同(Smalltalk 等唯一常见的语言是 APL。)您有一个包含整套代码和运行时包的图像。当您更改图像时,图像中的每一位代码都会受到影响。其他图像不变。您可以使用更改集来重新加载您最喜欢的 hack,但它们基本上是将代码导入图像中。

于 2009-05-18T21:37:36.413 回答
1

Smalltalkers 不使用术语“猴子补丁”,但我觉得“方法覆盖”是最接近的术语。也就是说,用包B中同一个类的方法覆盖了包A中一个类的方法。因此,当您加载包B时,将覆盖A中的原始方法。

方法覆盖有其优点,但如果不小心使用,则缺点更多,因此通常我们倾向于避免使用它们。它还取决于 Smalltalk 方言 - 例如,在 VisualWorks 中,工具支持很好的覆盖,而在 Squeak 中则不然。

于 2009-05-18T21:37:52.827 回答
1

如果您正在寻找最先进的解决方案,请查看 Changeboxes。Changeboxes 的研究原型基于 Squeak Smalltalk。

http://scg.unibe.ch/research/changeboxes

于 2009-06-16T08:30:21.687 回答
0

回答我自己,这是我目前的观点:

场景 A 和 B

由于所有代码都是开放的,最好的做法是直接修复损坏的项目。像 git 这样的工具已经管理代码合并,所以我们不需要依赖运行时合并,这并不总是有效的。

根据上游合并您的修复程序的意愿和发布新版本的速度,您可能会设想生成一个猴子补丁。在这种情况下,最好的办法是有一个机制说:

monkeypatch(ClassName, :method, &newcode) of the broken project
is applied if project.version in [a set of releases where the bug exist]
if the project version is unknown to the monkeypatch,
  raise an error to tell the developer to fix the monkeypatch (check if bug exist).
if a monkeypatch for that project, classname and method already exist, yell

这是我的想法。如果错误修复需要的不仅仅是方法更改,则可能会出现问题。

场景 C:待办事项

于 2009-05-21T13:29:30.757 回答