UML软件工程组织

“寻找圣杯的任务”——度量软件之美
作者:苏丽辉 杜玄出处:程序员

 “当你能够测度你所说的并将其用数字表达出来,你就对它有了一些了解;但当你不能测度,不能用数字表达它时,你对它的了解就很贫乏.你在思想上还远没有进入科学的阶段” ——Load Kelvin

  软件质量判定遇到的问题

  判断和衡量代码质量一直是开发过程中令人苦恼的问题,在同样完成功能的情况下,如何判别一种写法比另一种写法好呢?在代码重构的过程中,如何确定代码质量是在不断的改进当中呢?引入一种设计模式以后,代码真的变的比以前好了吗?

  大部分时候我们凭感觉和经验做这些事情,我们使用很多模糊的词语来描述我们的判断,比如这样做以后,代码的可维护性更好,可扩展性提高等等。在越来越注重代码设计的今天,很多人开始使用更感性化,更形而上学的词语来形容软件质量,我们会听到评价软件结构
很优雅,带来美的享受,甚至一些设计原则被提升到了哲学高度,:)。

  不得不承认这些词语的描述确实很符合我们看到一段高质量代码的心境,但是这些新词语的出现并没有帮助我们解决软件质量判定中遇到的问题,因为这些感性的判定,由于每个人的经验不同,经历不同,所得出的结论也不尽相同。

  软件度量能解决的问题

  众所周知,度量对任意一个工程产品研制都是很重要的,度量让人们更加 了解产品,可以评价产品,衡量产品质量从而进行改进。对于软件产品也一样,只有定性的评估是不够的,只有通过定量的评估才可以根本的解决评估软件产品质量这样的问题。然而,软件产品的度量却非常困难,对它的测量可能永远无法做到和物理产品一样的完美,但是,软件测量仍然具有重要的意义。

  要度量软件质量,首先需要定义软件质量要素,比如,软件的功能性(functionality)、可用性(usability)、可靠性(reliability)、性能(performance)和支持度(supportability)都衡量软件质量的要素。不过,要真正定量的从技术上度量这些要素,就是非常困难的了。

  软件度量工作首先需要确定能够表示软件质量的各种属性和指标;然后,分析软件,收集数据;接着运用公式换算代码的各种指标值;最后,通过这些指标就可以分析代码的质量。确定哪些属性和指标可以表示软件质量,收集哪些数据,如何用公式推导指标,都是软件度量这门科学的研究重点。它所确定的各种软件度量指标为我们了解软件属性,衡量软件质量提供了科学的依据。

  软件度量经历了几十年的发展,在软件的各个方面和领域都开发出了各种度量套件。有针对分析模型的度量,体系结构设计的度量,构件级设计的度量,界面设计的度量,以及源代码级的度量等等,要了解这些度量套件如何进行质量测量可以参考相关的资料。不过,这些度
量套件并不是都具备实际的操作意义,有些度量就太复杂不可操作,或者脱离实际很难理解。但是也有一些度量套件具备很实际的指导意义。本文打算介绍的构件级度量套件和源码级度量套件都是很有意义的。

  软件度量可以帮助我们理解软件属性,衡量软件质量,但是,软件度量并没有真正的去测量软件质量,而是测量软件质量的表现,因此,仍然需要我们去分析确定所测量的指标和软件质量的准确关系。

  构件级和源码级的度量

  构件级的软件度量集中评价软件构件的特性,它主要包括3C测量,既:内聚度(coheion),耦合度(coupling),和复杂度(complexity),这组测量指标贴切的描述了构件设计质量,我们也能看出各种设计模式和设计原则都在想办法平衡这些元素。

  内聚度和耦合度可以通过考察构件的输入,输出参数的性质和个数,全局变量,被调用模块的个数(扇出),调用的外部模块数(扇入),得出测量数据。分析公式就不列举在这里了,公式的大概含义是如果一个模块有少的输入参数,且都是数据型的参数,没有访问全局数
据,被单一的模块调用,可以预计这个模块将有低的耦合度。关于复杂度还有一个著名的测量指标——环复杂度,它基于构件控制流图进行分析。

  源码级的软件度量主要评价代码复杂度,Halstead测量套件被称为“最著名和研究最完全的软件复杂度复合度量之一”。它通过研究源代码中的操作符和操作数,开发出了一系列指标,可以描述代码的实际体积,开发工作量,开发时间,甚至软件中被预测的错误数。 很多软件测量工具都提供象耦合度,环复杂度,Halstead测量套件,扇入扇出数,等指标的自动统计,透过这些指标,我们可以掌握代码的内部特性,分析每次代码改动对代码质量的影响。一些停留在定性描述上的质量改进,完全可以通过数据得到印证。比如某部分代码采用设计模式以后提高了内聚力,降低了耦合度,某块职责众多,特别复杂的代码被拆散,所拆出的各个模块的复杂度都很低,易于维护。那么通过度量数据一定可以反应出这些特性,比如,源码级的复杂度指标降低,构件级的耦合度指标降低等等。

代码实践

  下图展示了两段相同功能的代码,在重构前后的结构示意图。

 

  ProfileConf直接使用了第三方SNMP协议包,而ProfileConfNew则使用了封装后的SNMP协议软件包。进行协议封装的目的一是为了隔离第三方软件包,另一个目的是为了简化客户端使用SNMP协议栈的操作。改造完成后,我们使用Together自带的软件测量工具进行了数据测量。选择Together菜单中tools——>metrics,里面提供了大量的测量指标。


 
   我们选择了几个比较关注的指标,对新旧代码进行了测量,下面是测量结果。

 
   下表对测量指标做简单说明。



    通过数据可以看出,改进以后,编写的代码有所减少,大约节省三分之一的代码;耦合度有所降低,但并不是特别明显,因为我们把对第三方协议包的依赖转为对自己编织的协议包的依赖了;代码复杂度大大降低,这是因为我们自己编写的协议包更符合实际使用情况,因而使代码编写难度大大降低,非常容易学习,修改和维护。数据说明了一切。

  总结

  软件度量最终的目标是要提供统一衡量软件质量的标准,并促使软件质量的不断提高,这项任务被人称为是“寻找圣杯的任务”。但是,无数的科学事实都说明,如果因为目标太难达到就不作任何工作,就不可能有任何进步。在达到最终目标之前的过程中,会有很多有益的
小发现,这些发现又在不断促进新的发现,最后使不可能变成可能。

  软件度量科学的发展同样在追求最终目标的过程中为我们带来了众多的有益发现,让我们用更加科学和严谨的态度来看待软件质量问题;让我们对代码的认识从定性描述阶段,进入到定量描述阶段;让我们感受到科学和美学的统一所展现出的巨大魅力。

 

版权所有:UML软件工程组织