APP下载

一种面向程序理解的程序语义聚类技术

2019-12-04陈颖

软件导刊 2019年10期

陈颖

摘要:针对源代码中一些非结构化的自然语言描述信息进行语义聚类,辅助开发人员开展程序理解。主要利用自然语言处理技术对程序中的标识符和注释进行预处理,将程序转換成词频矩阵;然后利用潜在语义索引技术对该词频矩阵进行层次聚类,并对每个聚类的标记进行推荐,辅助开发人员理解程序。在开源项目JEdit上进行验证,结果显示对该5万行规模的项目代码进行聚类时耗不足1分钟。因此,该技术能够快速对程序进行语义聚类,辅助开发人员快速理解程序。

关键词:程序理解;语义聚类;潜在语义索引;语义标注

DOI:10.11907/rjdk.191119开放科学(资源服务)标识码(OSID):

中图分类号:TP303文献标识码:A 文章编号:1672-7800(2019)010-0062-03

0引言

软件维护是一个集软件分析、理解、修改、测试、重新确认于一体的过程。软件分析和软件理解是维护过程的第一步,能否准确、迅速、全面地理解程序是决定维护任务成败的关键。程序理解指运用一定的实施方法了解一个程序的功能及目的。程序理解是软件工程领域的重要组成部分,据估计,软件维护中高达60%的时间被用于程序理解。现有程序理解方法大多关注程序结构或外部文档,忽略了对源代码中一些非形式化语言的研究,这些诸如变量名、程序注释等自然语言往往隐藏着软件系统知识信息和领域信息,通过挖掘这些信息,开发人员能够对一个陌生的软件系统功能特征形成初步理解。

程序聚类可将程序源代码文件聚合成为模块,从而更好地理解程序设计,并从源代码文件中抽取有意义的概念。程序聚类在软件维护过程中有众多应用,常用于软件重新模块化、软件分解、软件演化分析与对象识别等方面。文献主要关注并分析了聚类活动中的3个方面,即聚类实体抽象描述选择、描述实体间耦合度量值及聚类算法,以及软件重新模块化识别;文献[10]提出一种转换框架,能够将嵌套的软件分解转换成为平面软件分解,并可在过程中避免信息丢失;文献[11]在5个大型开源系统上分别使用6种不同的聚类算法进行聚类实验,结果表明不同聚类算法具有不同特性,目前自动化聚类算法还需大幅提高效率以提供持续支持;文献[14]利用聚类技术针对面向过程的程序代码进行对象识别,辅助程序对象化转化。

上述研究主要利用程序聚类实现软件维护等应用,但是并没有从程序语义聚类的角度出发进行程序理解。语义聚类可直接用于程序理解。文献[15]提出将嵌套的软件分解转换为平面的软件分解,并且避免了显著信息丟失,使程序更容易理解;文献[16]提出使用潜在语义分析软件聚类的初步结果,挖掘软件代码同文档中潜在语义信息的关联,基于该语义关联辅助程序理解;文献[17]提出一种基于功能需求层次的程序聚类方法,通过需求层次识别相关程序;文献[18]提出利用模糊形式概念对软件进行分析和聚类,实现通过软件分解达到程序理解的目的;文献[19]提出针对软件代码进行聚類,并定义概要模板进行聚类的概要生成。

以上关于程序聚类的工作侧重于利用程序聚类对软件进行分解或借助外部文档信息辅助程序理解。但实际中对于分解的软件如果没有明确的语义标注,则程序理解难度较大;另一方面,在实际软件开发过程中,外部文档信息经常不准确、不全面,难以产生有意义的效果。

本文主要利用潜在语义分析技术对代码进行聚类,同时可实现聚类自动标记,辅助开发人员理解程序。本文对程序聚类的研究和解释不建立在外部文档的基础上,而是根据非形式化的静态方法进行分析,即使用源代码内部注释和变量名等文本信息进行分析。具体内容包括:通过潜在语义索引(Latent Semantic Indexing,LSI)技术进行程序聚类和解释,运用潜在语义索引中的奇异值分解(SingularValue Decomposition)对term-document降维,并在三维语义空间和四维语义空间进行聚类分析,通过层次聚类方法得到的树状图输出聚类结果,并对每个聚类的解释从单词和短语两个方面进行推荐,辅助开发人员理解程序。

1基础知识介绍

潜在语义索引(Latent Semantic Indexing)是基于向量空间模型的一种技术,表示词汇在软件系统中的含义。LSI将文件模型化,并将其排列成一个term-document矩阵。term-document矩阵A是一个稀疏矩阵。该矩阵大小为mxn,其中m是经过处理的单词数量,n是文件数量,矩阵的每个元素ai,j是在文件dj中词汇ti的频率。该矩阵的几何解释是一组文档向量由术语度量的向量空间表示。文档之间的相似性通常被定义为相应向量之间的余弦或内积。如果其对应的向量指向同一个方向,则两个文件被认为是类似的。

LSI以一个源term-document矩阵开始,通过加权函数加权平衡。奇异值分解(Singular Value Decomposition,SVD)用来把向量空间模型转换成更小的维数。该算法尽可能多地保留文档向量之间的相关距离,将term-document矩阵降维成一个维度大幅缩小的矩阵。

当矩阵A有k个最大奇异值时,利用奇异值分解把矩阵A分解成其奇异值奇异向量,并且用相似矩阵A代替秩为k的矩阵A。此外,不仅低秩的term-document矩阵A′可以计算,而且term-term矩阵和document-document矩阵也能被计算。因此,LSI允许计算term-document、term-term和document-document的相似性。

在使用LSI技术过程中,有一些参数需要设计,如在一般信息检索技术中聚类规模k通常取值200~500,但本文在分析软件数据时,参照已有工作k的取值为20~50。

2程序聚类与解释

本文方法主要基于Java语言代码进行分析。首先,分析源代码信息,包括变量名、方法名以及注释,再对这些信息进行预处理,从这些信息中提取关键词,以构建需要的term-document矩阵,基于term-document矩阵使用奇异值分解,将term-document降维以提取特征矩阵;其次,通过层次聚类的方法进行聚类,得到关于程序代码的聚类树状图,再将得到的聚类结果代人聚类标记算法进行标记推荐,实现聚类语义解释;最后,对整个软件系统进行聚类标记,实现从语义角度理解整个软件系统。

2.1程序语义聚类

在信息检索中,为提高检索准确率,需要对信息进行预处理,如删除停用词、词干处理等。由于本文主要分析的代码是基于Java编写的,因此诸如Java、int等类别的词均被加入停用词表;其次,进行词干处理减少term-docu-ment矩阵维数,能将一个词汇的不同形式转化为相同的词根,避免同义词的不同形式带来语义信息抽取误差,如achievement→achieve。

本文使用层次化聚类方法,主要采用迭代方法,聚类过程自下而上、由小变大。首先在所有类中选取两个距离最小的类,则这两个类先构成一个聚类,然后在其它类中寻找与其距离最小的类以及任意两个距离最小的类,若前者距离大于后者,则后者成为一个新的聚类,否则增大前者,依次往复,直到处理完所有类即形成第一层次的聚类。第2层次的聚类是运用第1层聚类将各个小的聚类构建成大的聚类;第3层及后续依次迭代形成。

2.2程序聚类解释

基于上述聚类结果,对聚类进行标记,协助开发人员基于聚类标记的结果理解某个聚类的程序代码,标记过程如下:

Stepl:找出聚类中每个java文件最高频的词;

Step2:对每个聚类最高频词进行查重处理:若一个高频词在该聚类的n(n>=2)个java文件中出现,则该词频率将对每个java文件中该词出现频率之和加上(n-1);其词频率赋给第一个出现该词的java文件,其它都置为0;若n=1,其词频等于该词本身;

Step3:若最终频率不为零的java文件数小于5,则该聚类标记数是不为。的java文件數,否则为5;

Step4:将利用Step2和Step3得到的频率作为最高标记输出;

Step5:重复Stepl、Step2和Step3,直到所有聚类标记过程结束。

3实验分析

3.1实验设置

本实验运行环境为HP ENVY 15j105tx,拥有CORE i74702QM处理器,8GB RAM。本实验实验对象为JEdit,是一个用Java语言开发的文本编辑器,在GPL下发布。JEdit 2.4.1一共包含282个Java文件,约5万行代码。

3.2实验结果与分析

首先,分析针对JEdit项目进行程序聚类前的预处理阶段时间性能分析,结果如表1所示。结果发现本文方法每一步所需时间均在30s以内,总时间控制在1min以内,证明其处理该规模软件的时间有效性。

基于实验结果,距离等于6时聚类效果较好,依此进行聚类结果提取,并将聚类结果输入开发的工具中进行聚类解释和词语推荐。各个聚类标记和解释如表2所示,第2列表示各聚类大小,第3列表示该聚类的推荐标记,最后一列是根据标记得出的解释。通过聚类解释,很容易发现该软件与文本编辑相关,再加上对短语的分析,更能验证对程序的解释,而该软件确实为一个文本编辑器。

4结语

本文针对程序代码从程序语义聚类的角度理解程序,提出利用潜在语义分析进行层次聚类,并利用词语推荐对聚类结果进行标记,实现对程序的有效理解。该技术通过在开源项目JEdit上进行实验,证明其有效性。

该技术还存在一些缺陷,如语义信息冗余,在今后的工作中,可将生成的标记建为聚类创建cluster-label矩阵,通过计算每个聚类相似度去除冗余语义信息;另外,也可以不局限于潜在语义分析,借助其它信息检索技术(如主题模型)辅助语义聚类与解释。