清理大型遗留 Java 项目
Posted
技术标签:
【中文标题】清理大型遗留 Java 项目【英文标题】:Cleaning up a large, legacy Java project 【发布时间】:2011-04-27 15:20:50 【问题描述】:我被分配在一个巨大的 Java 项目上做一些工作,开发人员多次迭代的影响是显而易见的。没有标准的编码风格、格式、命名约定或类结构。当我遇到一个使用 Javadoc 的课程时,这是一个美好的一天,而单元测试是一个快乐的白日梦。
到目前为止,我们这些参与该项目的人一直在“融入”,适应我们正在从事的任何课程的现有惯例,但现在是时候强加一些秩序和一致性了。
这是一项艰巨的挑战,我正在寻找人们对此类任务的任何建议。是否有任何特别有效的策略或需要注意的陷阱?尝试一下是不是个好主意?
编辑补充:我不想给人留下这个项目很糟糕的印象——它实际上设计得很扎实,而且大部分写得很好。它只是感觉它的年龄和维护的必然性......
【问题讨论】:
我想你应该阅读refactoring 和legacy 上一些最受好评的主题。 【参考方案1】:我发现 Eclipse 对于此类操作来说是一个非常强大的工具。
很多人都对命令行工具和基于模式的文本编辑器发誓进行编程,但使用完整的 IDE 进行重大重构有很大的优势:
自动实时编译会在错误发生时以及发生的任何地方向您显示错误。仅仅因为您进行了更改并且课程中没有任何内容或立即打包中断并不意味着您没有在其他地方创建问题。红旗会在 Eclipse 中的包树上向上显示,引导您直接找到它们。 基于图形的重命名和移动。重命名代码元素的影响可能比您所知道的要大得多。 Eclipse 将向您显示相关元素的每个实例的详细信息以及如何通过重命名对其进行更改。 自动导入管理让您无需处理确保所有导入都井井有条的工作。 Eclipse 会在使用时自动添加导入,并用动作灯泡标记未使用的导入,以便一键删除。 使用代码样式确保所有源文件对所有内容都使用相同的格式。空格、缩进、换行、括号都可以为您设置格式。这适用于您创建新代码以及更新现有文件。除了 Eclipse 的工具集之外,您还可以考虑利用其他现代 Java 工具来确保您的代码始终正常运行。
测试套件可让您不断确保所做的任何更改不会对项目的功能产生负面影响。如果你要重构一个特性,编写两三个测试用例来展示它的工作方式。确保它们在任何更改之前和之后运行。这是在问题成为问题之前发现问题的最简单方法。 使用 Maven 等工具来协助处理依赖关系、测试、编译和部署。不要再浪费时间做任何上述任务。专注于编写完成工作的代码。编辑:
我个人也更喜欢 Eclipse,因为我是负责重构的人,而不是对我的代码几乎一无所知的自动化工具。
【讨论】:
很好的答案,如果您想在重构时修复大量错误/不一致,也值得加入 FindBugs Eclipse 插件......【参考方案2】:您可以使用tool 对项目中的源代码施加通用格式。除此之外,请参阅 Michael Feathers 的 Working Effectively with Legacy Code(其中“遗留代码”被定义为“没有单元测试的代码”),它描述了如何逐渐将遗留代码转变为经过全面测试的代码和可测试的代码。
【讨论】:
【参考方案3】:在这种情况下我喜欢做的是:
-
首先将项目转换为使用maven构建,这样我就知道依赖是什么版本了。
这也为我提供了一些不错的代码质量报告,可用作基准,包括 checkstyle、findbugs、pmd 和代码覆盖率。
而且我(和许多其他人)已经习惯了这种结构,所以我们知道在哪里可以找到源代码、单元测试、资源等。
如果它是一个大型项目,那么 maven 多模块项目布局可能是正确的结构。
如果它目前是一个大泥球,那么它将成为核心模块,以后可以重构为单独的模块。
standard maven directory structure 为单元测试提供了空间,因此鼓励了单元测试。
单元测试是开始重构之前的关键先决条件。
使用Hudson 建立持续集成构建周期。
【讨论】:
除了第 2 步和第 8 步之外,我现在的作业几乎相同。【参考方案4】:从整体类开始并将它们分解(超过 500 条语句,不包括 cmets 和仅带有大括号的行)。引入接口,然后是依赖注入。
【讨论】:
【参考方案5】:我已经经历了几次这个过程,我发现解决方案需要了解以下内容:
解决这些问题会引发政治动荡吗? 现在是否有一个公认的标准来说明这些东西的外观/格式? 有很好的测试用例吗?政治局势最难缓解,基本上没有人喜欢横向移动的想法,而执行代码格式和命名约定的过程在很大程度上是横向移动。如果你能拿出一套可靠的指标来证明你的决定是合理的,那么你的横向运动就可以被伪装成向前运动。我发现这里最好的指标是
“一套一致的编码标准将导致: - 错误减少 30% - 开发速度提高 30% - 维护成本降低 80% - 我们 100% 的程序员都会对这种变化感到高兴”
诀窍不仅仅是从空中提取这些数字。能够证明这一点。
显然,除非您从当前添加到该项目的人员那里获得支持,否则开始这项工作是没有意义的。每个人都必须同意并开始将这些理想重新安装到当前存在的代码中。请记住,不是每个人都使用 IDE(例如,我在 VIM 中编写了所有 java 代码),因此您应该确保这种格式在 wiki 上指定给所有人(尤其是新团队成员),并且 wiki 页面有各种编辑器的下载正在使用中。
因为我们很可能不仅仅是在讨论代码格式,还有变量重命名和模式更改,这些都会影响类的公共 api,所以你真的需要确保你有一组非常稳定的测试用例.如果缺少测试用例,那么您应该始终从外部开始 - 为您的测试建模,以便它们像您的用户一样进行交互。然后你就可以带着一定的信心去经历和重构。一旦你的代码与你的梦想相似,你就可以进入并在每个对象附近添加测试。没有什么比创建所有测试用例、然后更改 API 并不得不更改所有测试用例更痛苦的了;每次我看到这种情况都会导致测试覆盖率大幅下降。
【讨论】:
【参考方案6】:我的建议是在你的构建系统中添加类似 Checkstyle 的东西。很难让管理层接受一次性进行全面检修的想法。设计一套你认为好的风格指南,并在 Checkstyle 中实现它们并将其添加到你的构建中。
然后,要求所有新的代码签入都不会破坏 Checkstyle。这意味着无论何时你在课堂上工作,你都会把它提高到标准。如果只是在投入一段时间之前你必须做的一些事情,那么你似乎根本不会做任何额外的工作。
此外,Eclipse 还存在 checkstyle 插件。
【讨论】:
【参考方案7】:这是一项相当普遍的任务,不是很快乐,但也不是噩梦...如果用其他语言(Perl、php、C++、-gasp-VB...)编码,情况可能会更糟;实际上,Java 是最适合您的方案的一种。
获得一个不错的 IDE (Eclipse) 并花时间了解依赖关系和调用周期。熟悉所有内容需要很长时间,因此请先尝试仅进行小的更改。
当缺乏文档时,IDE(和静态编译)有助于了解谁在使用哪个类或方法,并且您可以非常自信地进行重构。但首先尝试确定在哪些层/包/类中使用了反射(由您的代码显式,或由您的框架隐式 - 例如一些 getter 和 setter)。
有很多书专门讨论“再造遗留软件”和相关问题。
【讨论】:
【参考方案8】:我有过这样的经历。 我同意推荐 maven build、eclipse、Checkstyle、重构大类等的人的观点。我知道在开始工作之前您无法实现完整的测试覆盖率。我会推荐 1. 使用 checkstyle 或类似工具以批处理模式重新格式化代码 2. 在 Eclipse 中启用所有合理的警告并重构导致此类警告的代码,如果这种重构是微不足道的。在其他情况下,将 @SupressWarning 和特殊的 TODO 放在稍后返回此代码。 3. 使用缺陷驱动的自动测试,即为您要更改的模块开发测试。
祝你好运!
【讨论】:
【参考方案9】:我还建议使用 IDE 的功能来提高代码质量。对于 Eclipse 这我会做什么:
在首选项 java > code style > formatter - 定义你自己的格式并添加它。之后右键单击项目和源
之后我会做其他人建议的事情,比如使用 checkstyle、pmd、findbugs 等等。
【讨论】:
以上是关于清理大型遗留 Java 项目的主要内容,如果未能解决你的问题,请参考以下文章