如何在遗留项目中实现静态代码分析器而不影响团队积极性

如何在遗留项目中实现静态代码分析器而不影响团队积极性
尝试静态代码分析器很容易。 但要实现它,尤其是在大型旧项目的开发中,需要技巧。 如果做得不正确,分析人员可能会增加工作量、减慢开发速度并降低团队的积极性。 让我们简单谈谈如何正确地将静态分析集成到开发过程中,并开始将其用作 CI/CD 的一部分。

介绍

最近我的注意力被《在不让团队不知所措的情况下开始静态分析”。一方面,这是一篇值得熟悉的好文章。另一方面,在我看来,它仍然没有提供关于如何在一个有大量数据的项目中轻松实现静态分析的完整答案。文章说,您可以接受技术债务并仅在新代码上工作,但没有回答稍后如何处理该技术债务。

我们的 PVS-Studio 团队就此主题发表了自己的看法。 让我们看看实现静态代码分析器的问题最初是如何出现的,如何克服这个问题,以及如何轻松地逐步消除技术债务。

问题

启动并查看静态分析器如何工作通常并不困难[1]。 您可能会在代码中看到有趣的错误,甚至可怕的潜在漏洞。 您甚至可以修复某些问题,但许多程序员会放弃。

所有静态分析仪都会产生误报。 这是静态代码分析方法的一个特点,对此我们无能为力。 在一般情况下,这是一个无法解决的问题,正如赖斯定理所证实的那样[2]。 机器学习算法也无济于事[3]。 即使一个人不能总是分辨出这个或那个代码是否错误,那么你也不应该期望程序会出现这种情况:)。

如果静态分析器已配置,则误报不是问题:

  • 禁用不相关的规则集;
  • 一些不相​​关的诊断已被禁用;
  • 如果我们谈论的是 C 或 C++,那么宏会被标记为包含特定的结构,这些结构会导致在使用此类宏的每个地方出现无用的警告;
  • 自己的函数被标记为执行类似于系统函数的操作(它自己的模拟 Memcpy или 的printf)[4];
  • 使用注释专门禁用误报;
  • 等。

在这种情况下,我们预计误报率较低,约为 10-15% [5]。 换句话说,十分之九的分析器警告将表明代码中存在真正的问题,或者至少是“气味浓烈的代码”。 同意,这个场景非常令人愉快,分析器是程序员真正的朋友。

如何在遗留项目中实现静态代码分析器而不影响团队积极性
事实上,在一个大型项目中,最初的画面会完全不同。 分析器针对遗留代码发出数百或数千条警告。 不可能快速了解这些警告中哪些是相关的,哪些是不相关的。 坐下来开始处理所有这些警告是不合理的,因为这种情况下的主要工作将停止数天或数周。 通常,团队无法承受这种情况。 还会有大量的差异破坏变更历史。 快速批量编辑代码中如此多的片段将不可避免地导致新的拼写错误和错误。

最重要的是,这种对抗警告的壮举毫无意义。 同意该项目已成功运行多年,其中大部分关键错误已得到纠正。 是的,这些修复非常昂贵,必须进行调试,收到有关错误的负面用户反馈,等等。 静态分析器将有助于在编码阶段快速且廉价地修复许多此类错误。 但目前,无论怎样,这些错误已经被修复,分析器主要检测旧代码中的非关键错误。 该代码可能不会被使用,也可能很少使用,并且其中的错误可能不会导致明显的后果。 也许按钮的阴影在某个地方颜色错误,但这不会影响任何人使用该产品。

当然,再小的错误也仍然是错误。 有时,错误可能隐藏真正的漏洞。 然而,放弃一切并花费数天/数周的时间来处理几乎不显现出来的缺陷似乎是一个可疑的想法。

程序员看着、看着、看着所有这些关于旧工作代码的警告……他们认为:我们可以不用静态分析。 让我们去写一些新的有用的功能。

以他们自己的方式,他们是对的。 他们认为首先必须以某种方式消除所有这些警告。 只有这样,他们才能从定期使用代码分析器中受益。 否则,新的警告就会被旧的警告淹没,而没有人会注意到它们。

这与编译器警告的类比相同。 他们建议将编译器警告的数量保持在 0 并不是没有道理的。如果有 1000 个警告,那么当有 1001 个时,就没有人会注意了,而且也不清楚去哪里寻找这个最新的警告。

如何在遗留项目中实现静态代码分析器而不影响团队积极性
这个故事中最糟糕的事情是,如果此时上面有人强迫您使用静态代码分析。 这只会削弱团队的积极性,因为从他们的角度来看,额外的官僚复杂性只会造成阻碍。 没有人会看分析仪的报告,所有的使用都只是“纸上谈兵”。 那些。 形式上,分析被内置到 DevOps 流程中,但实际上这对任何人都没有好处。 我们在展位上听到了与会者的详细故事。 这样的经历可能会阻碍程序员在很长一段时间内(甚至永远)使用静态分析工具。

实施和消除技术债务

事实上,即使在大型旧项目中引入静态分析也没有什么困难或可怕的。

CI / CD

此外,分析仪可以立即成为持续开发过程的一部分。 例如,PVS-Studio 发行版包含用于方便地以您需要的格式查看报告的实用程序,以及向编写有问题的代码部分的开发人员发出的通知。 对于那些对从 CI/CD 系统启动 PVS-Studio 更感兴趣的人,我建议您熟悉相应的内容 部分 文档和一系列文章:

但让我们回到在实施代码分析工具的第一阶段出现大量误报的问题。

修复现有技术债务并处理新警告

现代商业静态分析器允许您仅研究新代码或更改代码中出现的新警告。 这种机制的实现方式各有不同,但本质是一样的。 在PVS-Studio静态分析仪中,该功能的实现如下。

为了快速开始使用静态分析,我们建议PVS-Studio用户使用批量抑制警告的机制[6]。 总体思路如下。 用户启动分析仪并收到许多警告。 由于一个已经开发多年的项目仍然存在,正在开发并且正在赚钱,那么报告中很可能不会有太多表明严重缺陷的警告。 换句话说,关键错误已经通过更昂贵的方法或客户的反馈以某种方式得到修复。 因此,分析器当前发现的所有内容都可以被视为技术债务,试图立即消除它是不切实际的。

您可以告诉 PVS-Studio 认为这些警告暂时无关紧要(为以后保留技术债务),并且它将不再显示它们。 分析器创建一个特殊文件,其中保存有关尚不感兴趣的错误的信息。 现在,PVS-Studio 将仅针对新的或更改的代码发出警告。 而且,这一切都是巧妙实施的。 例如,如果在源代码文件的开头添加一个空行,那么分析器就会明白,实际上什么都没有改变,并且将继续保持沉默。 该标记文件可以放入版本控制系统中。 文件很大,但这不是问题,因为经常存储它没有意义。

现在,所有程序员都会看到仅与新代码或更改代码相关的警告。 因此,正如他们所说,您可以从第二天开始使用分析仪。 您可以稍后返回技术债务,并逐步纠正错误并配置分析器。

这样,在大型旧项目中实施分析器的第一个问题就已经解决了。 现在让我们弄清楚如何处理技术债务。

错误修复和重构

最简单、最自然的事情就是留出一些时间来分析大量被抑制的分析器警告并逐步处理它们。 在某个地方你应该修复代码中的错误,在某个地方你应该重构以告诉分析器代码没有问题。 简单的例子:

if (a = b)

大多数 C++ 编译器和分析器都会抱怨此类代码,因为他们实际上想要编写的可能性很高 (a==b)。 但有一个不言而喻的约定,并且这通常会在文档中注明,即如果有额外的括号,那么就认为程序员故意编写了这样的代码,无需发誓。 例如,在 PVS-Studio 诊断文档中 V559 (CWE-481) 明确指出以下行将被认为是正确且安全的:

if ((a = b))

另一个例子。 这段C++代码中是否忘记了? 打破 或不?

case A:
  foo();
case B:
  bar();
  break;

PVS-Studio 分析仪将在此处发出警告 V796 (CWE-484)。 这可能不是一个错误,在这种情况下,您应该通过添加属性给解析器一个提示 [[失败]] 或者,例如, __attribute__((失败)):

case A:
  foo();
  [[fallthrough]];
case B:
  bar();
  break;

可以说这样的代码修改并没有修复bug。 是的,这是事实,但它做了两件有用的事情。 首先,分析仪报告消除了误报。 其次,代码对于参与维护的人员来说变得更容易理解。 这非常重要! 仅此一点,就值得进行一些小的重构,以使代码更清晰、更易于维护。 由于分析器不知道是否需要“break”,因此其他程序员也不清楚。

除了错误修复和重构之外,您还可以专门抑制明显错误的分析器警告。 可以禁用一些不相关的诊断。 例如,有人认为警告毫无意义 V550 关于比较浮点/双精度值。 有些人将它们列为重要且值得研究的[7]。 哪些警告被认为是相关的,哪些是不相关的,由开发团队决定。

还有其他方法可以抑制误报。 例如前面提到的宏标记。 所有这些在文档中都有更详细的描述。 最重要的是要明白,如果你逐步、系统地处理误报,那么它们并没有什么问题。 绝大多数无趣的警告在配置后就消失了,只剩下真正需要仔细研究的地方和代码中的一些更改。

此外,如果出现任何困难,我们总是帮助客户建立PVS-Studio。 此外,在某些情况下,我们自己消除了错误警告并纠正了错误[8]。 为了以防万一,我决定提一下,这种扩展合作的选择也是可能的:)。

棘轮法

还有另一种有趣的方法可以通过消除静态分析器警告来逐步提高代码质量。 最重要的是,警告的数量只会减少。

如何在遗留项目中实现静态代码分析器而不影响团队积极性

记录静态分析仪发出的警告次数。 质量门的配置方式是现在您只能输入不会增加操作次数的代码。 因此,逐渐减少警报数量的过程是从调整分析仪和纠正错误开始的。

即使一个人想作一点小作弊,并决定通过改进旧的第三方代码而不是消除新代码中的警告来通过质量关卡,这并不可怕。 尽管如此,棘轮朝一个方向旋转,缺陷的数量会逐渐减少。 即使一个人不想修复自己的新缺陷,他仍然需要改进相邻代码中的某些内容。 在某些时候,减少警告数量的简单方法就会结束,而真正的错误将会得到修复。

Ivan Ponomarev 在一篇非常有趣的文章中更详细地描述了这种方法“在流程中实施静态分析,而不是用它来查找错误”,我建议任何有兴趣提高代码质量的人阅读该书。

文章作者也有关于这个话题的报告:“连续静态分析".

结论

我希望读完这篇文章后,读者能够更加接受静态分析工具,并愿意将它们应用到开发过程中。 如果您有任何疑问,我们随时准备着 请教 我们的静态分析仪 PVS-Studio 的用户并帮助其实施。

对于静态分析是否真的方便和有用还有其他典型的疑问。 我在《开发过程中引入PVS-Studio静态代码分析器的原因》一书中试图消除大部分疑虑[9].

感谢您的关注并前来 下载 并尝试 PVS-Studio 分析仪。

附加链接

  1. 安德烈·卡尔波夫。 如何快速查看 PVS-Studio 分析器为 C 和 C++ 代码生成的有趣警告?
  2. 维基百科。 赖斯定理.
  3. 安德烈·卡尔波夫,维多利亚·哈涅娃。 使用机器学习进行程序源代码静态分析.
  4. PVS-工作室。 文档。 附加诊断设置.
  5. 安德烈·卡尔波夫。 使用 EFL Core Libraries 示例的 PVS-Studio 分析器的特征,误报率为 10-15%.
  6. PVS-工作室。 文档。 分析仪消息的批量抑制.
  7. 伊万·安德里亚辛。 关于我们如何测试 X 射线血管内手术教育模拟器项目的静态分析.
  8. 帕维尔·叶列梅耶夫,斯维亚托斯拉夫·拉兹梅斯洛夫。 PVS-Studio 团队如何改进虚幻引擎代码.
  9. 安德烈·卡尔波夫。 在开发过程中引入静态代码分析器PVS-Studio的原因.

如何在遗留项目中实现静态代码分析器而不影响团队积极性

如果您想与英语读者分享这篇文章,请使用翻译链接:Andrey Karpov。 如何在遗留项目中引入静态代码分析器而不会让团队泄气.

来源: habr.com

添加评论