Smalltalk如何处理monkeypatching?

时间:2009-05-18 21:21:46

标签: ruby smalltalk monkeypatching

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

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

情景A:错误修复冲突

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

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

情景B:过时的错误修复

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

如果加载项目A,是否仍会应用补丁,可能会发生破损?我很想知道是否存在某种机制,例如,如果代码是固定的,则不加载补丁。

情景C:有冲突的扩展程序

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

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

关于问题更新

阅读答案,我发现我的问题过于宽泛和模糊。所以这是它的重写版本。

5 个答案:

答案 0 :(得分:6)

在Smalltalk中,我们传统上称之为压倒一切。根据您使用Smalltalk的版本控制工具,您可以;

  • 创建最初拥有相关类/方法的软件包的新版本
  • 创建一个新的包,它将拥有所讨论的类/方法的覆盖

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

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

在客户端应用程序中,当您从Venor(或Squeak团队等人)更新到Smalltalk的新版本时,覆盖确实只会影响您。对于服务器应用程序,服务器中可能存在多个应用程序,您需要更加谨慎地处理您的决定。

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

答案 1 :(得分:1)

它说“是的!去吧!”

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

转到类浏览器中的根类,然后可以将所有方法添加到您喜欢的图像中。

请记住,Smalltalk的世界图像与其他常用语言完全不同(像Smalltalk这样的唯一其他普通版本是APL。)你有一个包含整个集合的图像代码和运行时包。更改图像时,图像中的每一位代码都会受到影响。其他图像不会更改。您可以使用更改集来重新加载您喜欢的黑客,但它们基本上是将代码导入图像。

答案 2 :(得分:1)

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

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

答案 3 :(得分:1)

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

请参阅http://scg.unibe.ch/research/changeboxes

答案 4 :(得分:0)

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

情景A和B

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

根据上游合并修复程序和发布新版本的速度的意愿,您可能会设想生成monkeypatch。在这种情况下,最好的办法是:

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:TODO