如何在重构之前和之后比较Rails的'可执行文件'?

时间:2012-09-01 11:57:18

标签: ruby-on-rails ruby jruby rubinius

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

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

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:2)

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

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

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

作为一个简单的例子,假设ruby支持乘法而C不支持。然后,您可以在C代码中包含静态mult函数,并从中翻译:    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结构引用。关键在于您希望在牺牲实际行为的同时保持命名关系的完整性。

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

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

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