Watts New - 关于bug,你可能忽略的事(编者按)
bug是软件的伴生品,依Humphrey的经验来看,即使是身经百战的程序员,其bug注入的比例大约是千行代码100个,如果程序员的编码经验并不丰富,或熟练程度不高,这个比例便会变得更大。
既然有bug不可避免,就要寻找和修复。因为资源有限,我们不可能发现和修复软件中的所有bug,因此我们会“策略性”地选择一些严重的bug,放纵一些轻微的bug,这便是大家普遍会做的bug分级制度。
那么问题来了,何为“严重”,何为“轻微”?即使我们有基本共识,也仍然存在非常大的分歧。
如果bug会致死致伤或引发财务问题的,那肯定是严重的。而诸如不方便、不高效或引起麻烦这种的,就明显依赖于个人的主观判断了——如果你就是那个频频遭受不方便的倒霉蛋,你便会认为这严重;如果你是这个软件的开发者,不方便没有造成客户抱怨和流失,也没有威胁到业务基础,你就不会觉得严重。
我们不仅没法从bug的影响上来统一衡量bug的严重程度,也无法从bug的产生来判断其严重程度。在Humphrey的经历中,一些看似琐碎的缺陷却产生了戏剧性的后果。比如对于制造行业某公司来说,最昂贵的三个bug是一行被省略的代码,两个命名中互换的字符和一次不正确的初始化。这三个缺陷都导致了百万美元的损失。
既然“轻微”也未必“轻微”,我们便不能小瞧任何一个bug。在英文中,“bug”有“小毛病”的意思,因此相较于“defect”会被轻视。而在我们的语言环境中,不太会区分“bug”和“defect”,所有的bug都是defect,反而有利于我们正确的对待每一个缺陷。
既然要认证对待每一个bug,是不是bug分级就没了意义呢?答案显然是否定的。
划分缺陷影响程度的重要依据是质量策略。也就是说,什么样的影响算严重,取决于公司在乎什么。在这一点上,每家公司的质量策略很难完全一样,因为它取决于多方面因素的共同作用——如法律法规、行业规约、客户需要,以及企业自身的发展策略。而控制缺陷的引入需要规范编码。这方面最有效的做法是结对编程,而最普遍的做法是使用代码扫描工具。
还有一点值得一提,大多数工程师认为找缺陷是测试的责任,这个观点并不正确。
因为即使在有很多缺陷的情况下,软件也仍然能通过大量的测试。想要消灭所有的bug只能穷举,即测试所有的逻辑分支和条件。Humphrey曾测试过一个只有59行代码的微小程序。一次穷举测试需要67个测试用例,368个路径测试和共计65536个数据值。在小型软件上这么做尚且不具实操性,就更不要提大型软件了。
下图是一份来自喷气推进实验室(这个组织为NASA探索太阳系研发航天飞机)的数据——系统测试发现的缺陷累计。这些软件系统大约都有2万行代码,并且每一个的系统测试时间都超过2年。下图的三个航天飞机系统测试每周发现的累计缺陷从每千行6.5个到9个不等,且无法确保所有缺陷都已被发现。

这幅图不应被视为对喷气推进实验室的批评。他们有用技术高超且遵守开发纪律的程序员,却还是无法找出所有的bug。因此,解决缺陷的思路不是向后看的测试,而是向前看的编码。我们在文章《如何从源头,遏制软件缺陷的引入》中就提到缺陷的引入从需求开始,测试能做的有限。
发表时间:1999年3月
编译:冯信