2

在 C 中,我可以生成一个可执行文件,进行广泛的仅重命名重构,然后再次比较可执行文件以确认可执行文件没有更改。这对于确保重构不会破坏任何东西非常方便。

有没有人用 Ruby 做过类似的事情,尤其是 Rails 应用程序?策略和方法将不胜感激。理想情况下,我可以运行一个脚本来输出某种纯字节码且不会因命名更改而更改的单个文件。我猜 JRuby 或 Rubinus 在这里会有所帮助。

4

2 回答 2

2

我认为这种策略不适用于 Ruby。与编译器丢弃名称的 C 不同,您在 Ruby 中命名的大多数东西都带有该名称。这包括类、模块、常量和实例变量。

自动化单元和集成测试是支持 Ruby 重构的方法。

于 2012-09-01T12:35:07.443 回答
2

有趣的问题——我喜欢你可以从这个回归策略中得到明确的“是”答案,至少对于重命名重构的具体情况。

我不够专业,无法判断您是否可以编译 ruby​​(或者至少是一个子集,没有类似的东西eval),但似乎有一些提示:

假设不可能进行完整的编译,那么抽象解释方法呢?您可以将 ruby​​ 解析为 AST,从 AST 发出某种 C 代码,然后编译 C 代码。C 代码不需要完全捕获 ruby​​ 代码的行为。只要红宝石是不同的,它就只需要是可编译的并且是不同的。(实际上运行它可能会导致乱码,或者可能是立即的内存违规错误。)

举个简单的例子,假设 ruby​​ 支持乘法,而 C 不支持。mult然后,您可以在 C 代码中 包含一个静态函数并从:a = b + c*d 到 转换a = b + mult(c,d) ,生成的编译代码在名称重构下将保持不变,但在其他类型的更改下会显示出差异。该mult函数实际上不需要实现乘法,您可以使用其中之一:

static int mult( int a, int b ) { return a + b; } // pretty close
static int mult( int a, int b ) { return *0; } // not close at all, but still sufficient

只要 C 编译器不会内联定义,您仍然可以获得所需的不变性。同样的翻译,从一个不可编译的 ruby​​ 结构到一个功能较少但独特的 C 结构,应该适用于对象操作等等,将类操作映射到 C 结构引用。关键在于您希望在牺牲实际行为的同时保持命名关系完整。

(我想知道您是否可以使用具有以 ruby​​ 代码中的所有类和属性名称命名的成员(指向同一结构类型的所有指针)的单个 C 结构做一些事情。然后,类和对象操作将对应于嵌套的取消引用操作,使用这个单一的结构。只是一个概念。)

即使您无法制定精确的映射,遗漏一些细微差别的不精确映射可能仍然足以增加对原始名称重构的信心。

实现这种方案的最快方法可能是从字节码映射到 C(而不是从 ruby​​ AST 到 C)。这将节省大量解析,但映射将更难理解和验证。

于 2012-09-23T03:32:41.390 回答