您如何处理对提高质量影响最大的遗留代码库?

问题描述 投票:39回答:11

当您在遗留代码库中工作时,随着时间的推移会产生哪些影响,从而提高代码库的质量?

  • 删除未使用的代码
  • 删除重复的代码
  • 添加单元测试以改善覆盖率低的测试覆盖率
  • 跨文件创建一致的格式
  • 更新第三方软件
  • 减少静态分析工具(即.Findbugs)生成的警告

代码库是由许多开发人员编写的,他们多年来具有不同的专业知识水平,许多领域未经测试,有些领域不可测试,而且没有花费大量时间编写测试。

refactoring legacy legacy-code
11个回答
34
投票

这是一本很好的书。

如果你不喜欢这个答案,那么我能给出的最佳建议是:

  • 首先,停止制作新的遗留代码[1]

[1]:遗留代码=没有单元测试的代码,因此是未知的

在没有自动化测试套件的情况下更改遗留代码是危险且不负责任的。如果没有良好的单元测试覆盖率,您无法知道这些更改会产生什么影响。 Feathers建议采用“束缚”方法,在这种方法中,您需要更改需要更改的代码区域,编写一些基本测试以验证基本假设,通过单元测试进行小的更改,然后从那里开始工作。

注意:我并不是说你需要停止所有事情并花费数周时间为所有事情编写测试。恰恰相反,只需测试您需要测试和从那里进行测试的区域。

Jimmy Bogard和Ray Houston在一个非常类似的主题上做了一个有趣的屏幕:http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/05/06/pablotv-eliminating-static-dependencies-screencast.aspx


1
投票

我想说的是,大部分时间都不要管它。如果它没有坏,那么不要修复它。如果它被破坏,那么继续修复和改进被破坏的代码部分及其周围的代码。您可以利用错误的痛苦或严重缺失的功能来证明改进该部分的努力和费用。

我不建议任何批发类型的重写,重构,重新格式化或放入不受实际业务或最终用户需求指导的单元测试。

如果你确实有机会修理某些东西,那么就做对了(第一次做正确的机会可能已经过去了,但是因为你再次接触那个部分也可能正确地做到这一点)这包括所有你提到的项目。

总而言之,你应该做的不是单一或只是一些事情。你应该以一小部分和机会主义的方式做到这一切。


1
投票

晚到派对,但在使用或经常引用函数/方法的情况下,以下值得做:

  • 局部变量往往在遗留代码中命名不佳(通常是由于在修改方法时范围扩大,并且未进行更新以反映这一点)。根据实际目的重命名这些可以帮助澄清遗留代码。
  • 即使只是略微不同地设置方法也可以创造奇迹 - 例如,将if的所有子句放在一行上。
  • 那里可能存在陈旧/混乱的代码注释。如果不需要它们,请将它们移除,或者如果您不需要则修改它们。 (当然,我不是主张删除有用的评论,只是那些妨碍评论。)

这些可能没有您正在寻找的巨大标题影响,但它们风险较低,特别是如果代码无法进行单元测试。


21
投票

我使用由大约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

值得的。有时警告可以隐藏潜在的错误。


6
投票

添加单元测试以提高测试覆盖率。拥有良好的测试覆盖率将允许您无需担心地重构和改进功能。

CPPUnit的作者Working Effectively with Legacy Code撰写了一本很好的书。

向遗留代码添加测试肯定比从头创建测试更具挑战性。我从这本书中摘取的最有用的概念是“接缝”的概念,Feathers定义为“接缝”

“你可以改变程序行为而不在那个地方进行编辑的地方。”

有时它值得重构以创建接缝,使未来的测试更容易(或者首先可能。)google testing blog有关于这个主题的几个有趣的帖子,主要围绕Dependency Injection的过程。


5
投票

我说'删除重复的代码'几乎意味着你必须将代码拉出并抽象它以便它可以在多个地方使用 - 理论上,这使得错误更容易修复,因为你只需要修复一段代码,与许多代码相对,修复其中的错误。


3
投票

我可以提到这个问题,因为我目前在我的膝盖上有一个'那些'旧学校代码库。它不是真正的遗产,但它肯定没有跟随多年的趋势。

我会告诉你我想要解决的事情,因为他们每天都在烦我:

  • 记录输入和输出变量
  • 重构变量名称,以便它们实际上意味着其他东西和一些匈牙利语符号前缀,后跟三个字母的首字母缩写,带有一些模糊的含义。 CammelCase是要走的路。
  • 我害怕改变任何代码,因为它会影响数百个使用该软件的客户,有人会注意到最模糊的副作用。任何可重复的回归测试都是祝福,因为现在有零。

剩下的就是花生。这些是遗留代码库的主要问题,它们真的耗费了大量时间。


2
投票

我说它在很大程度上取决于你想用遗留代码做什么......

如果它将无限期地保持在维护模式并且工作正常,那么什么都不做是最好的选择。 “如果没有破产,请不要修理它。”

如果它工作不正常,删除未使用的代码并重构重复的代码将使调试更容易。但是,我只会对错误的代码进行这些更改。

如果您计划使用2.0版,请添加单元测试并清理您将提出的代码


2
投票

好文档。作为必须维护和扩展遗留代码的人,这是头号问题。如果不是彻头彻尾的危险,改变您不理解的代码是很困难的。即使你很幸运能够提交文件化的代码,你对文档是否正确有多确定?它涵盖了原作者的所有隐含知识?它说的是所有的“技巧”和边缘案例?

良好的文档是允许原始作者以外的人理解,修复和扩展甚至错误的代码的原因。我将采用黑客但记录良好的代码,我可以在一周中的任何一天通过完美但难以理解的代码来理解这些代码。


1
投票

我对遗留代码所做的最重要的事情就是围绕它构建一个真正的API。这是一个1970年代风格的COBOL API,我已经构建了一个.NET对象模型,所以所有不安全的代码都放在一个地方,API的本机数据类型和.NET数据类型之间的所有转换都集中在一个地方,主方法返回并接受DataSet,依此类推。

这样做非常困难,而且我知道它仍然存在一些缺陷。随着所有的编组工作的进行,它也不是非常有效。但另一方面,我可以构建一个DataGridView,将数据往返于一个已有15年历史的应用程序,该应用程序在大约半小时内将数据保存在Btrieve(!)中,并且可以正常工作。当客户来找我项目时,我的估计是几天和几周,而不是几个月和几年。


1
投票

与Josh Segall所说的相似,我会说它出了问题。我已经研究过几个非常庞大的传统系统,这些系统被丢弃在我的膝盖上,我发现最大的问题是跟踪我已经了解的特定部分代码。一旦我开始放置笔记,包括“待办事项”笔记,我就不再重新弄清楚我已经弄清楚了什么。然后我可以专注于这些代码段如何流动和交互。

© www.soinside.com 2019 - 2024. All rights reserved.