基于软件度量的函数提取重构初探
2017-09-08冯燕肖笛
冯燕+肖笛
摘要:本文从软件度量的角度分析了可被实施函数提取重构的代码序列特征,并提出了一种基于软件度量的函数提取重构方法。
关键词:度量;代码重构;方法提取
中图分类号:TP311.53 文献标识码:A 文章编号:1007-9416(2017)06-0254-01
软件开发开发是一项智力活动,而且不同于一般的实体产品,软件在开发过程中甚至在完成之后,仍会面临客户的需求变更。变更将导致软件的修改。因此,随着软件开发的深入推进,随着软件系统的演化,软件结构也会越来越复杂。重构是一种通过对代码结构进行修改,能够有效改善代码质量的行为。对软件代码中某些函数复杂臃肿的函数进行函数提取重构,分解函数功能,降低函数复杂性,是一种提高代码质量的有效手段。
1 函数提取重构的模型
1.1 函数提取重构基本概念
函数提取重构是软件开发中最常用的重构手段之一,是指从已有代码序列中提取部分代码创建一个新的函数。函数提取重构通常发生在某个函数过长,或者包含多种不同功能的时候。在这些场景下,往往需要注释才能让人理解它的用途。在函数提取重构中,首先需要判断某个函数是否需要重构,可行性如何;然后,如果确定需要重构,则选取某些连续的代码片段;之后,创建一个新的函数,将所选中的代码片段提取到新函数中,并为新函数确定参数和返回值;最后,在原函数中的代码片段会被一个对新函数的调用所替代。虽然不连续的代碼片段也存在被重构的可能,但这种重构非常复杂,在实践中往往极少实施,本文也只考虑连续代码片段的重构。函数提取重构有多种好处:首先,减小函数粒度,增大函数的可复用性;其次,使得处于代码高层的函数代码简单易懂;此外,单一功能且细粒度的函数的理解和维护都会容易些[1]。
1.2 函数提取重构的可行性分析
重构的基本目的是使代码更易于理解和维护。除此之外,函数提取重构的目的还包括增加代码的可复用性,如果两个或多个不同的函数包含一段相似的代码,即可将这段代码提取为一个新的函数,在原来的代码中调用新函数。因此,我们总结了适用于函数提取重构的一些场景:函数过长或控制结构过于复杂,导致阅读和理解困难;某个函数完成了两个或两个以上的相对独立的功能,这种情况下应该将对函数进行分解,将每个功能对应的代码提取成一个函数,使每段代码的含义更加清晰,增加了代码的可复用性;多个函数具有相似或相同的代码序列,这种情况可以实施函数提取重构提高代码复用性。
函数提取重构的适用场景也是有限制的,需要满足某些特定的抽取条件。一个基本条件是被提取的代码都位于同一个函数内部,不能起始于一个函数,终止于另一个函数,那样的重构会使程序出错。此外,之前所述的非连续代码片段,其重构也非常复杂。本文对函数提取重构的可适用代码片段进行了更严格的界定,认为满足以下条件的代码序列也不应该进行重构:代码序列中含有终止执行所在函数的代码,比如return语句、exit语句、panic语句等终止语句;代码序列中含continue、break等跳转语句,但跳转语句的目标在该所选择的代码序列之外;代码序列不完整的,例如开头或结尾含有注释但提取后注释不完整,括号被拆分等,这类重构会造成语法错误。
2 程序复杂性度量模型
函数提取重构的基本目的是便于软件维护,因此我们借鉴软件度量中可维护性指数的概念,提出了面向该重构的程序复杂性度量模型,用于判断某个函数是否需要实施函数提取重构。使用这个模型对软件系统中的所有函数进行检查,判断函数的可维护性,如果函数的可维护性过低,就认为该函数应该被重构。
MI公式中,g是指控制流图,avgV指程序的平均Halstead复杂度,Halstead复杂度用来测量程序操作的计算复杂度。如果一个程序一共有M个操作符与操作数并且有N个不同的操作符与操作数,则它的Halstead复杂度V被定义为V=M*。aveV(g)是指平均圈复杂度(Cyclomatic complexity),是对程序的各个独立的逻辑路径的测量,圈复杂度计算公式为V(G)=e-v+2p,其中,e表示控制流图中边的数量,v表示控制流图中节点的数量,p为控制流图的连接组件数目(图的组件数是相连节点的最大集合)。aveLOC是平均代码行数。PerCM是平均注释行数的百分比。MI指数值的范围是从0到100。微软在其Visual Studio工具中定义为值在20到100之间是高可维护性,10到19之间是中等可维护性,0到9之间是低可维护性。我们沿袭这个标准,认为低可维护性的函数都是需要重构的,中等可维护性则由开发者自行决定是否需要重构。
3 函数提取重构方法
3.1 待提取语句序列分析
为了实施重构,我们首先要对待提取语句序列进行分析,其中最重要的是获取重构后新函数的参数和返回值。我们为待提取的语句序列构建抽象语法树,然后对该抽象语法树进行控制流和数据流分析,获得该语句序列中所有的变量声明和使用情况。抽象语法树(AST,Abstract Syntax Tree)是程序的一种中间表示形式,它是源代码的抽象语法结构的树状表现形式。树上每个节点都表示源代码中的一种结构。通过对变量的定义引用对分析,我们分别得到待提取语句序列的入口处变量和出口处变量,它们分别作为重构后新函数的参数和返回值。全局变量既是参数也是返回值[2]。
3.2 局部变量分析
为了对局部变量进行深入分析,我们将待提取的代码序列分为四种情况:第一种是不含有局部变量;第二种是含有局部变量,但仅仅是被使用;第三种是含有局部变量,但仅仅是进行赋值;第四种情况是第二和第三种情况的综合,即包含了局部变量,且局部变量在代码序列中既被使用又被重新赋值。
3.3 重构后评价
在进行方法提取重构后,我们还需要对重构进行评价,判断程序结构是否得到了改善。从直观上看,原函数和新函数各自的代码显然都会比原有函数的代码少,因此,单个函数对比,每个函数都变得更简单,粒度更细,单个函数的结构得到了改善。当然,由于一个函数变成了两个甚至多个函数,总的代码量可能会增加,原有的代码局部性可能也会被打破。为了对重构进行客观的评价,我们同样可以使用软件度量的方法进行评估,例如,通过计算代码行数、圈复杂度、Halstead复杂度等。通过度量的计算,我们能够对重构前后软件的复杂度、内聚度和耦合度等特征做出更客观的判断,从而为是否实施重构做出合理的选择。
4 结语
综上所述,基于软件度量的函数提取重构可以对代码序列的复杂性和可维护性做出客观的判断,实施重构后能够简化复杂代码,或者使得功能交错的函数得到分解,有利于开发者对软件的理解和维护。
参考文献
[1]刘伟,胡志刚,刘宏韬.单例模式导向的源代码自动重构研究[J].小型微型计算机系统,2014(12):2664-2669.
[2]林治.软件重构在软件开发过程中的作用分析[J].扬州教育学院学报,2007(3):21-24.
Abstract:from the point of view of software metrics, this paper analyzes the feature of code sequences that can be extracted and reconstructed by function, and proposes a method of function extraction and reconstruction based on software metrics.
Key Words:metrics; code reconstruction; method extractionendprint