代码之家  ›  专栏  ›  技术社区  ›  Craig Angus karan

对于对提高质量有最大影响的遗留代码库,您可以做些什么?

  •  38
  • Craig Angus karan  · 技术社区  · 18 年前

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

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

    多年来,许多具有不同专业水平的开发人员编写了代码库,其中有许多领域未经测试,有些领域不稳定,而没有花大量时间编写测试。

    11 回复  |  直到 12 年前
        1
  •  33
  •   chadmyers    18 年前

    这是一本好书。

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

    • 首先,停止生成新的旧代码[1]

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

    在没有自动化测试套件的情况下更改遗留代码是危险和不负责任的。如果没有良好的单元测试覆盖率,您就不可能知道这些更改会有什么影响。Feathers推荐了一种“绞尽脑汁”的方法,在这种方法中隔离需要更改的代码区域,编写一些基本测试来验证基本假设,在单元测试的支持下做一些小的更改,并从中得出结论。

    注意:我并不是说你需要停止一切,花几个星期的时间来为一切编写测试。恰恰相反,只需在需要测试的区域周围进行测试,然后从那里开始计算。

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

        2
  •  21
  •   Hapkido    17 年前

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

    在我看来,格式上的差异是遗产的一部分。它向您提供了关于代码编写者或编写时间的提示。这可以给您一些关于如何在代码的那一部分中行为的线索。重新格式化的工作并不有趣,也不会给客户带来任何价值。

    * Update 3rd party software
    

    只有当有新的非常好的功能或者新的操作系统不支持您所拥有的版本时,才可以这样做。

    * Reduce warnings generated by static analysis tools
    

    这是值得的。有时警告会隐藏潜在的错误。

        3
  •  6
  •   Gordon Wilson    18 年前

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

    有一本很好的关于这方面的书是由人民政协的作者写的。 Working Effectively with Legacy Code .

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

    “可以在不在该位置编辑的情况下更改程序行为的位置。”

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

        4
  •  5
  •   James Inman    18 年前

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

        5
  •  3
  •   Caerbanog    18 年前

    我可以和这个问题联系起来,因为我现在在我的膝盖上有一个“那些”旧的学校代码库。它并不是真正的遗产,但肯定没有遵循这些年的趋势。

    我会告诉你我想在里面解决的事情,因为他们每天都在骚扰我:

    • 记录输入和输出变量
    • 重构变量名,使它们实际上表示其他一些匈牙利符号前缀,后面是三个字母的首字母缩写,含义有些模糊。卡梅尔凯斯是一条必经之路。
    • 我害怕更改任何代码,因为它会影响数百个使用该软件的客户机,甚至有人会注意到最模糊的副作用。任何可重复的回归测试都是一件好事,因为现在已经没有了。

    其余的都是花生。这些是遗留代码库的主要问题,它们占用了大量的时间。

        6
  •  2
  •   Austin Salonen gmlacrosse    18 年前

    我想说,这很大程度上取决于您想如何处理遗留代码…

    如果它将无限期地保持在维护模式下,并且工作正常,那么您最好不做任何事情。”如果没坏,就别修了。”

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

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

        7
  •  2
  •   Josh Segall    18 年前

    良好的文件。作为一个必须维护和扩展遗留代码的人,这是第一个问题。很难,如果不完全危险的话,改变你不理解的代码。即使您很幸运地获得了文档化的代码,您又如何确定文档是正确的呢?它涵盖了原作者所有的隐性知识?它能说明所有的“技巧”和边缘案例吗?

    好的文档可以让原始作者以外的人理解、修复甚至扩展坏代码。我将在一周中的任何一天使用我能理解的、被黑客攻击但又有很好文档记录的代码。

        8
  •  1
  •   Robert Rossney    17 年前

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

    这是非常困难做正确的,而且仍然有一些缺陷,我知道。它的效率也不高,因为所有的编组都在进行。但另一方面,我可以构建一个DataGridView,它将数据往返于一个15年前的应用程序,该应用程序将其数据保存在btrieve(!)中。大约半小时后,它就开始工作了。当客户带着项目来找我时,我的估计是几天几周,而不是几个月几年。

        9
  •  1
  •   dj_segfault    17 年前

    与乔希·西格尔所说的类似,我想说的是“见鬼去评论”。我已经研究了几个非常大的遗留系统,这些系统被丢弃在我的大腿上,我发现最大的问题是跟踪我已经了解的关于特定代码部分的内容。一旦我开始边走边写笔记,包括“要做”的笔记,我就不再去想我已经知道了什么。然后我可以关注这些代码段是如何流动和交互的。

        10
  •  1
  •   Omen    15 年前

    我想说的是大部分时间都不要插手。如果它没有坏,那就不要修理它。如果它被破坏了,那么继续修复并改进被破坏的代码部分及其周围的代码。您可以使用bug带来的痛苦或严重缺失的特性来证明改进该部件所付出的努力和费用是合理的。

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

    如果你真的有机会修复某件事,那么就把它做对(第一次做对的机会可能已经过去了,但既然你再次接触到这一部分,那么最好在适当的时候做对了),这包括你提到的所有项目。

    所以总的来说,你不应该做任何一件或只是一些事情。你应该以一种机会主义的方式,只做一小部分。

        11
  •  1
  •   craigmcnulty    13 年前

    对于参与方来说,可能晚了,但在经常使用或引用函数/方法的情况下,可能需要执行以下操作:

    • 在遗留代码中,局部变量的命名往往很差(通常是因为当方法被修改时,它们的作用域会扩大,并且不会被更新以反映这一点)。根据它们的实际用途重命名这些代码可以帮助澄清遗留代码。
    • 即使只是以稍微不同的方式列出方法也能产生奇迹——例如,将 if 在一条线上。
    • 可能已经有陈旧/混乱的代码注释。如果不需要,可以将其移除,如果必须,也可以对其进行修改。 (当然,我并不主张删除有用的评论,只是那些妨碍的评论。)

    这些可能没有你想要的巨大的标题影响,但是它们的风险很低,特别是如果代码不能被单元测试的话。