水星探索项目中一段Fortran代码里的逗号被写成了点号,影响了运算的准确性,导致太空探测器无法到达更远的轨道。出现这种事情的几率有多大?一种编程语言的设计在多大程度上会影响程序正确性和导致相似的事件?最近发表在第四届International Workshop on Evaluation and Usability of Programming Languages and Tools上的一篇论文中,我展示了一些研究发现:通过往由各种不同语言编写的类似程序中随机的制造一些干扰信息,看编译器或运行系统能否发现由这些干扰引起的错误,或者最终导致了程序输出了错误的结果。
在由我和我的同事 Vassilios Karakoidas、Panagiotis Louridas共同指导的这项研究中,我们首先选择了10中流行的编程语言,以及用它们写出的一批程序。我们选择这些语言的条件是基于一篇IEEE Spectrum文章里提供的数据(由软件研究公司TIOBE建立的一个索引目录)、出现在Powell’s Books书名中的数量、IRC在线讨论中引用的数量,以及Craigslist中招聘职位的数量。在这样一个流行语言的大集合中,由于一些可操作性的原因,部分语言被排除在外。根据流行度索引,这个集合大概能覆盖所有语言的71%到86%。
然后我们从Rosetta Code wiki中寻找我们研究的这10种语言写成的执行相同任务的各种源代码。用Rosetta Code这个网站的创办人自己的话,这个网站的目的就是搜集用不用的各种语言来完成同一种任务的代码,展示它们的相似和不同,帮助那些研究基础工作的人了解问题的另一种解决方案。
我们的下一步是要制造一个代码干扰器:一个能系统的往代码里随机引入各种随机混乱的工具。干扰器能替换标志符,把一些数字加一,随机改变字符或把字符串替换成相似的东西或随机的串。最后,我们把干扰器应用到我们搜集的代码里,检查这些被修改后有错误的代码是否能被编译器或运行环境检测到,或是否导致了错误的输出。
理论上,我们人工引入的这些错误是模拟现实生活中的很多具体表现。错误拼写——“胖手指”——就是一个很常见的例子。另外的场景包括马虎大意,自动重构错误(特别是在像C和C++这些语言里,自动重构是很难正确无误的实现的),复杂的编辑器命令导致的意外失误,或搜索-替换操作造成的错误,甚至还包括猫踩着键盘上产生的后果。
总计我们一共测试了136个任务实现,尝试了2万8千种干扰操作,其中成功的有261,667 (93%)个。被干扰的程序中有90,166 (32%)个编译通过或语法上没有发现异常。60,126 (67%, 或 总共被干扰的数量的23%)个能正常的结束运行。 18,256个输出了完全无异的结果,表明干扰没有对程序产生任何影响。其余的,41,870 个程序 (能运行的70%, 总数的16%)编译和运行都没有问题,但输出了结果错误。
上图显示了对各种语言的统计结果,是按失败情况统计:成功的编译或执行,没有捕获程序中的错误,导致输出了错误的结果。上图验证了我们一些非常直觉的看法。强静态类型语言(Java, Haskell, C++)比那些弱的或动态类型语言(Ruby, Python, Perl, PHP, 和 JavaScript)能在编译器捕获更多的错误。稍微有点意外的是,C语言出现在了中间位置,验证了一个被很多人相信的观点:C语言的类型系统并不像它的众多追随者(包括我)认为的那样强。然而,C语言在运行期却抛出了大量的错误,导致最终它的不正确输出结果的比率跟那些强类型语言的相似。
这还有一副类似的统计图,统计的是运行时各种语言的表现。同样,相比起强类型语言,弱类型语言更倾向于仍能无异常(崩溃或抛出异常)的运行。根据这两个统计表可以看出,弱类型语言在输出结果上将会有更高的错误率。相比起C++或C#,PHP的错误率是36%,而C++的是8%,C#是10%,用像PHP这样语法上不是很严格的语言写成的应用,虽然充分利用了这些弱类型语言带来的方便性,但不经意的拼写错误也会很容易溜进产品代码里。总的看来,动态脚本语言跟强静态类型语言比起来差距很大。这可能是我们只在较高层面测试这些脚本语言特征有关。
我们对这些数据做了进一步分析,发现了下面一些事情。
- 这些在静态语言和动态语言干扰测试对比结果在统计学上有重要意义。这验证了静态语言比动态语言更容易发现错误。
- C#的表现更像C和C++,而不是Java,尽管它外观上跟后者更相似。
- Haskell 的表现跟Java很相似。
- 统计数据显示在静态类型语言间被干扰表现有明显不同,比如C和C++间,C++和Java间,Haskell和Java间等。然而,动态语言间却没有一个可比较的模式。借用托尔斯泰的一句话,它们看起来各有各不同。
然而,我想我们的研究最重要的成果是,通过对具有可比性的语言进行干扰测试,提供了对编程语言的设计进行评价的数据资料。
译文链接:http://www.aqee.net/programming-languages-vs-fat-fingers/