清理大型遗留Java项目

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

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

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

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

我发现Eclipse对于像这样的操作来说是一个非常强大的工具。

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

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

除了Eclipse的工具集之外,您还可以利用其他现代Java工具来确保代码始终正常运行。

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

编辑:

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

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

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

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

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

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

  • 修复这些事情的概念是否存在政治动荡?
  • 现在是否有一个公认的标准来看待/格式化这些东西?
  • 有很棒的测试用例吗?

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

“一套一致的编码标准将导致: – 错误减少30% – 开发速度提高30% – 维护成本降低80% – 我们100%的编码人员会对此更改感到高兴”

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

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

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

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

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

此外,Eclipse还存在checkstyle插件。

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

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

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

有很多书专门讨论“重新设计遗留软件”及相关问题。

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

祝你好运!

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

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

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