论文笔记--一种基于深度学习的上帝类检测方法

一种基于深度学习的上帝类检测方法

作者:卜依凡, 刘 辉, 李光杰 北京理工大学 2019软件学报

代码坏味道:代码坏味,是指那些阅读和理解起来非常拗口、困难、耗费大量脑力的代码。判定一段代码是否属于坏味道是比较主观的,它会随语言、开发人员和开发方法的不同而不同。在工作当中,很多时候都是在维护之前的项目和在此基础上增加一些新功能,为了能让项目代码易于理解和维护,要时刻注意代码中的“坏味道”,当发现代码如果有坏味道了,要及时去重构它使其变成优秀的整洁的代码。

代码坏味检测是软件重构中的一个重要步骤。它不会妨碍程序的预期功能,但是会随着时间的推移对软件系统造成一定的缺陷,导致高额的维护成本。

软件维护过程中的软件重构环节可以有助于提高软件质量,软件重构可以重构软件应用程序的内部结构而不改变其外部行为。重构的三个步骤:确定软件应该重构的位置;确定哪些重构应该应用于已识别的位置;评估重构对软件质量的影响。

上帝类:即为object类,在Java中任何一个对象都有上帝类中定义的方法。对于任何一个类,如果没有写extends XXX,那么该类都是默认为extends Object,即为上帝类,任何类都是Object类的子类。

概述

软件应用过程中产品需求的变更会导致程序设计之初设计好的代码框架需要不断地调整以实现功能的变更,长此以往程序将逐渐偏离原有的框架,使得程序变得难以维护。对于这样的问题提出了软件重构对此类软件进行优化,在不改变外部特性的前提下提高软件的设计质量,进而提高软件的可维护性和可拓展性。 为了确定应该在程序的何处进行重构,Fowler提出代码坏味的概念。一共提出了22种代码坏味。 本文中仅针对上帝类这一种代码坏味进行深入研究。上帝类是指某个承担了本应由多个类分别承担的多个职责的类,违背了单一职责的设计原则。原有的检测上帝类的方法主要基于代码行数、圈复杂度、内聚度等常见的软件度量,使用提取类或者提取子类等重构操作来处理上帝类。不同的检测方法之间存在较大差异,且查全率和查准率偏低。

本文提出一种基于深度神经网络的上帝类检测方法,考虑常见的软件度量以及代码的文本信息。文本信息用于标注每个类所承担的主要角色,结合上帝类在耦合度、内聚度、类规模等属性相关的多个度量指标。采用有监督学习的方法,标签是自动生成的。

上帝类检测方法

数据集生成

原理:对于一个可成功编译的合理的开源项目,在不改变类的外部行为的前提下,将其中两个类合并为一个类,就认为这个大类承担了两个类的职责,视为上帝类正样本。从其余未参加合并的类中抽取出相应数目的类作为负样本集合

神经网络分类器的输入:从正负样本集中分别提取出符合预设输入格式的文本信息软件度量特征(文本信息:从代码中提取的部分相关标识符(存在于一个类中的多个成员之间的在语义上的关联);软件度量特征:选取数个与上帝类代码结构相关的代码度量项,如代码耦合度、内聚度、复杂度、代码规模等) 预期输出:样本的标签(是否为上帝类)二分类 0 和 1。

文本信息(标识符的表示) :用 Word2Vector 将标识符中的词语映射为向量,对神经网络分类器的输入(各个标识符)进行预处理。 1、分词。根据驼峰命名法和下划线命名法规则对标识符(可以理解为变量名,函数名等)进行分词,拆为多个逻辑单字。(已有) 2、使用Word2Vector模型将逻辑单字映射为词嵌入向量 3、将原标识符拆分后得到的各个分词向量相加后取均值构成新的词向量。 4、单个类中的标识符个数固定在50个,对前50个成员进行预处理,不足50则补0 。

神经网络分类器

输入:分为文本输入度量指标输入两部分。(语义特征和结构特征) 文本输入部分:由类中的成员标识符组成,经预处理之后,由文本信息转变为词向量的形式(50×200的矩阵),输入到长短时记忆网络(LSTM)(使用sigmoid激活函数),权重采用均值,使用LSTM从长序列重提取到语义特征,检测类在语义上的内聚性。 度量输入部分:12个度量指标的数据集输入到全连接层(激活函数tanh),权重均匀,有监督学习。 融合:两部分输入数据在融合层以向量拼接的方式合并。 再经过一层全连接层(激活函数tanh)映射到最终的Sigmoid输出层。权重初始化为全0矩阵 输出层(激活函数sigmoid函数),模型损失函数为binary_crossentropy函数,优化器为adam自适应方法,epoch为10,batch_size为5。

训练集

主要采用“合并类”的操作来进行。 假定 某个程序的现有设计合理,那么将其中的两个类合并成一个大类,这个合并起来的大类就相当于一个上帝类,作为上帝类正样本。在合并时,尽量不改变合并的两类的源码,以保证合并后大类的外部行为与合并之前的保持一致。(合并容易导致的语法错误如:合并的两个类存在成员名冲突,两个类是否继承于不同的父类)

上帝类正样本

要生成训练样本集要对项目里的各编译单元进行三次筛选 第一次筛选:判断单个编译单元的顶层类,筛选能够进行合并操作的常规类 第二次筛选:将得到的类两两合并,判断是否会发生语法错误(语法错误如两个类中是否存在成员名冲突,两个类是否继承于不同的父类) 第三次筛选:判断合并后是否会导致程序错误与外部行为变化 合并类算法: 这个NewClass作为上帝类正样本,使用12个度量值进行计算。

上帝类负样本

将未参与合并的类,定义为负样本。同样使用文本信息和度量指标两个方面来进行转换 控制正负样本比例为1:1

实验

研究问题

研究问题 1:该方法是否能准确有效地检测出上帝类?其查全率和查准率是否优于现有方法? 答:使用JDeodorant作为对比实验对象。 研究问题 2:所提出的神经网络分类器中的两个特征输入(代码文本特征与代码结构特征)对最终结果分别有什么影响?即如果只有其中的一个特征输入,分类器的性能会如何变化? 答:分别将两部分特征输入分开来输入到神经网络分类器中,使用F1值作为评估指标 研究问题 3:利用其他网络模型(如卷积神经网络 CNN 和全连接网络 dense)替代神经网络分类器中所使用的长短时记忆网络 LSTM,能否进一步提高分类器的性能,如查全率、查准率等? 答:替换后使用F1值作为评估的参考指标 研究问题 4:该方法训练一个神经网络分类器的时间需要多久?利用已训练好的分类器进行预测又需要多长时间?

实验数据

训练数据(有) 12个开源项目用力构造神经网络分类器的训练数据。

测试数据(有) Palomba 提出的一个开源的代码坏味数据集,包含了在 30 个软件项目的 395 个历史版本中 13 种代码坏味的检测情况。 本次实验选用了存在上帝类这一代码坏味种类的,且可以编译的13个项目作为测试项目。

实验过程 利用之前提到的样本标签生成工具生成固定格式的正负样本标签,构建出的训练集(正样本845条,负样本775条),使用训练集来训练神经网络分类器。使用已标注好的Palomba提出的代码坏味数据集作为测试集,分别在本方法和JDeodorant中进行测试,并将两种检测结果进行对比。使用查准率,查全率、F1值作为评价指标。

实验结果

(回答问题1)表四为 相同测试集在本方法(神经网络分类器)和JDeodorant上的两种检测结果。 根据表四看到:本文提出的神经网络分类器在总体表现上优于JDeodorant,F1值提高了2.39%,在查全率上优势明显,提高了35.58%,虽然查准率略高于已有方法,但是两种方法查准率都偏低。

(回答问题2 )在本文提到的神经网络分类器中,对比单一的代码文本特征输入(语义特征)、单一的代码结构特征(结构特征)、二者综合输入(映射为向量相加),这三种输入方式的对比结果。 根据表5得到:当文本特征与结构特征一起作为输入时,分类器的综合表现优于任何一种单一输入的分类器;就只比较两种输入的特征时,结构特征对结果的影响要大于文本特征,在查准率上的表现更为明显。

(回答问题3 )在分类器的文本特征处理阶段,分别采用长短时记忆网络、全连接神经网络(隐藏层激活函数为sigmoid函数)、卷积神经网络(三层一维CNN)三种模型进行处理。 根据表6得到,LSTM模型的代码文本特征提取能力高于其他两种.Dense分类器在测试集中的不同项目之间的差异很大。

(回答问题4)表7展示了训练集提取样本数据的时间。

讨论

样本噪音

主要从两个方面来减少样本噪声 1、默认用于构建训练集的正负样本的类不存在上帝类代码坏味,且均符合单一职责原则。这样的假设也许不成立,会导致训练集中出现噪声。 解决方式:尽量选择高质量的项目源码用来构造训练集。 2、为了增加神经网络的鲁棒性,选取了LSTM 长短时记忆网络作为文本处理的方式。

总结

查准率较现有方法有所提高但是依旧偏低,查全率有了较大提高。本方法可用于实际开发中,上帝类代码坏味辅助检测,通过提供上帝类坏味候选清单,帮助开发人员缩小人工检测的范围,从而更快锁定上帝类代码坏味的重构时机。

可以基于提出的方法的框架模式,通过替换各类代码坏味所特有的特征表现以及坏味合成方式来实现不同的基于深度学习的坏味检测方法。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值