基于图表示学习的代码异味强度排序模型

2023-12-13 01:39王书涵陈军华高建华
小型微型计算机系统 2023年12期
关键词:开发人员异味度量

王书涵,陈军华,高建华

(上海师范大学 计算机科学与技术系,上海 200234)

1 引 言

随着软件设计各类需求变化日渐多样,软件的规模和复杂性显著增长.面对持续的变更请求、严格的截止日期等挑战,开发人员有时不自觉向源代码中引入了不理想的设计,使得最终呈现的代码结构违背了软件工程的某些原则.这类设计缺陷会使得软件更容易出错,且后续会更加难以维护[1,2].软件重构是解决这一问题的有效方案[3].软件重构是指在不改变代码外部行为的同时实现对软件内部结构的修改[3],其目的是提高代码的可读性或通过改变代码的结构和设计,使其在将来容易维护.

软件重构的关键之一在于找到重构应用的位置.为了对这一位置进行描述和识别,Fowler等人[3]提出了代码异味这一概念,即代码中存在重构可能性的某些结构,异味的存在会对软件设计质量产生不良影响.因此,通过对软件中的代码异味进行检测,开发人员可以获得重构的位置并采用对应的重构方式以进行及时调整进而提升设计质量.

但大量的代码异味检测结果易造成信息过载,不同异味实例可能在粒度、严重性方面各不相同,即代码异味的强度不同,其对软件质量的影响程度也存在差别.事实上,异味强度高的代码异味可能十分复杂和庞大,会为系统软件的可维护性带来相对更严重的问题.因此,对代码异味的强度进行排序应成为报告代码异味检测结果时需考虑的重要因素,其允许开发人员在进行重构工作时进行优先级排序,例如,时间紧迫时优先选择异味强度最严重的异味进行修复.即以不同的方式管理不同强度的代码异味,进而可高效降低开发和维护阶段后续活动的成本.

目前部分代码异味强度排序方法依赖手工设计的特征或代码度量信息,基于启发式方法建立上述信息与异味强度之间的映射关系[4,5],从而实现强度排序.且多数方法仅从代码角度出发,未能考虑开发人员对于代码异味强度的主观感知.因此,该类强度排序结果无法为开发者提供与其对异味严重性程度感知相一致的重构顺序建议.不同的排序方法也可能会对相同的异味设计不同的启发式算法,使得排序方法之间的一致性较低.另外,利用代码度量进行异味检测结果排序时,由于代码度量只关注代码自身的结构属性,仅从结构方面捕获源代码的特性,从而忽视了代码之间的联系与逻辑关系,即代码之间的包含、继承等关系.Hadj-Kacem等人[6]通过抽象语法树获取代码间的语义信息,其将抽象语法树节点转换为数值向量表示,将向量输入到变分自动编码器以生成语义信息.但仅用语义信息不足以描述代码之间的复杂关系,因此,本文在抽象语法树的基础上构建语义结构图,利用图的特性同时考虑代码的语义信息与结构信息,实现对项目中代码间复杂关系的进一步刻画.

为了实现对语义结构图中信息的提取,本文采用无监督的图表示学习方法进行图的向量表示.近年来,图表示学习在机器学习领域得到了广泛关注,其保留图拓扑信息与节点内容,将复杂的图中节点表示为低维向量,同时该向量反映出节点在原图中复杂的交互信息,并使得后续的下游分析任务(如节点分类、链接预测等)都可以通过机器学习方法实现.因此,本文提出了一种基于图表示学习的代码异味强度排序模型CSSRM(Code Smell Severity Ranking Model,CSSRM),该模型同时考虑代码语义信息与结构信息构建语义结构图,利用图表示学习与机器学习方法,利用开发人员感知到的代码异味的不同严重性级别实现代码异味强度排序.

本文的主要贡献为:

1)提出了一个基于图表示学习的代码异味强度排序模型CSSRM,该模型同时考虑代码语义信息与结构信息实现对于开发人员感知到的代码异味强度进行排序.

2)模型采用无监督的图表示学习方法将代码节点表示到低维空间中,以便后续任务处理,具有良好的通用性与可扩展性.

3)将所提出的模型应用于开源项目进行实验,相较于基线方法,F1值最高提升了10.35%,验证了模型的有效性.

本文的章节安排如下:第2节介绍代码异味强度排序以及图表示学习的相关工作;第3节研究和设计代码异味强度排序模型;第4节展开实验并对实验结果进行分析;第5节总结本文内容并讨论未来工作方向.

2 相关工作

2.1 基于度量的代码异味强度排序

代码度量是软件评测的重要部分,可用于测量和改进源代码本身的质量,其通常用于与源代码相关的各类实验,以评估软件的整体质量.Fontana等人[7]提出了一种代码异味强度度量指数,用以近似衡量异味的实际严重性.该指标中强度的计算依赖于度量分布,通过为各度量指标设定正确的阈值实现强度划分.Guggulothu等人[8]利用特征选择过程筛选出的代码度量指标,通过分析4种代码异味的内部关系,尝试不同重构顺序实现排序.但上述方法并非完全自动化的解决方案,实验过程存在手动试验等部分,不利于开发人员的实际操作.

2.2 基于机器学习的代码异味强度排序

基于启发式的代码异味强度排序方法之间一致性较低,它们中的大多数需要指定阈值或明确的分类规则,不同的阈值设定可能会导致排序结果产生明显差异.机器学习技术可有效克服上述限制,其依赖分类器来区分异味强度类别,而不是通过计算指标的预定义阈值来实现分类,开发人员不需要将异味严重性定义形式化.Pecorelli等人[9]提出了一种基于机器学习的方法,根据开发人员感知的异味严重性程度对代码异味进行优先级排序.Fontana等人[10]使用机器学习技术预测代码异味的严重性程度,并比较了多种机器学习模型在异味严重性分类任务中的性能.两种研究方法虽克服了手动实验的局限,采用机器学习方法实现自动化,但仅使用代码度量作为自变量实现异味排序,并未考虑代码的其他结构特性,对代码间复杂关系的刻画并不全面.

2.3 基于语义信息的代码异味相关研究

语义信息在其他领域被证明是有价值的,且相关分析也已经用于多种软件工程任务,但在代码异味领域却少被研究.Sae-lim等人[11]通过考虑开发人员的当前上下文,对代码异味强度进行排序.Palomba等人[12]提出了TACO(代码气味检测的文本分析),利用源代码标识符和注释提取代码中的文本内容,对其进行标准化后应用不同的启发式方法实现气味的检测.Hadj-Kacem等人[13]将源代码生成抽象语法树,并利用变分自编码器生成抽象语法树的嵌入表示,随后将嵌入得到的代码语义特征作为逻辑回归的输入以进行异味检测.

2.4 图表示学习方法

图表示学习旨在通过保留图的网络拓扑结构和节点内容信息,将图中顶点表示为低维向量,以便下游任务后续处理.Perozzi等人[14]首次提出DeepWalk算法,该方法通过随机游走学习出一个网络或一张图的向量表示.Tang等人[15]提出的LINE算法,对节点的一阶二阶相似度进行建模.基于矩阵分解的方法是将节点间的关系以矩阵的形式表示,并对该矩阵进行分解以得到嵌入向量.Cao等人[16]设计的GraRep算法通过SVD分解分别学习节点的k阶表示,并将其结合生成最终表示.Bandyopadhyay等人[17]提出的FSCNMF算法交替训练网络结构与节点内容,并将二者分别作为正则化项,以此得到融合网络的结构与内容的节点嵌入表示.Yang等人[18]设计的NodeSketch算法是一种通过递归保持高阶节点邻近性的高效图嵌入技术.利用自循环增强(Self-Loop-Augmented,SLA)邻接矩阵获得低阶嵌入表示,然后递归生成k阶节点嵌入,利用独立于数据的散列技术解决图嵌入问题.

3 基于图表示学习的代码异味强度排序模型

针对代码异味检测结果过多造成异味信息过载,使得开发人员无法从检测结果中选择影响较为严重的异味优先进行重构的现象,本文基于图表示学习方法融合代码语义信息与结构信息,提出了一种代码异味强度排序模型,如图1所示.

图1 基于图表示学习的代码异味强度排序模型概图Fig.1 Overview of code smell severity ranking model based on graph representation learning

1)实验数据集构建:本文利用文献[9]的数据集与源项目,获取对应于各项目的抽象语法树,并将开发人员感知的代码异味严重程度作为机器学习使用的标签值.即原数据集中关于异味强度的标记NON-SEVERE、MEDIUM与SEVERE.因此,将问题映射为多分类问题.

2)生成语义结构图:将存在代码异味的类作为节点,利用抽象语法树获得的代码间逻辑关系构造边,生成可表示代码间复杂关系的语义结构图.

3)获得节点嵌入表示:分别利用两种图表示学习方法,将表示代码语义信息的语义结构图与包含结构信息的代码度量值结合,获得对应的节点嵌入表示.

4)实验评估:利用5种评价指标对本文提出的方法进行有效性评估.

3.1 代码异味选择

Blob,Complex Class,Spaghetti Code,Shotgun Surgery这4种异味常见于代码异味检测等相关研究[19],在软件系统项目中,上述异味被证明在软件系统中高度扩散,进而会影响代码组件的可维护性[20].因此本文选择此4种基于类的代码异味重点关注:

1)Blob(BL):类的代码数量大,并使用来自其他类的数据,表现出较低的内聚力,实现多个不同的功能.

2)Complex Class(CC):若类的复杂度较高,则认为该类会出现此异味.

3)Spaghetti Code(SC):该异味是指包含很多复杂控制语句的非结构化代码,此类代码通常难以理解和维护.

4)Shotgun Surgery(SS):该异味是指,单个修改会同时引发其他代码段一同更改的情况.即当大量外部方法创建与类的依赖关系时,会出现该异味.

3.2 异味数据集的构建

文献[9]从开发人员视角出发,利用开发者感知到的代码异味的严重性程度对异味进行评级标记.首先,利用Decor[21]与Hist[22]两种已在其他相关研究中显示良好效果的代码异味检测器识别出上述4种异味,并对工具检测出的存在异味的类进行手动二次检查,获得存在异味的类的列表.接着,监控开发人员在相应存储库上执行的活动,一旦监测到开发人员对列表中存在异味的类进行修改,则利用电子邮件询问其是否感知或识别到异味的存在.如果答案是肯定的,便请其大致描述该异味的特征再请开发者对该异味的严重性程度进行1~5级的评级.其中1级与2级被标记为NON-SEVERE,即严重性程度低,代码异味强度低;若开发者评级为3级,则标记为MEDIUM,即严重性程度中等,代码异味强度中等;否则,将其标记为SEVERE,该异味强度较强.因此,对于存在异味的类,由开发人员感知并标记的代码异味严重性程度获得对应的异味强度标签,从而构建异味数据集.

3.3 语义结构图的构建

本文使用一个轻量级、高度可扩展的多语言解析工具srcML1,其可将源代码转换为抽象语法树(Abstract Syntax Tree,AST),并保存为XML文件格式.抽象语法树是源代码的抽象语法结构的树状表示,树上的每个节点都表示源代码中的一种结构.但仅使用抽象语法树不足以完全表示出代码间复杂的逻辑与结构关系.因此,本文以代码中存在异味的类作为节点,利用抽象语法树中体现出的代码间的逻辑关系作为边,并同时将各类对应的代码度量值作为节点属性,以此构建语义结构图,从多角度捕获源代码的特征并实现对于代码间关系的进一步刻画.

对于图中的各节点,考虑以下两种关系以构造边:

1)两个类同属一个Java文件;

2)两个类之间存在依赖或继承关系.

本文首先选取文献[23]中统计得出的7种被广泛使用的代码度量指标(LOC,LCOM5,C3,CBO,MPC,RFC与WMC),接着结合所关注的4种代码异味的特点,对于图中每个节点的属性,共考虑以下14种常用的基于类的代码度量值.其中后7种指标捕获了代码的修改次数等流程和开发人员相关度量,它们能够从不同角度捕获类的特征.表1给出了各度量值[9]及其对应描述.

3.4 语义结构图的嵌入表示

为实现结构语义图与代码度量信息的结合,本文选用两种不同的嵌入表示方法生成可输入机器学习模型的最终嵌入表示.

3.4.1 拼接语义结构与代码度量的表示方法

将代码中的节点表示为低维向量,使其能够反映出节点在原图中复杂的交互信息,嵌入表示避免了手动的特征工程且适用于下游的机器学习任务,例如对某节点存在的异味严重性进行分类.

为此,本文采用一种通过递归草图保留高阶节点邻近度的高效图嵌入技术NodeSketch[18]以获得语义结构图的节点嵌入,后将嵌入表示获得的矩阵与代码度量进行拼接,得到完整的节点嵌入表示,将此方法记为CSSRM-SM(Code Smell Severity Ranking Model-Structure and Metrics,CSSRM-SM).

目前大多数图嵌入技术使用余弦距离来刻画节点相似度,然而有研究工作[24]表明,使用汉明距离进行有关相似度计算可有效加速下游机器学习任务.因此,NodeSketch利用数据独立散列,即sketching技术,使用随机散列函数为原始数据生成固定大小的草图,并在汉明空间中快速进行相似度近似生成节点嵌入.利用NodeSketch生成节点嵌入过程如图2所示.

图2 利用NodeSketch生成节点嵌入过程Fig.2 Using NodeSketch to generate node embedding process

对于低阶节点嵌入,如若直接使用图邻接矩阵的各行进行编码,将忽略一阶节点邻近度而仅保留二阶节点邻近度.因此,本文选用图的自循环增强(Self-Loop-Augmented,SLA)邻接矩阵生成低阶节点嵌入表示.SLA邻接矩阵是通过在原始邻接矩阵基础上加上一个单位阵得到的,如公式(1)所示:

(1)

对于每行SLA邻接向量,利用公式(2)生成对应的低阶节点嵌入:

(2)

接着,以递归方式学习高阶节点嵌入.为生成节点的k阶嵌入,NodeSketch利用公式(3),将每个节点的SLA邻接向量与其所有邻居节点的(k-1)阶嵌入向量以加权的方式合并,得到k阶SLA邻接向量Vr(k).

(3)

对于Vr(k)再次使用公式(2)得到k阶节点嵌入矩阵S(k).

将S(k)与代码度量矩阵M利用公式(4)进行拼接,得到最终嵌入表示:

U=[S,M]

(4)

3.4.2 融合结构语义与代码度量的表示方法

本文采用的另一种节点嵌入表示方法为融合语义结构与代码度量的表示方法.代码度量中的某些指标体现在了语义结构图中,例如统计类的代码行数的指标LOC,度量对象类之间的耦合的指标CBO等,同时节点结构也会影响对应的代码度量指标.代码度量作为软件评估的重要部分,应将其作为语义结构图中节点的属性,丰富节点的嵌入表示.因此,本文采用一种基于NMF(Non-negative matrix factorization,NMF)的优化模型FSCNMF[17],该方法在邻接矩阵和特征矩阵上使用联合矩阵分解技术,将语义结构与代码度量分别作为正则化项进行交替训练,得到融合语义结构与代码度量的节点嵌入表示,将此方法记为CSSRM-A.生成节点嵌入的过程如图3所示.

图3 利用FSCNMF生成节点嵌入过程Fig.3 Using FSCNMF to generate node embedding process

首先从结构中学习,对于邻接矩阵A,对其进行NMF分解,并最小化近似误差的F-范数,得到两个低秩矩阵U,V,如公式(5)所示.其中α2,α3是为避免过拟合而使用的权重参数.

(5)

对于节点的内容矩阵以相同方式进行分解,给定代码度量指标矩阵M,通过最小化F-范数,并设定权重参数为β2,β3,利用公式(6)得到低秩矩阵P,Q:

(6)

接着,将基于语义结构或代码度量的嵌入矩阵分别作为正则化项交替训练,利用公式(7)生成更新后的嵌入矩阵U,V:

(7)

同理,通过公式(8)可得P,Q:

(8)

可通过调节α1与β1的值来体现嵌入表示中语义结构与代码度量各自的重要性程度,如若模型更重视代码的语义结构信息,则将β1调整为较高值;反之若模型更重视代码度量内容,则将α1调整为较高值.

以迭代方式多次执行公式(6)、公式(7)并利用公式(9)对U,P进行拼接,得到语义结构图的最终嵌入:

E=[U,P]

(9)

3.5 评价指标

为了衡量所提出的模型的性能,本文选用5个评价指标:Precision,Recall,F1,AUC-ROC与MCC对实验进行评估.其中Precision,Recall,F1与MCC指标计算方法如公式(10)~公式(13)所示:

(10)

(11)

(12)

(13)

其中TP(True Positive)指正确实现代码异味强度分类的异味样本数,TN(True Negative)指正确将非某强度类的样本识别为非本类的异味样本数,FP(False Positive)指错误将非本异味强度类的样本分入本类的异味样本数,FN(False Negative)指错误将本异味强度类的样本分入了其他强度类的异味样本数.

AUC(Area Under Curve)是ROC(Receiver Operating Characteristic curve)曲线下方的面积,该曲线横坐标为伪阳性率(FPR),纵坐标为真阳性率(TPR),该指标量化模型区分不同分类的能力.

4 实验及结果分析

4.1 问题设定

为验证基于图表示学习的异味强度排序模型的有效性,本文寻求3个问题的解答.

Q1:引入了语义结构图的CSSRM-SM与CSSRM-A两种方法中,哪种嵌入表示方法对应的模型性能更加优越?

Q2:与其他根据开发人员感知严重性对代码异味强度进行分类的方法相比,本文提出的基于图表示学习的分类模型是否更具有效性?

Q3:选用其他分类器替代随机森林,能否进一步提升模型分类效果?

4.2 实验环境设置

本文实验基于Pycharm软件环境,操作系统为Intel Core i5 -1038NG7@2.00GHz,16GB内存,Mac OS X.基于图表示学习的节点嵌入方法中嵌入维度均为32,CSSRM-A模型中,取正则化参数为1、α1和α2均为1000的模型默认值.实验的基准分类算法为随机森林,采用5折交叉验证的方式进行训练与评估.

4.3 实验对象

本文使用文献[9]的数据集,针对每种代码异味选择3个开源项目与14种基于类的代码度量指标进行实验评估.表2给出了所选项目[9]的基本信息与统计数据.

表2 实验所涉项目Table 2 Projects for experiment

4.4 实验结果分析

根据实验结果,可以依次回答4.1节中的3个问题.

对于Q1,表3~表6给出了两种对应分类模型在4种异味与各项目上的实验性能.由实验结果可知,在12项实验中,CSSRM-SM方法对应的分类模型在11项实验中的评价指标值均优于CSSRM-A方法对应的模型.虽然采用两种方法均使得分类模型有较好的效果,但在多数情况下,将语义结构图与代码度量进行拼接的嵌入表示方法CSSRM-SM对应的异味强度分类器效果相对更优.这说明相较于利用结构语义信息与代码度量间一致性来生成嵌入表示的CSSRM-A方法,CSSRM-SM方法考虑了结构语义图的高阶邻近度,从结构角度获得更好的节点语义的嵌入表示,对于模型的性能提升具有更大意义.

表3 Blob异味强度排序结果比较Table 3 Accuracy results of Blob

表4 Complex Class异味强度排序结果比较Table 4 Accuracy results of Complex Class

表5 Spaghetti Code异味强度排序结果比较Table 5 Accuracy results of Spaghetti Code

表6 Shotgun Surgery异味强度排序结果比较Table 6 Accuracy results of Shotgun Surgery

对于Q2,由于使用CSSRM-SM嵌入表示方法对应的模型效果更优,因此,将该模型针对于各异味实现的分类性能求均值,并与文献[9]中对应的实验结果进行比较,结果如表7所示.

表7 代码异味强度分类结果比较Table 7 Comparison of code smell severity ranking results

其中,本文提出的模型性能相较于基线模型,在对Complex Class异味强度排序上效果有较大提升,F1值提高了10.35%.实现提升的原因可能在于存在Complex Class异味的类皆是具有较高的圈复杂度的类,因此该异味的存在与类的结构特性有关.而CSSRM-SM方法中获取节点嵌入表示时添加了类与类间的逻辑关系信息,且NodeSketch方法保留了节点的高阶相似度,因此在基线方法的基础之上从另一角度更进一步地补充了类间的结构关系,有利于模型更加准确地实现对于Complex Class异味的强度排序.

基线模型在对Spaghetti Code异味强度排序有最高的性能,而本文模型在该异味上的提升效果相对其他异味较不明显.Spaghetti Code异味包含很多复杂控制语句,且含有该异味的代码通常是非结构化的.文献[9]也曾提出该异味强度与结构因素的相关性较弱,可读性(Readability)度量是开发人员对该异味进行排序时考虑的关键因素,而可读性是否良好、代码语义是否连贯等主要需要开发人员的主观判断.因此,这说明本文方法增加考虑代码间的语义结构关系对于提升模型性能的效果较不明显的原因在于Spaghetti Code异味本身的特性.

本文提出的模型利用图结构从多个角度对代码中类的特征与关系实现进一步刻画,为模型提供更多代码特性信息用以更加准确的判断异味强度.表7的实验结果证实,相较于文献[9]的方法,本文所提出的模型在引入了结构语义信息与图表示学习方法后,对于4种异味强度的分类效果均有不同程度的提升,体现了模型的有效性.

对于Q3,在本文提出的图表示学习方法架构下,选择支持向量机(Support Vector Machine,SVM)、决策树(Decision Tree,DT)与逻辑回归(Logistic Regression,LR)3种分类器与实验基准分类器随机森林(Random Forest,RF)进行对比,比较其在相同实验数据集上的代码异味强度分类效果差异.由表8看出,在BL、CC、SC、SS 4种异味下采用两种嵌入表示方法利用随机森林(RF)实现的最终强度分类效果均优于使用SVM、DT与LR算法.在对SC异味使用CSSRM-SM嵌入表示方法时,利用RF实现分类的模型的F1值最高高出利用SVM的模型28.58%,因此采用RF实现基于图表示学习的代码异味强度分类方法效果更好.其余3种分类器中,选用CSSRM-SM嵌入表示方法时,DT和LR相比SVM略微存在优势,选用CSSRM-A时,SVM对应的最终模型效果略优于DT与LR.

表8 不同分类器的代码异味强度分类效果Table 8 Code smell severity ranking results with different classifiers

5 总结与展望

本文提出了一种基于图表示学习的代码异味强度排序模型CSSRM,该模型利用抽象语法树与代码间复杂的逻辑关系构建语义结构图,并利用图表示学习方法结合代码度量信息生成节点嵌入,随后利用随机森林作为分类器实现对于代码异味的强度分类,进而可以利用本文提出的模型来对代码异味实例进行优先级排序,为开发者的重构优先级决策提供参考.通过实验表明,本文提出的模型显著提高了代码异味强度排序的准确率,且CSSRM可结合更多先进的表示学习方法与机器学习方法进行强度分类,具有良好的通用性与可扩展性.

在未来研究中可关注3个方向:

1)扩大数据集,在更多不同规模的项目上探索本模型的可用性,进一步分析基于图表示学习的代码异味强度排序效果.

2)扩大所研究的异味粒度,由于所选用的数据集关注于类级别的代码异味,因此本文所提出的模型研究粒度也限制于类级别,在未来研究中可探索方法级别的异味严重性排序模型性能以丰富研究内容进而克服此局限.

3)捕获其他性质或粒度级别的代码特征,在目前模型的基础上进一步丰富节点嵌入所包含的内容,探索对于模型性能实现进一步提高的可能性.

猜你喜欢
开发人员异味度量
鲍文慧《度量空间之一》
模糊度量空间的强嵌入
迷向表示分为6个不可约直和的旗流形上不变爱因斯坦度量
Semtech发布LoRa Basics 以加速物联网应用
基于4G技术的VOCs及异味检测系统
用这些告别异味吧!夏天就要清清爽爽过!
PIC-408系列采用育种技术控制公猪异味
地质异常的奇异性度量与隐伏源致矿异常识别
后悔了?教你隐藏开发人员选项
去除鞋柜异味等