代码中的bug与什么有关?代码行数?项目规模?还是开发者的数量?在本文中,我将根据机器学习模型绘制的图形告诉您许多错误的来源!以下为译文:我们怎样才能减少软件中的错误?这篇文章将告诉您传统观点是错误的,而以下统计数据会让您大吃一惊。软件开发人员普遍认为,代码量越大,错误越多。虽然很多人不是很清楚这两者之间的确切关系,但他们认为两者之间是线性关系,即每千行代码中的bug数量与代码量成正比。然而,根据对GitHub中100,000个代码存储库的研究,代码行数和错误之间的这种恒定关系并不存在。此外,代码行数并不是错误数量的可靠指标。注:在本文中,我使用“bug”来指代从用户角度来看软件中的一些异常行为,例如:崩溃、视觉异常、数据不正确等。“Bug”也常用来描述一个软件中的可利用缺陷,但这是从黑客的角度来看的。本文不涉及安全漏洞,因为安全漏洞可能需要其他模型来分析。相反,我们发现了两个更可靠的指标:贡献代码的开发人员数量和代码提交数量。这篇文章中的图片使用了一个有两个变量的模型,这个模型预测的错误数量几乎和我的另一个有16个变量的模型一样。我将详细解释这些模型的建模过程,但首先:如果存在这样的因果关系,这对减少错误意味着什么?如果您想要可靠的软件,请不要使用会产生错误的方法。比如Agile提倡直接写代码,然后通过迭代这些代码来优化需求,所以会产生很多提交(提交的数量和bug的数量密切相关)。原型可以减少错误,但是当你用完这些原型时,你必须扔掉它们。您进行几次提交以了解技术和客户的需求,然后编写一个提交次数较少和/或团队规模较小的非原型版本。刻意维护系统可靠性的努力可能会产生相反的效果。在测试驱动开发和单元测试的情况下,如果代码提交的数量,或者开发人员需要的数量,那么bug的数量也会如此,这可能有悖于你的直觉。就个人而言,你应该把时间花在写代码以外的事情上,比如思考、设计和原型制作。对于企业来说,他们雇佣的开发人员越少越好,当然开发人员越有经验越好。数据收集首先,我通过GitHubAPI查询了10万个项目(star数超过135的项目)。这些项目不是随机抽样,它们代表了GitHub高端的0.1%,所以我们更有信心很多人会发现并报告bug。对于每个项目,我提取了项目的创建日期(GitHub上的日期)、给予的星数、问题数、提交的PR数以及问题跟踪器是否被禁用。接下来,我克隆了所有非私有存储库并直接从Git和文件系统收集了以下统计信息:对于每个存储库的HEAD信息,我收集了Tokei统计信息:代码行数、注释、空格等。然后,对于检测到的每个Tokei语言,我计算了总字节数和LZMA压缩字节数。总代码量前50行。排除的语言(文本和标记)显示为灰色(Text、Html、Markdown、Sg、ReStructuredText)控制流行度等差异我们预计,对于较旧和流行的项目,错误的平均数量会更高。为了控制这些和其他差异,我使用了以下模型:ln(issues)=β1createdage+β2firstcommitage+β3ln(stars)+β4ln(contributors)+β5ln(allcommits)+β6ln(code)+β7ln(comments)+1)+β8ln(pullrequests+1)+β9ln(files)+ε我通过这个模型做了拟合,通过10折交叉验证用线性回归测试了模型的拟合度,然后在组合图中预测绘制了每个折叠的错误。在此之前,我删除了所有私有、存档、镜像和分叉的项目、未启用问题跟踪器的项目以及数据集中零错误的项目。9变量模型的预测误差该模型有一些偏差,但在其他方面拟合得很好。对于问题数量较少(<10)的项目,它高估了GitHub上的错误数量(相反,它低估了问题数量较多的项目)。我怀疑是因为在github的api中没有标注fork出来的项目,有一些项目包含了第三方代码。这些项目用issue>ln(issues)=β1ln(code)+εln(issues)=β1ln(lzmabytes)+ε夸大模型,仅包含代码行或lzma压缩代码字节(考虑语言差异之间的代码密度)表现同样糟糕。用9个变量的模型拟合完整数据集给出以下近似值:ln(issues)=0.022createdage–0.017firstcommitage+0.315ln(stars)+0.071ln(contributors)+0.266ln(allcommits)+0.072ln(code)+0.034ln(comments+1)+0.413ln(pullrequests+1)–0.069ln(files)–1.690我们可以看到模型中的主要变量是PR数(0.413),给出星数(0.315)和提交数量(0.266)。将这两者与代码行数(0.072)和注释(0.034)进行比较,这些差异就更加明显了,尤其是考虑到变量还没有归一化,代码行数会高于几乎所有项目的PR。给星星或承诺。由于PR数和star数是GitHub特有的函数,所以我也搭建了一个没有这两个数据项的模型。然后根据拟合模型的系数,进一步简化为只包含提交代码的人数和提交次数。这个只有3个变量的模型的性能几乎和其他模型一样,也可以用3G图来展示:ln(issues)=β1firstcommitage+β2ln(contributors)+β3ln(allcommits)+β4ln(code)+β5ln(comments+1)+β6ln(files)+εln(issues)=β1ln(contributors)+β2ln(allcommits)+ε删除GitHub特定数据项后,提交代码的人数和提交占主导地位,删除所有其他变量时错误数量略有减少就证明了这一点。会不会是模型错了?既然我们知道代码提交人数和提交次数的影响,那么在没有任何根据代码提交人数绘制图表的模型的情况下,让我们看看代码行数和问题数量之间的关系和提交的数量。对于GitHub,绘制代码行数(x轴)与GitHub上的问题数(y轴),按提交代码的人数和提交次数分组。为了节省空间,我没有显示所有100k项。我是按照提交代码的人数和提交次数来分组的,因为我觉得这样分组最有意思也最有代表性。为了避免选择偏差,我只在选择分组后绘制。你只是看到一堆乱七八糟的点,对吧?没错:上图证实了代码行数和错误数量之间的相关性非常弱。请记住,图表是以对数方式绘制的,并且该模型使用ln(code)(代码行数的日志):因为相关性与代码行数成比例。随着代码行数的增加,错误的数量增长缓慢。我看到有人说每千行代码的错误数是0.5-50。但是我发现,得出这样结论的人只是研究了某个时间点或两个版本之间的1-2个成熟软件项目的代码。仅查看某个时间点的项目快照,您为什么会认为该项目在早期或后期阶段会保持不变?根据以上数据,假设错误数量与代码行数之间存在任何恒定关系是不明智的。相反,我们应该认识到,随着项目的成熟,错误数量的增长速度将会放缓。是什么原因?我认为:我们观察到频率的对数分布,而不是正态分布。一小部分错误被发现得更快、更频繁,而系统“长尾”中的错误被发现得更慢、更频繁。bug数与函数数有关,与代码行数无关,代码行数与函数数呈超线性分布。(随着项目的增长,添加新功能所需的代码行数增加。)项目的核心应该随着时间的推移变得更加稳定,因为我们修复错误但不进行重大更改。随着项目的成熟,新来的开发人员不太可能更改关键代码,并且新功能的开发需要更少的核心更改。那么什么是不是问题的错误和不是错误的问题呢?对于这种规模和范围的研究,GitHub问题是我所知道的最好的错误记录形式。自动错误检测软件只适用于部分语言,只能检测“结构性”错误(如无效的内存访问),而不能检测逻辑错误(如计算错误),手动错误计数的数量不切实际(或根本不可能)。我们必须假设未解决的问题代表用户遇到的错误数量。离群值和备选假设在查看这些数据之前,我没想到仅凭错误数量就能预测错误数量。这表明项目的开发人员数量包含有关该项目的大量其他信息。一个合理的解释是“大型开发团队有向均值回归的趋势”:即随着团队中开发人员数量的增加,项目的提交/功能/代码行数与数量的比值开发商的价值趋于平均值。随着开发人员数量的增加,代码行的范围会缩小。在浏览异常值时,我遇到了一个特别有趣的类别:控制台模拟器。这类软件有测试输入(游戏)、测试者(游戏玩家)和其他实现(其他模拟器和系统本身)等数据,可以为以后软件错误计数的比较研究提供一个更可控的实验环境。
