除了修正缺陷以及记录实现的具体步骤,开发人员还应该对bug进行进一步的分析。这次分析应该着眼于导致bug产生的开发情景。
在线程同步的例子中,开发人员不应该仅仅记录增加了一个调用来释放 mutex(注:Mutal Exclusion = 互斥锁,保证了共享数据不会同时被多个线程访问,只向一个线程授予对共享资源的独占访问权)。反之,开发人员应该找出没有释放mutex的原因。假设分析的原因是:因为需要同步的方法超过一个的返回点,因此开发人员在某些控制路径上忘记清理代码。
这一类简单的分析实际带来了非常大的价值。不同于记录具体问题的具体解决办法,我们现在有了可以解决许多情况的经验,有些情况甚至并不涉及到线程同步和释放mutex。但是,分析过程并没有结束,我们需要进一步的分析来将收集的所有数据转换为实践,从而帮助在将来避免类似bug的发生。
(3) bug预防分析
分析的最后一步就是寻找一个预防类似错误的方法。这一方法不仅涉及到开发、QC工程师,还涉及到不直接负责代码编写的资深开发人员。
这一阶段的成果是一些有用的实践经验,开发人员可以通过这些实践预防bug而不是修正bug。这些实践不应该是某个具体问题的解决方案。在我们线程同步的例子中,可能得到这样一个实践:是否有审计范围机制来获取和释放资源?这种实践 (不一定适合所有编程语言)可以指导开发人员用一个类(class)封装资源, 这样构造(constructor)函数容易分配和而与析构(destructor) 函数释放资源。如果遵守这样的约定, 当程序结束这方法时,不管控制路径是怎样的,资源(上述例子中获得的mutex)总能被释放。
Bug预防分析是整个bug分析过程的核心。这一阶段总结出的实践可以在更广泛的范围内预防潜在的缺陷。由于分析结果的广泛应用性,分析某个具体问题的投入将很容易被收回。
非常重要的是我们前面所举的例子是一个随机性的bug。开发人员由于疏忽而忘记了释放资源。在代码实现时,这样的bug是随机产生的,但是类似bug产生的几率却非常高。所以,尽管这一类bug是随机的,但仍然可以被预见并防止发生。
(4) 发布经验
分析得出的实践经验应该被记录并发布,这样其他的开发人员就可以通过学习这些经验避免类似的错误。一个发布经验最好的办法就是知识库。这将使得新的知识在组织内流动并被相关的开发人员所学习。
如果不将分析结果传达给组织内相关的其他人员,那么分析的目的就没有达到。避免下一个bug出现的唯一办法就是让开发人员知道如何避免它,并鼓励他们这么做。
Bug分析实例
让我们研究另外一个例子,以便更好地理解bug分析的益处。在这个事例中,QC工程师进行了如下的操作:当输入一个长字符串到应用程序时造成其崩溃(crash)。这一结论本身就需要一定程度的分析,但这个QC工程师并不满足于这样的分析,进一步研究了相关的代码,发现crash的原因是输入字符串时的处理有问题。其中一个步骤是将输入的字符缓存在一个固定大小的数组中,而这个数组有时候显得太小了。
和线程同步的例子一样,QC工程师的初步分析带来了很大的价值,开发可以更容易的发现和修正这个bug。此外,记录缺陷的真正原因而不是表象,将帮助其他人避免类似的bug。
接着,开发人员开始修正这个bug。当修正的时候,她不仅记录了解决措施,并说明了导致缺陷产生的原因。在这个例子中,造成bug的原因是在操作未经处理的C/C++缓冲区时,没有经常检验缓冲区的大小是否不够。然而,这个结论甚至可以被进一步总结为更广泛应用的经验以便帮助开发人员在以后避免类似的缺陷发生。所以,在分析的最后阶段,开发人员在组内更资深的开发人员的帮助下,得到了下面的实践经验:避免使用未经处理的C/C++缓冲区,尽量使用安全的collections和strings,如标准模版数据库中提供的可用 collections和strings。这样就完全可以避免前面发现的这个bug。
益处
Bug分析带来了很多的好处。第一个好处就是帮助产生错误的开发人员总结经验,并使他在将来避免类似的错误。有时,只修正一个具体的bug而不去分析它产生的原因并不会帮助在日后得到提高。在这种情况下,只有深入分析和资深开发人员的指导才能使开发人员成长和提高能力。
原文转自:http://www.uml.org.cn/Test/200611295.htm