关于辩论有很多强烈的意见,但显然这实际上不是意见问题,而是事实问题。因此,我们应该研究实证研究。从中得到的证据很明显:
是的,静态类型是值得的权衡-而不仅仅是一点,但实际上基本。实际上,有确凿的证据表明,静态类型化可以将代码中的错误数量减少至少15%(这是一个低估计,实际百分比几乎肯定会更大)。这是一个令人震惊的数字:我想即使是大多数支持静态键入的人也不会想到它产生了如此巨大的变化。
考虑一下:如果有人告诉您,有一种简单的方法可以在一夜之间将项目中的错误减少15%,那应该很容易。1 这几乎是众所周知的银弹。
证据是文件中提出要键入或没有键入:量化在JavaScript中检测的错误由征稿,基督教伯德和伯爵T.巴尔。我鼓励大家阅读它,这是一篇写得很好的论文,展示了杰出的研究成果。
很难简单地总结出作者进行的分析的严格程度,但这是一个(非常粗糙的)概述:
TypeScript和Flow是基于JavaScript的两种编程语言,在保持其他兼容性的同时,还添加了类型提示和静态类型检查。这允许按类型扩充现有代码,然后进行类型检查。
研究人员从GitHub收集了用JavaScript编写的开放源代码项目,查看了已解决的错误报告,并尝试将每个报告的错误减少为一段代码,这些代码将由TypeScript或Flow的静态类型检查器捕获。这使他们能够估计可以通过使用静态类型修复的错误百分比的下限。
研究人员采取了严格的预防措施,以确保他们的分析不会将与类型无关的错误视为与类型相关。2
与以前的研究相比,这项新研究具有特殊的优势:
- 静态类型与动态类型具有直接的比较,几乎没有混杂因素,因为JavaScript和TypeScript / Flow之间的唯一区别是类型。
- 他们通过检查TypeScript和Flow(即不同的类型系统),并由不同的人员重现(手动)类型注释来修复错误,从而跨多个维度执行复制。他们在来自不同项目的大量代码库中执行此操作。
- 本文测量了静态类型对可修复错误的直接影响(而不是一些模糊的质量)。
- 作者定义了一个严格的模型,用于预先衡量什么以及如何进行度量。此外,它们的描述非常清楚,并且易于分析缺陷(当研究论文向攻击开放时,总是很好的:如果没有攻击设法削弱其论点,则结果会更强)。3
- 他们执行适当的功效分析,以使他们的样本量足够,并且随后的统计分析是不透气的。
- 他们过于保守,以排除混淆的解释,仅测量单个活动部分。此外,他们通过包含类型将分析范围限制为可立即修复的错误,并排除可能需要进行更高级重构以容纳类型的所有错误。因此,实际上,效果似乎要大得多,但肯定不会比他们报告的小。
- 最后,他们并没有发现什么微小的影响,而是一个了不起的区别。尽管他们的程序过于保守,但即使在95%置信区间的低端,他们仍然发现至少有10%的错误会通过最少的附加类型检查而消失。
除非该文件中存在尚未有人发现的根本缺陷,否则该文件将最终显示出静态键入的巨大好处,而几乎没有任何成本。4
从历史上看,关于编程中的类型学科的研究起步艰难,因为长期以来,证据还不清楚。这样做的原因是,进行系统的实验以检查静态和动态类型的影响并不容易:系统的实验必须隔离我们正在研究的影响。不幸的是,由于打字规范与编程语言相关,因此我们无法隔离打字规范的效果。
实际上,有一些编程语言允许在不同的方言中进行静态和动态键入(例如,带有Option Strict
On
或的VB Off
或静态键入的Lisp)。但是,它们并不适合直接比较,最重要的是,因为不存在允许直接比较的现有足够大的代码库。充其量,我们可以在“实验室设置”中对它们进行比较,在这种情况下,测试对象可以以静态或动态类型的语言变体随机地解决任务。
不幸的是,这些人为编程任务无法很好地模拟实际使用情况。特别是,它们中的许多范围较小,可以解决定义明确的问题,该问题可以总结为半页文本。
幸运的是,这是过去的事情,因为TypeScript,Flow和JavaScript确实是相同的语言(除了静态类型),而且还有大量的实际代码和错误数据集可供选择。
1受到原始论文引用的启发。
2我对此并不完全满意:静态类型语言的主要优势之一是表面上与类型无关的问题可以用可以进行静态类型检查的方式来表述。这将许多逻辑错误转换为类型错误,从而大大提高了静态类型可以捕获的错误的比率。实际上,该论文对与类型无关的错误进行了粗略分类,我认为,其中很大一部分实际上可能是由静态类型捕获的。
3我邀请任何人,尤其是动态类型的支持者,尝试找出分析中未解决的缺陷。我认为并没有很多(如果有的话),并且我相信没有潜在的缺陷会实质性地改变结果。
4我怀疑在实际的大型项目中静态键入的实际成本是不存在的,因为它随后成为体系结构的自然组成部分,甚至可能简化规划。修复静态类型错误需要花费时间,但比以后发现的错误要少得多。对此已经进行了广泛的经验研究,并且已经知道了几十年(请参见例如Code Complete)。