将中型代码库从Java 1.4.2迁移到Java 5的策略

时间:2009-04-07 12:01:49

标签: java refactoring migration

我正在审核代码库(~20K LOC)并尝试确定如何将其从1.4.2迁移到5.显然,这不是一夜之间的项目,我收到的建议是编写针对Java 5的新代码,并以零散的方式迁移旧代码。此外,我不是Java 5新功能的专家(即我知道它们,但从未编写任何用于生产用途)。

我的问题:

  1. Java 5的哪些功能通常用于生产代码? (即泛型,自动拳击等)是否有特征要避免/不被认为是最佳做法?

  2. 我可以使用哪种最佳重构策略迁移此大小的代码库? (即,只有在编辑类时才对类一次进行更改等)目标 - 降低代码库的风险。限制 - 进行重构的资源。

  3. 感谢任何建议 - 提前感谢。

    更新 - 一年太晚了,但迟到总比没有好? =)

    感谢所有评论 - 很多很棒的观点。在软件开发人员的生活中,总会有你努力完成的项目,但由于某些更“紧急”的事情,我们永远不会到处走。

    关于Java 5的使用(当时),它是客户端生产环境中所需要的,因此我们不使用Java 6。

    我发现集合,枚举和基元拆箱的强类型是我倾向于应用最多的功能,包括旧代码和新代码。重构非常简单,但代码理解得到了显着改善,标准变得更容易实施。我最麻烦的是仿制药;我认为这是一个我仍然没有机会完全掌握和欣赏的概念,因此我很难找到以前适用仿制药的案例。

    再次感谢所有为此话题做出贡献的人,并为后期跟进道歉。

6 个答案:

答案 0 :(得分:6)

Java 5几乎完全向后兼容Java 4.通常,迁移时必须进行的唯一更改是重命名Java 4中新enum关键字的任何用法代码。

此处列出了潜在兼容性问题的完整列表:

http://java.sun.com/j2se/1.5.0/compatibility.html

我在实践中遇到的唯一另一个问题与JAXP实现的变化有关。在我们的例子中,它只是意味着从类路径中删除xerces.jar。

就重构而言,我认为迁移您的集合类以使用新的强类型泛型版本并删除不必要的转换是个好主意。但正如另一张海报指出的那样,如果你在垂直切片中工作,改用通用集合往往效果最好。否则,您最终必须向代码添加强制转换,以使泛型类型与非泛型类型兼容。

我在迁移代码时喜欢使用的另一个功能是@Override注释。当你重构代码时,它有助于捕获继承问题。

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Override.html

如果您的代码使用线程,那么新的并发库非常有用。例如,您可以使用ThreadPoolExecutor替换自己开发的线程池。

http://java.sun.com/j2se/1.5.0/docs/relnotes/features.html#concurrency

我肯定会采取在正常维护期间更改代码时更新代码的方法。除了兼容性问题之外,我认为使用新的Java 5功能没有令人信服的理由,除非您因其他原因已经更改了代码。

答案 1 :(得分:2)

仿制药的“病毒”性质存在一个非常现实的问题;一旦你开始在架构中的给定层引入它们,你通常希望在上面的层中引入它们。下面也是。我发现引入泛型可能最好在完全“垂直”中完成。但您不必一次全部垂直。

答案 2 :(得分:2)

这是一个非常难以回答的问题,因为它取决于将受到影响的代码以及代码的重要程度。

首先,当迁移是一项非常重要的工作时,请帮自己一个忙,并升级到最新版本的Java,这将是Java 6而不是Java 5. Java 6已经推出了一年半或更长时间已经成熟了。没有理由不在Java 5(imho)上选择它。

其次,与任何软件项目一样,您的目标应该是尽快将某些内容投入生产。因此,您需要确定系统的一部分。越小越好,非脉冲越多越好。

另一件事就是尝试在Java 6下启动你的应用程序,看看有什么中断。它可能比你预期的更糟糕。它可能会好得多。

您可能需要注意的另一件事是,通过它的声音,您的应用程序中的jar /库将被弃用。有些甚至可能与1.4.2之外的Java不兼容。您可能希望将所有这些升级到最新版本。

这可能意味着更多的东西会破坏,但使​​用旧的/弃用的API只是在街上踢罐头并导致其他问题。

除此之外,升级可能会产生深远的影响。想到了Axis1到Axis2。这些情况需要更仔细的考虑。

至于使用了什么功能......所有功能都非常多。我无法想到任何应该避免的问题。

另外,我刚注意到你项目的大小:~20K LOC。这实际上很小(例如我自己在过去的3个月里写过一个关于那个尺寸的应用程序)。

最后,这还取决于你会发现破坏的容易程度。如果你有良好的单元测试覆盖率那么好。这是非常罕见的。如果您可以通过应用程序运行并可靠地发现问题,那就不错了。

有问题的情况是情况很难测试,很可能你不会立即发现问题。这需要更加谨慎。

答案 3 :(得分:1)

您可能希望迁移在1.4到5的转换中不起作用的东西(不确定那会是什么),但我要警惕迁移缘故的东西它

如果你采取这种方式,有些问题:

你有全面的测试报道吗?如果没有,您应该为要迁移的代码编写单元测试。

您是否拥有在代码库中广泛使用的组件?如果是这样,它们可能是根据其API进行迁移的候选者(例如使用泛型等)

就Java 5中广泛使用的内容而言。泛型非常重要,让您的生活更轻松。我没有看到autoboxing 太多,也没有枚举(这都是相对的)。 Varargs几乎没有。注释对框架很有用,但我会使用它们。我不认为自己曾经实施过。

答案 4 :(得分:1)

20(非评论)kloc应该小到足以插入带有大爆炸的泛型。显然,请确保您的代码首先在Java SE 5上编译运行。关于泛型的相对容易的事情是,添加它们对语义的改变非常小(某些重载可能因隐式情况而改变 - Iterator<char[]> iter; ... System.out.println(iter.next());作为我头脑中的一个坏例子。)

添加泛型的某些情况会突出显示代码的概念问题。例如,使用一个Map作为具有不相交键集的两个映射。 TreeMap是Java库中的一个示例,其中单个类具有两种不同的模式(使用Comparator<T>Comparable<T>)。

增强型和自动式拳击等内容非常局部,可以零碎添加。枚举很少见,可能需要考虑一下你将如何使用它们。

答案 5 :(得分:1)

我认为你这是错误的做法。您的计划不应该是将所有当前代码更新为Java 1.5,您的计划应该是确保所有当前代码在1.5中的运行方式与1.4.2中完全相同,并且所有未来编写的代码都可以在1.5中正常运行

我经历了一些像各种大小的代码库这样的过渡。我们的目标始终是确保我们有大量的单元测试,以便我们可以轻松插入1.5并通过它运行我们的测试。我们实际上遇到了大约10个问题,主要与正则表达式库有关,它们不支持某些东西或支持不同的东西。

然后在1.5中编写所有新代码,如果因任何原因更改旧类,花一分钟时间实现泛型,但没有理由重构所有内容。如果您没有进行测试,那对我来说听起来有点危险。