39

当您在遗留代码库中工作时,随着时间的推移,什么会对提高代码库的质量产生最大的影响?

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

多年来,该代码库由许多具有不同专业水平的开发人员编写,其中许多领域未经测试,有些无法测试,而无需花费大量时间编写测试。

4

11 回答 11

37

这是一本很好的书。

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

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

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

在没有自动化测试套件的情况下更改遗留代码是危险且不负责任的。如果没有良好的单元测试覆盖率,您不可能知道这些更改会产生什么影响。Feathers 推荐一种“扼杀”方法,您可以隔离需要更改的代码区域,编写一些基本测试来验证基本假设,在单元测试的支持下进行小的更改,然后从那里开始工作。

注意:我并不是说您需要停止一切并花费数周时间为所有内容编写测试。恰恰相反,只需围绕您需要测试和锻炼的区域进行测试。

Jimmy Bogard 和 Ray Houston 就与此非常相似的主题做了一个有趣的屏幕投射: http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/05/06/pablotv-eliminating-static-dependencies-screencast。 aspx

于 2008-09-28T22:57:03.757 回答
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

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

于 2008-10-19T23:31:00.923 回答
6

我会说“删除重复的代码”几乎意味着您必须将代码提取并抽象出来,以便它可以在多个地方使用 - 从理论上讲,这使得错误更容易修复,因为您只需要修复一段代码,而不是许多代码,来修复其中的错误。

于 2008-09-28T22:55:09.253 回答
6

添加单元测试以提高测试覆盖率。拥有良好的测试覆盖率将使您能够毫无畏惧地重构和改进功能。

CPPUnit 的作者写了一本很好的书,有效地使用遗留代码

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

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

有时它值得重构以创建接缝,这将使未来的测试更容易(或首先可能)。谷歌测试博客有几篇关于这个主题的有趣帖子,主要围绕依赖注入的过程。

于 2008-09-28T23:06:57.837 回答
4

我可以与这个问题联系起来,因为我目前在我的膝上是“那些”旧学校代码库之一。它不是真正的遗产,但它肯定没有跟随这些年来的趋势。

我会告诉你我想在其中修复的东西,因为它们每天都会困扰我:

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

剩下的真的是花生。这些是遗留代码库的主要问题,它们确实占用了大量时间。

于 2008-09-28T23:02:27.987 回答
2

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

如果它将无限期地保持在维护模式并且工作正常,那么您最好什么也不做。“如果它没有坏,就不要修理它。”

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

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

于 2008-09-28T23:19:24.280 回答
2

好的文档。作为必须维护和扩展遗留代码的人,这是第一个问题。更改您不理解的代码是很困难的,如果不是非常危险的话。即使您有幸获得了文档化代码,您有多确定文档是正确的?它涵盖了原作者的所有隐含知识?它说明了所有的“技巧”和边缘情况?

好的文档可以让原始作者以外的人理解、修复和扩展甚至是糟糕的代码。我将在一周中的任何一天使用那些我可以理解的被破解但有据可查的代码,而不是完美但难以理解的代码。

于 2008-09-29T00:34:42.087 回答
1

我对必须使用的遗留代码所做的最大的一件事情就是围绕它构建一个真正的 API。这是一个 1970 年代风格的 COBOL API,我围绕它构建了一个 .NET 对象模型,因此所有不安全的代码都在一个地方,API 的本机数据类型和 .NET 数据类型之间的所有转换都在一个地方,主要方法返回和接受数据集,等等。

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

于 2008-12-08T00:59:19.553 回答
1

与 Josh Segall 所说的类似,我想说的是,该死的评论一下。我曾在几个非常大的遗留系统上工作过,这些系统被丢在我的腿上,我发现最大的问题是跟踪我已经了解的关于特定代码部分的内容。一旦我开始放置笔记,包括“待办事项”笔记,我就不再重新找出我已经弄清楚的东西。然后我可以专注于这些代码段是如何流动和交互的。

于 2008-12-08T01:34:47.563 回答
1

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

我不会推荐任何不以实际业务或最终用户需求为指导的大规模重写、重构、重新格式化或放入单元测试。

如果你确实有机会修复某些东西,那就把它做对(第一次做对的机会可能已经过去了,但既然你再次接触那个部分,不妨及时做对),这包括所有你提到的项目。

因此,总而言之,您不需要做任何一件或几件事情。你应该做这一切,但要以小部分和机会主义的方式。

于 2011-07-15T00:37:27.303 回答
1

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

  • 局部变量在遗留代码中的命名往往很糟糕(通常是因为它们的范围在修改方法时扩展,并且没有更新以反映这一点)。根据实际目的重命名它们有助于澄清遗留代码。
  • 即使只是稍微不同地布置方法也能产生奇迹——例如,将 an 的所有子句if放在一行上。
  • 那里可能已经有陈旧/令人困惑的代码注释。如果不需要,请删除它们,或者如果您绝对需要,请修改它们。(当然,我不主张删除有用的评论,只是那些有碍的评论。)

这些可能不会产生您正在寻找的巨大的标题影响,但它们的风险很低,尤其是在代码无法进行单元测试的情况下。

于 2013-02-25T15:25:15.987 回答