Java反思和重构的痛苦

Java Reflection提供了一种在运行时对Object进行内省的机制。 没有第二个想法,这是一个很棒的function,但它打破了所有重构惯例!

即使在现代IDE中也没有简单的方法( File Search除外)知道引用了哪个属性以及在哪里。 这使得Refactorings变得更加复杂(令人厌烦!)并且容易出错。

坦率地说,它不仅仅是Reflection API ; Hibernate mapping files (hbm.xml)JSP files都将属性称为String,当您重构属性名称时,您必须手动更改所有这些位置。

更糟糕的是,Hibernate映射文件或JSP文件中的更改会导致运行时错误。

我很想知道其他程序员如何在Java中处理这个问题。 有一些工具吗? 我使用Eclipse / IBM RAD作为主要开发平台。 通常我们使用constant来定义属性并尽可能地使用它,但它并不总是可行的。

我也有兴趣其他语言如何处理这个!

Javareflection会导致许多与动态类型语言(如Python和Ruby)相同的问题。 实际上,考虑动态类型语言的一种方法是使用reflection调用所有内容,语言只为reflection提供了一个漂亮,干净的语法。

是的,对于动态类型语言(或reflection的大量使用),重构很难。 您没有获得良好的Eclipse重构function。 相反,grep成为你的朋友。

根据我的经验,你能做的最好的事情就是建立一个良好的unit testing安全网。 这样,如果你在重构期间破坏了一些动态代码,至少在运行测试时你会很快发现它。

如果你正在做很多静态类型的代码,那么如果没有良好的unit testing基础,你会遇到大麻烦。 如果你正在做很多动态类型的代码(包括带有大量reflection的代码),没有良好的unit testing基础,你就没有希望成功。

现代IDE具有以下function:在重命名类时,它们将在例如xml文件中搜索完全限定名称,以尝试重命名您可能具有的任何引用。 不要认为它解决了问题 – 通常你不会绝对引用类名。

此外,这就是为什么在您自己的代码中使用它之前必须特别注意和考虑的原因。

但这种反思问题是为什么使用注释变得越来越流行。 使用注释时问题会减少。

但是让我说,正如之前的post正确地指出的那样,如果你没有良好的unit testing安全网,那么任何一种重构,无论你是否使用大量reflection,都是危险的。

我们实际上已经开发了一个Eclipse插件,可以在很大程度上解决这个问题。 它被称为RefaFlex: http ://www.feu.de/ps/prjs/rf/

通过在语言中引入更多“文字”可以改进重构。 例如,imho .class文字是确保某些模型的编译时安全性的好方法。 然而,重要的是在这里说,有时, 我想失去编译时的安全性 。 字符串是表达两层之间松散耦合契约的最简单但最强大的方法,因为您可以根据正则表达式对它们进行操作或匹配,等等

反思的真正问题是API的冗长使用。 这是灵活性的主要成本。

PS

项目硬币可以在未来某处引入一些新的语言构造来增强这一领域。

您可能对使用IntelliJ IDEA感兴趣,它还将在注释和字符串常量中搜索重构的类名。

好吧,这是IDE制造出售昂贵的高级版本的另一个机会,这些版本将识别和重构特定配置文件中使用的类名。

或者,这样的重复出现的情况可以由对这些文件执行完整性检查的测试套件来处理,即检查所有被引用的类和方法是否存在。 这些特定于一种文件格式,但通常相对容易编写,然后可用于检查该格式的所有文件。

但是对于直接的,“手动”使用reflectionAPI没有通用的解决方案 – 这就是为什么它通常不鼓励的原因。

另外,如果您想通过混淆保护代码,Reflection也会导致问题。 典型的混淆工具现在要求您维护所有不需要混淆的文件的列表,以便所有XML配置文件的reflection都能正常工作。

也就是说,Eclipse IDE的J2EE版本以及Hibernate,Spring等主要框架的合适插件将在处理重构方面做得相当不错。 unit testing将缩短测试周期,但关注的是有时unit testing还依赖于某些XML配置,迫使您使用reflection。 因此,可以在重构时将unit testing与代码分开。

那么你知道的taggin类,方法,字段是通过reflection访问的吗? 当您更改名称时,IDE可能会发出警告。

当您在编译时知道要查找的内容时,可以避免使用dp4j.com编写reflectionAPI。

关于xml映射,它们很痛苦,我也熟悉NetBeans平台,而JPA2则不那么熟悉。 好消息是注释正在接管,这再次提供了编译时检查。 我不确定Hibernate,但JPA和NetBeans( 更多的是7 )提供了xml映射的注释等价物。

我还开发了SqlWrapper以避免在JDBC中使用字符串。 更复杂(和复杂)是JPA2的标准API。