一种面向代码重用的源代码推荐方法
技术领域
本发明属于软件工程技术领域,具体涉及一种面向代码重用的源代码推荐方法。
背景技术
随着软件技术的发展,用户量不断加大且用户对软件功能的需求不断增加,这使得软件开发的规模不断增大。开发人员在软件开发过程经常要对一些功能函数进行重复编写,而且很多时候开发人员不能很好的理解软件需要文档。开发人员通过搜索引擎等方法搜索其他开发者的代码作为参考完成自己的任务,但对于搜索引擎得到的参考代码并不能很好的切合自己已写的代码。开发者通常还要阅读自己的代码,对参考代码进行一定的修改才能得到自己想要的形式,这对开发人员是在时间和精力上极大的消耗,大大拉长了软件开发周期。
目前已有一些深度学习方法开始应用到代码推荐当中,例如循环神经网络或者transformer(转换器)模型等等。但这些模型很少能够充分获取代码中的结构信息,并且存在对长序列的信息丢失问题,这些问题使得推荐的代码不够准确,并不能够很好的帮助到开发人员。代码块的另一种表征形式是抽象语法树,这一结构可以很好的体现结构信息,适应抽象语法树结构,不仅可以解决结构信息获取不足问题,同时也解决了长序列信息丢失问题,提高推荐精度。
基于以上叙述,可以通过重用以前项目中的源代码来减少开发时间和成本,需提供一种面向重用的源代码推荐方法,以帮助程序员根据软件需求规范找到相关的实现或示例代码。
发明内容
本发明要解决的技术问题是提供一种面向代码重用的源代码推荐方法,具有较高的实用性和正确性,能有效辅助程序员理解软件需求文档,实现功能,节省软件开发时间。
为解决上述技术问题,本发明的实施例提供一种面向代码重用的源代码推荐方法,包括如下步骤:
S1、源代码预处理和验证:对上传的源代码进行预处理,再通过构造抽象语法树从源代码中提取包括函数名和变量名的重要属性,如果在构造AST时出现错误,则将这段代码视为无效并放弃对该代码的上传;完成AST构造后对函数源代码进行验证,判断是否是库内已有函数源代码的功能延展,或者是库内某函数源代码的简版;
S2、生成函数摘要:结合步骤S1针对每个函数源代码构造的抽象语法树,通过AST提取函数源代码的包括函数名和变量的信息,与函数源代码的注释部分结合生成函数源代码的函数摘要;
S3、获取函数标签词:结合步骤S2针对函数源代码生成的函数摘要,识别函数摘要里的函数名、重要变量名以及部分重要注释,将这三部分内容结合在一起得到函数标签词;
S4、构造键值对:将步骤S1中经过预处理后的函数源代码与根据该函数源代码由步骤S2生成的函数摘要以及步骤S3生成的函数标签词生成具有相同“键”的键值对,即构造{Fun_id,Source_code}、{Fun_id,Fun_describe}、{Fun_id,Fun_label}键值对,分成存入数据库;其中,Fun_id表示为函数编号,Source_code表示为函数源代码,Fun_describe表示为函数摘要,Fun_label表示为函数标签词;
S5、生成问题词条:根据用户输入的已知问题项为用户推荐查询,分析用户输入的问题句,通过对比无效词库将自然语言的问题句进行剔除得到问题有效句,再对问题有效句进行分析转换成有效词条;
S6、查询匹配度计算:计算由步骤S5通过分析问题句得到的有效词条与库内各个函数源代码的函数标签词的相关系数,以及问题有效句在函数摘要的存在系数;查询匹配度来源于两个数值:相关系数以及存在系数;
S7、搜索结果输出:根据步骤S6计算得到的相关系数、存在系数两个数值,在函数源代码内搜索后输出搜索结果。
其中,步骤S1中,对代码进行预处理是为了规范上传代码的格式从而提高抽象语法树(AST)转换的成功率。与此同时,对于给定项目的新版本,用户可能查找的是一些基本功能,那新版本的一些功能对于用户来说是多余的,所以我们会同时保留两个版本,对上传代码的验证一方面是为了在原版本和新版本之间建立一种联系,方便后续相关功能的扩展;另一方面也杜绝了重复代码上传的情况;
对上传源代码预处理和验证包括如下步骤:
S1.1、使用pycodestyle包进行编程规范检查,快速验证代码块是否符合PEP8书写规范,确定代码哪些部分需要被格式化;
S1.2、使用autopep8模块规范代码格式;
S1.3、将上传代码与库内已有源代码进行重复度比较,对于重复读过高甚至完全重复的代码取消上传;
S1.4、使用python的ast模块将源代码转换为AST。
其中,步骤S2中生成的函数摘要是一个由自然词汇、句子以及短语组成的描述性文本;就单个函数摘要而言,首先从该函数的AST中提取函数名和变量,然后通过简单的文本处理遍历函数的源代码,识别注释符号,获取源代码的注释内容,在提取函数名、变量名和注释之后,将这些信息结合起来生成函数摘要;其中,对于函数名和变量的处理规定如下:
S2.1、对于由几个首字母为大写的英文单词连在一次的函数名或者变量名,读取每个英文单词进行翻译,生成中文注释;
S2.2、针对步骤S2.1,如果部分字母无法翻译,选择忽视该部分字母;
S2.3、在处理一些其中带有下划线或其他特殊符号的变量名时,只读取英文单词,而忽视特殊符号。
其中,步骤S3中,函数标签词将是系统为用户推荐查询的依据,在单个函数标签词内不会出现同一描述词,函数标签词来源于该函数源代码的函数摘要,函数标签词根据函数摘要对重要变量以及注释的选取规定如下:
S3.1、注释习惯“前短后长”,默认后面文字是对前面的解释,选择前面句子短且不超过5个字符的描述语加入标签词;
S3.2、注释习惯“前长后长”,默认该段注释都是对代码逻辑的解释,不选择操作;
S3.3、针对同一实体多个操作变量的命名,仅选择相同部分的实体名加入函数标签词;
S3.4、针对字符数小于2的字符,认为其不具有标签属性,不足以作为函数标签词。
其中,步骤S4中,键值对{Fun_id,Source_code}、{Fun_id,Fun_describe}、{Fun_id,Fun_label}的构造既满足了后续步骤对数据库的检索,又为特定项目新、旧版本代码的存储提供了方便,每个函数编号自动生成且唯一;其中,Fun_id表示为函数编号,Source_code表示为函数源代码,Fun_describe表示为函数摘要,Fun_label表示为函数标签词。
其中,步骤S5中,由于词汇不匹配问题,用户可能无法根据自己输入的查询语句找到最终想要的函数源代码,因此,系统会根据用户已输入的问题项通过对比函数标签词为用户推荐查询语句;对问题进行查询后,在后面相似度计算中所有术语会被认为同等重要,所以对查询语句中一些频繁出现但不重要的术语进行剔除,通过模型训练生成不重要词汇表,将各术语与不重要词汇表进行匹对从而达到剔除的目的。
其中,步骤S6中,问题有效句在函数摘要的存在系数,定义如下:
其中,
为问题有效句的总字数,
为函数摘要内存在最多问题有效句字数前提下最短的描述句总字数,
为问题有效句出现在函数摘要内选定描述语句的字数;
有效词条与函数标签词的相关系数,定义如下:
其中,
为问题有效句,
为问题有效句对应的一个有效词条的字数,
为在函数标签词内带该有效词条的描述句句数,
为问题有效句的总字数,
为函数标签词的总句数。
其中,步骤S7中,搜索结果输出,在讨论问题语句与某个函数源代码的匹配度时,该函数源代码所求得的相关系数在一定程度上受存在系数的取值影响,所以对存在系数设定一个阈值;对于问题查询所有结果存在系数都低于该阈值的情况,选择放弃对结果的输出,并认为目前系统数据库不具备用户搜索的目的函数;由于函数源代码注释描述的不确定性,每个项目库的阈值设定不一致;低于15%的存在系数所对应的函数源代码跟查询问题是不具备匹配特征的。
本发明的上述技术方案的有益效果如下:本发明提供了一种新的源代码推荐方法,具有较高的实用性和正确性,能有效辅助程序员理解软件需求文档,实现功能,节省软件开发时间。
附图说明
图1为本发明的流程图;
图2为本发明中上传代码验证重复度过高实例图;
图3为本发明中形成函数摘要相关步骤图;
图4为本发明中函数源代码的函数摘要实例图;
图5为本发明中函数标签词生成实例图;
图6为本发明中函数编号、函数源代码、函数摘要以及函数标签词的内在联系图;
图7为本发明中问题输入到问题词条生成的相关步骤图;
图8为本发明中根据问题推荐查询实例图;
图9为本发明中查询计算结果实例图。
具体实施方式
为使本发明要解决的技术问题、技术方案和优点更加清楚,下面将结合附图及具体实施例进行详细描述。
本发明提供了一种面向代码重用的源代码推荐方法,主要用于帮助公司程序员根据软件需求规范查找实例代码和相关实现,包括如下步骤:源代码预处理和验证;生成函数摘要;获取函数标签词;构造键值对;生成问题词条;查询匹配度计算;搜索结果输出。该方法的流程图如图1所示,包括如下步骤:
一、源代码的预处理和验证
在将函数源代码转换为抽象语法树(AST)之前对函数源代码进行预处理有利于提高AST转换的成功率,另一方面也是确保上传代码的正确性。上传代码预处理和验证步骤如下:
(1-1)使用pycodestyle包进行编程规范检查,快速验证代码块是否符合PEP8书写规范,确定代码哪些部分需要被格式化。此项处理面向上传者,系统在确认上传代码不符合规范的部分后,上传者可以对代码进行修改,从而确保了代码本身的正确性。
(1-2)使用autopep8模块规范代码格式。美观且专业的代码排版会对代码的呈现和操作带来一定好处。
(1-3)将上传代码与库内已有源代码进行重复度比较,如图2中,上传代码与系统数据库内某函数源代码仅某变量取值不一致,存在过高重复度。对于重复度过高甚至完全重复的代码取消上传。由于上传者是不知道上传代码是否已经存在于系统数据库,所以对上传代码的重复度验证至关重要。同时,由于特定项目存在代码更新的情况,重复度验证也能确认上传代码是否是某个特定项目的功能更新,从而在新旧版本代码之间建立一层关系。对于给定项目的新版本,用户可能查找的是一些基本功能,那新版本的一些功能对于用户来说是多余的,所以我们需要同时保留两个版本。
(1-4)使用python的ast模块将源代码转换为AST。代码的正确性是代码能成功转换为AST的前提。如果转换失败,则放弃对上传代码的上传,并返回失败。
二、函数摘要以及函数标签词的生成
函数摘要是基于函数源代码转换的AST以及函数源代码的注释部分形成的。如图3所示,是函数摘要形成的相关步骤。大多数情况下,可读变量和函数名包含有关该函数源代码的工作流和功能的重要信息。因此,可以把函数摘要理解成函数源代码的描述文档,是函数源代码的中文形式。在形成函数摘要时,我们会充分考虑那些能够丰富函数描述文档的意味性词。如图4所示,为某个函数源代码的函数摘要的生成实例。其中,对于函数名和变量的处理规定如下:
(2-1)对于由几个首字母为大写的英文单词连在一次的函数名或者变量名,我们读取每个英文单词进行翻译,生成中文注释。例如变量名为“SaveCityName”,我们将输出“保存城市名称”为变量名。
(2-2)针对(2-1)步骤,如果部分字母无法翻译,我们选择忽视该部分字母。例如变量名为“SaveCityNamePois”,我们将输出“保存城市名称”,而忽略Pois部分。
(2-3)在处理一些其中带有下划线或其他特殊符号的变量名时,只读取英文单词,而忽视特殊符号。例如,变量名为“GET_CITY__NAME”,我们输出“获取城市名称”为变量名。
函数标签词是基于函数摘要生成的。如图5所示,为函数源代码的函数标签词的生成实例。函数标签词是系统为用户推荐查询的依据,在单个函数标签词内不会出现完全相同的描述词。函数标签词根据函数摘要对重要变量以及注释的选取规定如下:
(3-1)注释习惯“前短后长”,默认后面文字是对前面的解释,我们选择前面句子短且不超过5个字符的描述语加入标签词。例如,内容类似于“冒泡排序,遍历数组按从大到小排序。”,我们选取“冒泡排序”加入函数标签词。
(3-2)注释习惯“前长后长”,默认该段注释都是对代码逻辑的解释,不选择操作。例如,内容类似于“如果数值小于后一位,交换两个数值位置。”,我们不操作。
(3-3)针对同一实体多个操作变量的命名,我们仅选择相同部分的实体名加入函数标签词。例如,内容类似于“获取学生姓名,获取学生学号,获取学生年龄,获取学生性别”,我们选取“获取学生”加入函数标签词。
(3-4)针对字符数小于2的字符,我们认为其不具有标签属性,不足以作为函数标签词。如部分翻译过来的函数变量“高”、“低”。
三、键值对的构造
对函数源代码处理之后,数据存储也是至关重要的一步。本发明选择了以{Fun_id,Source_code}、{Fun_id,Fun_describe}、{Fun_id,Fun_label}键值对的形式对信息进行存储。其中Fun_id表示为函数编号,Source_code表示为函数源代码,Fun_describe表示为函数摘要,Fun_label表示为函数标签词。三类键值对的函数编号是相同的,即函数源代码以及基于该函数源代码生成的函数摘要和函数标签词在键值对内具有相同的“键”。函数编号、函数源代码、函数摘要以及函数标签词的内在联系如图6所示。函数编号自动生成且唯一。以这种方式对数据进行存储为既满足了后续步骤对数据库的检索,又为特定项目新、旧版本代码的存储提供了方便。
四、问题词条的生成
问题词条是根据最终的查询语句进行分析得到的有效短句。本发明是根据问题词条来对系统数据库进行检索的。如图7所示,为问题输入到问题词条生成的相关步骤。由于词汇不匹配问题,用户可能无法根据自己输入的查询语句找到最终想要的函数源代码。因此,系统会根据用户已输入的问题项通过对比函数标签词为用户推荐查询语句,图8所示是当用户输入“排序”,系统为用户推荐的查询语句。当用户选择被推荐的查询语句时,最终搜索结果输出的函数源代码跟用户查询内容将会很匹配。而当用户需要查询的函数不在推荐里面,本发明会对用户输入的查询语句进行如下操作,步骤如下:
(5-1)剔除一些频繁出现但不重要的术语。例如“带有结果输出的冒泡排序”,剔除不重要术语后得到问题有效句--“结果输出冒泡排序”。
(5-2)将问题有效句进行切割,生成问题词条。例如“结果输出冒泡排序”会产生有效词条“结果输出”,“冒泡排序”,“结果”,“输出”,“冒泡”,“排序”。
五、查询匹配度计算
本发明的查询匹配度由存在系数和相关系数决定。存在系数计算的是问题有效句在函数摘要内的出现率,更多反映的是用户搜索的目的函数出现在该函数源代码的可能性。相关系数计算的是各有效词条与函数标签词的相关度,反映的则是该函数源代码对目的函数的纯粹性,即函数源代码附加除目的函数以外的其他功能的可能性。所以在结果输出中,我们会优先考虑存在系数的大小,而将相关系数作为一个辅助数值进行比较。在这样的安排下,我们确保在一个问题的结果输出上同一个函数源代码只会出现一次。
问题有效句与函数摘要的存在系数,定义如下:
其中,
为问题有效句的总字数,
为函数摘要内存在最多问题有效句字数前提下最短的描述句总字数,
为问题有效句出现在函数摘要内选定描述语句的字数。
有效词条与函数标签词的相关系数,定义如下:
其中,
为问题有效句,
为问题有效句对应的一个有效词条的字数,
为在函数标签词内带该有效词条的描述句句数,
为问题有效句的总字数,
为函数标签词的总句数。
六、搜索结果输出
查询结果的输出会基于前一步骤计算所得的两个数值。而在讨论问题语句与某个函数源代码的匹配度时,该函数源代码所求得的相关系数在一定程度上受存在系数的取值影响。所以我们会对存在系数设定一个阈值。对于问题查询所有结果存在系数都低于该阈值的情况,我们选择放弃对结果的输出,并认为目前系统数据库不具备用户搜索的目的函数。由于函数源代码注释描述的不确定性,所以每个项目库的阈值设定不一致。我们认为,低于15%的存在系数所对应的函数源代码跟查询问题是不具备匹配特征的。如图9,为本系统查询“快速排序”与系统数据库内某函数源代码的查询匹配度计算结果,可知该函数源代码跟所查询内容拥有很高的匹配度。
在得到输出结果之后,用户选择了查看函数源代码,本发明会为用户推荐该函数源代码的新版本或者之前的版本(如果存在),发掘用户的潜在查询需求。
本发明提供的一种面向重用的源代码推荐方法,以帮助程序员根据软件需求规范找到相关的实现或示例代码,具有较高的实用性和正确性,能有效辅助程序员理解软件需求文档,实现功能,节省软件开发时间。
以上所述是本发明的优选实施方式,应当指出,对于本技术领域的普通技术人员来说,在不脱离本发明所述原理的前提下,还可以作出若干改进和润饰,这些改进和润饰也应视为本发明的保护范围。