2008-09-28 71 views
36

当你在一个传统的代码库中工作时,将会对时间产生最大的影响,从而提高代码库的质量?你可以对遗留代码库做些什么,这对提高质量将产生最大的影响?

  • 删除未使用的代码
  • 删除重复的代码
  • 添加单元测试,提高测试覆盖率,其中覆盖率低
  • 创建跨文件格式保持一致
  • 更新第三方软件
  • 减少所产生的警告通过静态分析工具(ieFindbugs)

代码库由许多开发人员在多年的专业知识水平上编写而成,其中很多领域都未经过测试,而且有些测试不需要花费大量时间编写测试。

回答

33

这是一个伟大的书。

如果你不喜欢这个答案的话,我能给的最好的建议是:

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

[1]:遗产没有单元测试代码=代码,因此一个未知

更改传统代码没有自动化测试套件到位是危险的,不负责任的。没有良好的单元测试覆盖率,你不可能知道这些变化会有什么影响。 Feathers建议您采用“束缚”方法,在这些方法中,您需要隔离需要更改的代码区域,编写一些基本测试来验证基本假设,通过单元测试进行小的更改,然后从中解决。

注意:我并不是说你需要停止一切,花几个星期为一切写作测试。恰恰相反,只是测试你需要测试的区域并从那里开始工作。

吉米·博加德和雷 - 休斯顿做了非常类似于这样一个主题一个有趣的屏幕转换: http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/05/06/pablotv-eliminating-static-dependencies-screencast.aspx

5

我会说“删除重复的代码”几乎意味着你必须拉出来的代码和抽象的它,所以它可以在多个地方使用 - 这样,在理论上,使错误更容易解决,因为你只需要修复一块代码,而不是许多代码段,来修复它中的一个错误。

3

我可以涉及到这个问题,因为我目前在我腿上的一个“那些”老学校的代码库。它不是真正的遗产,但它肯定没有遵循这些年的趋势。

我会告诉你的事情,我喜欢它,因为他们的错误我天天来解决:

  • 文件的输入和输出变量
  • 重构的变量名,使他们实际上意味着以外的东西和一些匈牙利语符号前缀,后跟三个字母的缩写,并带有一些不太明确的含义。 CammelCase是要走的路。
  • 我很害怕改变任何代码,因为它会影响使用该软件的数百个客户,并且有人会注意到即使是最隐晦的副作用。任何可重复的回归测试将是一件幸事,因为现在为零。

其余的确是花生。这些是遗留代码库的主要问题,它们真的耗尽了大量时间。

6

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

CPPUnit,Working Effectively with Legacy Code的作者撰写了这本书。

向传统代码添加测试比从头创建测试要困难得多。我从书中拿掉的最有用的概念是“接缝”的概念,羽毛定义为

“一个您可以在该程序中修改行为而无需在该处进行编辑的地方。”

有时它的价值重构,以创建接缝,这将使未来的测试更容易(或有可能在第一的位置。)的google testing blog有关于这个问题的一些有趣的帖子,大多是围绕Dependency Injection过程中旋转。

+0

在代码中添加测试真的很困难,因为最终你甚至无法接近要测试的代码。它有点鸡和蛋,没有测试就不能重新考虑/不能重新编写好测试 – 2008-09-28 23:10:20

2

我会说这在很大程度上取决于你想用旧代码做什么...

如果将无限期地停留在维护模式和它的正常工作,什么都不做是最好的选择。 “如果它没有损坏,请不要修理它。”

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

如果您计划在2.0版本中,添加单元测试和清理代码,你会提出

2

良好的文档。作为必须维护和扩展遗留代码的人员,这是头号问题。即使不是彻底危险的改变你不明白的代码也很困难。即使你有足够的幸运可以交上文档化的代码,你对文档的正确性有多确定?它涵盖了原作者的所有隐含知识吗?它说明了所有的“技巧”和边缘情况?

良好的文档可以让原作者以外的人理解,修复甚至扩展糟糕的代码。我会采用黑客入侵的,但有充分文件记录的代码,我可以在一周中的任何一天通过完美而难以理解的代码来理解。

+0

单元测试是文档,问题是遗留代码(正如M. Feathers在“有效地工作遗留代码“)没有它们。 – 2010-07-03 10:14:17

20

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

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

1

我对遗留代码所做的最重要的事情就是围绕它构建真正的API。这是一个20世纪70年代风格的COBOL API,我已经构建了一个.NET对象模型,以便所有不安全的代码位于同一位置,API本地数据类型和.NET数据类型之间的所有转换都位于同一位置,主要方法返回并接受数据集,等等。

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

1

与Josh Segall所说的一样,我会说出评论。我曾经研究过一些遗留在我腿上的非常大的遗留系统,我发现最大的问题是跟踪我已经了解的特定代码段。一旦我开始放置笔记,包括“待办事项”笔记,我就不再重新计算出我已经弄清楚的内容。然后我可以专注于这些代码段如何流动和交互。

1

我会说,大多数情况下都不要说。如果它没有损坏,那就不要修复它。如果它被破坏了,那么请继续修复并改善破坏的代码部分及其周围的代码。您可以使用错误或严重缺失功能的痛苦来证明改进该部分的努力和成本。

我不会推荐任何批量改写,重构,重新格式化或放入不受实际业务或最终用户需求指导的单元测试。

如果你确实有机会解决某些问题,那就做对吧(第一次做这件事的机会可能已经过去了,但是因为你再次触摸那个部件不妨做正确的时间)这包括你提到的所有项目。

因此,总之,没有单一或只有几件事情,你应该做的。你应该尽一切努力,但以小部分和机会主义的方式。

1

迟到了,但在使用或引用通常是功能/方法下面可能是值得做的事情:

  • 局部变量往往倾向于在传统代码不佳命名(而且通常是因为其范围当一个方法被修改时扩展,而不是被更新来反映这个)。将这些重命名为符合其实际用途可以帮助澄清遗留代码。
  • 即使只是略微不同的布置方法也可以创造奇迹 - 例如,将if的所有子句放在一行上。
  • 这里可能有陈旧/混淆的代码注释。如果不需要,请将其移除,如果您绝对必须修改它们。 (当然,我不主张拆除有用的意见,只是那些障碍。)

这些可能没有你要找的大量头条的影响,但他们是低风险,特别是如果代码不能被单元测试的话。