当您在遗留代码库中工作时,随着时间的推移,什么会对提高代码库的质量产生最大的影响?
- 删除未使用的代码
- 删除重复代码
- 添加单元测试以提高覆盖率低的测试覆盖率
- 跨文件创建一致的格式
- 更新第 3 方软件
- 减少静态分析工具(即Findbugs)产生的警告
多年来,该代码库由许多具有不同专业水平的开发人员编写,其中许多领域未经测试,有些无法测试,而无需花费大量时间编写测试。
当您在遗留代码库中工作时,随着时间的推移,什么会对提高代码库的质量产生最大的影响?
多年来,该代码库由许多具有不同专业水平的开发人员编写,其中许多领域未经测试,有些无法测试,而无需花费大量时间编写测试。
这是一本很好的书。
如果您不喜欢这个答案,那么我能给出的最佳建议是:
[1]:遗留代码 = 没有单元测试的代码,因此未知
在没有自动化测试套件的情况下更改遗留代码是危险且不负责任的。如果没有良好的单元测试覆盖率,您不可能知道这些更改会产生什么影响。Feathers 推荐一种“扼杀”方法,您可以隔离需要更改的代码区域,编写一些基本测试来验证基本假设,在单元测试的支持下进行小的更改,然后从那里开始工作。
注意:我并不是说您需要停止一切并花费数周时间为所有内容编写测试。恰恰相反,只需围绕您需要测试和锻炼的区域进行测试。
Jimmy Bogard 和 Ray Houston 就与此非常相似的主题做了一个有趣的屏幕投射: http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/05/06/pablotv-eliminating-static-dependencies-screencast。 aspx
我使用由大约 50 名程序员编写和修改的遗留 1M LOC 应用程序。
* Remove unused code
几乎没用……忽略它。您不会从中获得很大的投资回报 (ROI)。
* Remove duplicated code
实际上,当我修复某些东西时,我总是搜索重复项。如果我发现了一些,我会放置一个通用函数或注释所有重复出现的代码(有时,放置一个通用函数的努力是不值得的)。主要思想是,我讨厌多次做同样的动作。另一个原因是因为总是有人(可能是我)忘记检查其他事件......
* Add unit tests to improve test coverage where coverage is low
自动化单元测试很棒……但是如果你有大量的积压,除非你有稳定性问题,否则任务本身就很难推广。继续你正在研究的部分,并希望在几年内你有不错的报道。
* Create consistent formatting across files
IMO 格式的差异是遗产的一部分。它会提示您编写代码的人或时间。这可以为您提供一些关于如何在该部分代码中表现的线索。进行重新格式化的工作并不有趣,也不会为您的客户带来任何价值。
* Update 3rd party software
仅当有新的非常好的功能或新操作系统不支持您拥有的版本时才这样做。
* Reduce warnings generated by static analysis tools
它可以是值得的。有时警告可以隐藏潜在的错误。
我会说“删除重复的代码”几乎意味着您必须将代码提取并抽象出来,以便它可以在多个地方使用 - 从理论上讲,这使得错误更容易修复,因为您只需要修复一段代码,而不是许多代码,来修复其中的错误。
我可以与这个问题联系起来,因为我目前在我的膝上是“那些”旧学校代码库之一。它不是真正的遗产,但它肯定没有跟随这些年来的趋势。
我会告诉你我想在其中修复的东西,因为它们每天都会困扰我:
剩下的真的是花生。这些是遗留代码库的主要问题,它们确实占用了大量时间。
我想说这在很大程度上取决于你想对遗留代码做什么......
如果它将无限期地保持在维护模式并且工作正常,那么您最好什么也不做。“如果它没有坏,就不要修理它。”
如果它不能正常工作,删除未使用的代码并重构重复的代码将使调试更容易。但是,我只会对错误代码进行这些更改。
如果您计划使用 2.0 版,请添加单元测试并清理您将提出的代码
好的文档。作为必须维护和扩展遗留代码的人,这是第一个问题。更改您不理解的代码是很困难的,如果不是非常危险的话。即使您有幸获得了文档化代码,您有多确定文档是正确的?它涵盖了原作者的所有隐含知识?它说明了所有的“技巧”和边缘情况?
好的文档可以让原始作者以外的人理解、修复和扩展甚至是糟糕的代码。我将在一周中的任何一天使用那些我可以理解的被破解但有据可查的代码,而不是完美但难以理解的代码。
我对必须使用的遗留代码所做的最大的一件事情就是围绕它构建一个真正的 API。这是一个 1970 年代风格的 COBOL API,我围绕它构建了一个 .NET 对象模型,因此所有不安全的代码都在一个地方,API 的本机数据类型和 .NET 数据类型之间的所有转换都在一个地方,主要方法返回和接受数据集,等等。
要做到这一点非常困难,而且我知道其中还有一些缺陷。它也不是非常有效,所有编组都在进行。但另一方面,我可以构建一个 DataGridView,将数据往返传输到一个有 15 年历史的应用程序,该应用程序在大约半小时内将其数据保存在 Btrieve (!) 中,并且它可以工作。当客户带着项目来找我时,我的估计是几天和几周,而不是几个月和几年。
与 Josh Segall 所说的类似,我想说的是,该死的评论一下。我曾在几个非常大的遗留系统上工作过,这些系统被丢在我的腿上,我发现最大的问题是跟踪我已经了解的关于特定代码部分的内容。一旦我开始放置笔记,包括“待办事项”笔记,我就不再重新找出我已经弄清楚的东西。然后我可以专注于这些代码段是如何流动和交互的。
我想说的是,大部分时间不要管它。如果它没有损坏,则不要修复它。如果它被破坏,那么继续修复和改进被破坏的代码部分及其周围的代码。您可以使用错误的痛苦或严重缺失的功能来证明改进该部分的努力和费用是合理的。
我不会推荐任何不以实际业务或最终用户需求为指导的大规模重写、重构、重新格式化或放入单元测试。
如果你确实有机会修复某些东西,那就把它做对(第一次做对的机会可能已经过去了,但既然你再次接触那个部分,不妨及时做对),这包括所有你提到的项目。
因此,总而言之,您不需要做任何一件或几件事情。你应该做这一切,但要以小部分和机会主义的方式。
派对迟到了,但在经常使用或引用函数/方法的情况下,以下可能值得做:
if
放在一行上。这些可能不会产生您正在寻找的巨大的标题影响,但它们的风险很低,尤其是在代码无法进行单元测试的情况下。