清理大型遗留Java项目

时间:2010-10-19 17:57:58

标签: java refactoring formatting legacy code-structure

我被指派在一个巨大的Java项目上做一些工作,并且几个迭代开发人员的影响是显而易见的。没有标准的编码风格,格式,命名约定或类结构。这是我和Javadoc一起上课的好日子,单元测试是一个快乐的白日梦。

到目前为止,我们这个项目的所有人都在“融入”,适应我们正在进行的任何课程的现有惯例,但现在是时候强加一些秩序和一致性。

这是一项艰巨的挑战,我正在寻找人们对此类任务可能提出的任何建议。是否有任何特别有效的策略,或者需要注意的陷阱?试试是不是一个好主意?

编辑添加:我不想给人一种项目不好的印象 - 它实际上是设计稳固且写得很好。它只是感受它的年龄和维护的必然性......

9 个答案:

答案 0 :(得分:11)

我发现Eclipse是一个非常强大的工具,可用于此类操作。

许多人发誓使用命令行工具和基于模式的文本编辑器进行编程,但使用完整的IDE进行重大重构有很大的优势:

  • 自动实时编译会在发生错误时及其发生的任何地方显示错误。仅仅因为你做了一个改变而且课堂上没有任何内容或者立即打包,并不意味着你没有在其他地方创造过问题。红旗将在eclipse中的包树上,直接引导你。
  • 基于图形的重命名和移动。重命名代码元素可能会产生比您所知的更大的影响。 Eclipse将向您显示相关元素的每个实例的详细信息以及重命名将如何更改它。
  • 自动导入管理可让您完成处理工作,确保所有导入都有序。 Eclipse将在使用时自动添加导入,并使用动作灯泡标记未使用的导入,以便一键删除。
  • 使用代码样式确保所有源文件对所有内容使用相同的格式。空格,缩进,换行,括号都可以为您格式化。这可以在您创建新代码以及更新现有文件时起作用。

除了Eclipse的工具集之外,您可能会考虑使用其他现代Java工具来确保代码始终正常运行。

  • 测试套件允许您不断确保所做的任何更改不会对项目功能产生负面影响。如果要重构某个功能,请编写两到三个测试用例来演示其工作方式。确保它们在任何更改之前和之后运行。这是在问题成为问题之前发现问题的最简单方法。
  • 使用Maven等工具来协助依赖,测试,编译和部署。不要浪费时间再做上述任何一项任务。专注于编写完成工作的代码。

编辑:

我个人更喜欢Eclipse,因为我是进行重构的人,而不是一些对我的代码几乎一无所知的自动化工具。

答案 1 :(得分:6)

您可以使用tool在项目的源代码中强制使用通用格式。除此之外,请参阅Michael Feathers的有效使用遗留代码(其中“遗留代码”被定义为“没有单元测试的代码”),其中描述了如何逐步将遗留代码转换为经过全面测试的代码和 - 稳定的代码。

答案 2 :(得分:3)

在这种情况下我喜欢做的是:

  1. 首先将项目转换为使用maven构建,以便我知道依赖项的版本。
  2. 这也为我提供了一些不错的代码质量报告作为基准,包括checkstyle,findbugs,pmd和代码覆盖率。
  3. 而我(以及其他许多人)习惯于这种结构,因此我们知道在哪里可以找到源,单元测试,资源等。
  4. 如果它是一个大项目,那么maven多模块项目布局可能是正确使用的结构。
  5. 如果它目前只是一个大漏洞,那么它就会成为核心模块,以后可以重构为单独的模块。
  6. standard maven directory structure提供了地点,因此鼓励进行单元测试。
  7. 在重构开始之前,单元测试是一个关键的先决条件。
  8. 使用Hudson建立持续集成构建周期。

答案 3 :(得分:3)

从单片类开始并将它们分解(超过500个语句,不包括注释和带有大括号的行)。介绍接口,然后介绍依赖注入。

答案 4 :(得分:2)

我现在已经完成了几次这个过程,我发现解决方案需要了解以下内容:

  • 解决这些问题的概念是否存在政治动荡?
  • 现在是否有一个公认的标准可以看待/格式化这些东西?
  • 是否有很棒的测试用例?

政治形势是最难减轻的,从根本上来说没有人喜欢横向移动的想法,并且贯穿执行代码格式化和命名惯例的过程非常是横向移动。如果您能够提出一套可靠的指标来证明您的决定,那么您的横向运动可以伪装成向前运动。我发现这里最好的指标是

“一套一致的编码标准将导致:   - 减少30%的错误   - 开发速度提高30%   - 维护成本降低80%   - 我们100%的程序员会对这一变化感到高兴“

不只是将这些数字从空中拉出来就是诀窍。能证明这一点。

显然,除非你从当前加入项目的人那里购买,否则没有必要开始这项工作。每个人都必须同意并开始将这些理想复制到当前存在的代码中。记住不是每个人都使用IDE(例如我在VIM中编写所有我的java代码),所以你应该确保这个格式在wiki上由所有人看(特别是新的团队成员),并且wiki页面有各种编辑器的下载在使用中。

由于我们很可能不只是谈论代码格式化而且还有变量重命名和模式更改,这些会影响您的类的公共API,因此您确实需要确保拥有一组非常稳定的测试用例。如果缺少测试用例,那么您应该始终从外部开始 - 对测试进行建模,使其与用户进行交互。然后你可以有一定程度的自信地进行重构。一旦你拥有类似于你梦想的代码,你就可以进入并在每个对象附近添加测试。创建所有测试用例,然后更改API并且必须更改所有测试用例,没有什么比这更痛苦了;每次我看到这种情况都会导致测试覆盖率大幅下降。

答案 5 :(得分:1)

我的建议是在你的构建系统中加入类似Checkstyle的东西。管理层很难接受一次性全面检修的想法。设计您认为是一套很好的样式指南并在Checkstyle中实现它们并将其添加到您的构建中。

然后,要求所有新的代码签入都不会破坏Checkstyle。这意味着无论何时你上课,你都会把它提升到标准。如果只是在做出一段时间之前你需要做的一些事情,你似乎根本不会做任何额外的工作。

此外,Eclipse还存在checkstyle插件。

答案 6 :(得分:0)

这是一项相当普遍的任务,不是非常快乐,但也不是噩梦......如果用其他语言编写,可能会更糟糕(Perl,PHP,C ++,-gasp-VB ......);实际上,Java是最适合您的场景的。

获得一个不错的IDE(Eclipse),并花时间了解依赖性和呼叫周期。熟悉一切都需要很长时间,所以尽量只做一些小改动。

当缺少文档时,IDE(以及静态编译)有助于了解谁正在使用哪个类或方法,并且您可以非常自信地进行重构。但首先要尝试确定哪些层/包/类是反射使用的(显式由您的代码,或由您的框架隐式 - 例如,一些getter和setter)。

有很多书专门讨论“再造传统软件”及相关问题。

答案 7 :(得分:0)

我有过这样的经历。 我同意那些推荐maven build,eclipse,Checkstyle,重构大班等的人。我知道在你开始工作之前你无法实现完整的测试覆盖。我推荐 1.使用checkstyle或类似工具以批处理模式重新格式化代码 2.如果此重构很简单,则启用Eclipse中的所有合理警告以及导致此类警告的重构代码。在其他情况下,将@SupressWarning和特殊TODO稍后再回到此代码中。 3.使用缺陷驱动的自动测试,即为您将要更改的模块开发测试。

祝你好运!

答案 8 :(得分:0)

我还重新使用IDE的功能来提高代码质量。对于日食这个我会做的事情:

在首选项中,java>代码风格> formatter - 定义您自己的格式并添加它。之后右键单击项目和源<清理。选择sustom配置文件并进行配置。你可以在这里做很多事情,比如代码格式化清理导入将旧版for循环转换为增强版,清理未使用的代码等等。

之后我会做其他人在这里建议的事情,比如使用checkstyle,pmd,findbugs等。