基于问答平台的弃用API迁移建议推荐技术

2022-07-07 02:41奚耀国沈立炜赵文耘
计算机应用与软件 2022年5期

奚耀国 沈立炜 赵文耘

(复旦大学软件学院 上海 201203)(复旦大学上海市数据科学重点实验室 上海 201203)

0 引 言

应用程序接口(API)是软件开发过程中不可或缺的部分,它封装了类库和框架的某个功能,开发者无须了解其内部构造只需调用接口就可以快速地编写程序。开发者倾向于在开发中使用API以避免重复工作[1]并提高软件系统的可重用性[2]。框架和类库通常会使用升级版本的方式来提供新的功能或修复缺陷,此过程经常会变更原先提供API。变更的API通常会导致客户端在升级类库版本时无法正常运行。为了避免API变更造成客户端程序无法兼容的情况发生,类库开发人员往往不会直接更改或移除API,而是将变更的API标记为弃用,在之后的版本中逐步将其移除[3-4]。在此机制下,开发者可以在弃用API被移除之前对其进行迁移[5],从而提升程序的功能性、性能与安全性[3]。

由于API文档经常出现缺失迁移信息的情况[3,6-7],开发者更习惯于在网络中搜索替换API及其代码示例。问答网站Stack Overflow存在很多弃用API的讨论帖,其中包含对替换API及其使用方式的介绍。然而由于讨论帖数目较多且开发者的问题描述经常与迁移弃用API的词汇存在差异,因此在寻找替换API及其代码示例的过程中会耗费大量时间,搜索结果往往也不够全面。尽管现有的技术可以帮助开发者快速搜索代码示例[8-9],但搜索结果包含很多开发者不关心的元素,使得代码可读性差。同时,这些技术并未对搜索结果进行筛选排序,开发者仍需花费时间从搜索结果中筛选具有参考价值的代码示例。

针对上述问题,本文提出基于问答平台的弃用API迁移建议推荐技术,该技术旨在通过快速提供包含与文本描述和代码示例的迁移建议来提高开发者迁移弃用API的效率。具体而言,该技术首先结合弃用API相关元素、标签和关键词组成的搜索条件在Stack Overflow中搜索讨论帖。在对讨论帖进行分析之后为回答生成回答快照,回答快照包括文本信息、代码示例、回答本身的附加信息。之后根据替换API对回答快照进行分类,以快照集的形式表示分类结果。接着根据回答快照的附加信息从两个维度上对快照集和回答快照进行排序。最后依据替换API对回答快照中的代码示例进行简化。与现有的迁移技术相比,该技术的优势有:1) 开发者无须提供替换API即可得到包含文本描述和代码示例的迁移建议;2) 生成的迁移建议将会以特定的规则进行排序,以方便开发者参考;3) 为了帮助开发者更快地掌握替换API的使用方式,该技术会根据替换API移除代码示例中无关的元素,提供清晰简洁的代码示例。本文基于此技术实现了迁移建议推荐工具并组织了用户实验。实验结果表明该工具能够显著地提高开发者迁移弃用API的效率。

1 相关工作

1.1 弃用API迁移技术相关研究

手动迁移弃用API需要耗费大量的时间与精力,针对此问题,研究者提出了辅助开发者迁移弃用API的技术。Dig等[10]将类库演化过程中API的变更分为结构变更和行为变更。结构变更表示变更了API对应方法的方法签名,此类变更会导致客户端程序无法成功编译执行,行为变更表示改变了API的功能。Kapur等[11]开发了迁移工具Trident,开发者输入弃用API和替换API,该工具即可自动扫描项目中的弃用API并将其替换为指定的API。但该工具仅能从文本上对弃用API进行替换,并未适配代码上下文。Strobl等[12]开发了两个工具用来迁移弃用API。Generator可以根据一些启发式规则生成.xml格式的配置文件,而JaSCUT则根据配置文件对源码中的弃用API进行迁移。然而该工具仅能迁移弃用API的名称,无法从更细粒度的级别进行迁移。Henkel等[13]开发了Eclipse插件Catch!,该工具可以记录开发者迁移弃用API的操作,并将这些操作回放到相同的弃用API上。但是该工具需要类库提供者花费额外的时间录制脚本,同时由于代码上下文不同,回放结果经常不能满足用户的需要。Dagenais等[14]开发了弃用API迁移推荐系统SemDiff,该系统通过分析类库在标记弃用API时如何适应自身的变更来抽取迁移策略。以上方法在一定程度上提升了开发者迁移弃用API的效率,然而这些方法经常受到文档和类库代码质量的约束,迁移效果往往不能满足用户的需求。

1.2 Stack Overflow相关研究

Vásquez等[15]发现API的变更会引发Stack Overflow中关于变更API的讨论。Vasilescu等[16]调研了问答网站对开发者的影响,结果表明尽管参与问答过程会花费时间,但是却能够在一定程度上提升开发者的开发效率。Rahman等[9]开发了代码搜索插件RACK,该插件结合IDE中代码上下文自动从Stack Overflow和Github中搜索代码示例。Gu等[17]利用深度学习将API序列与自然语言关联起来,在开发者搜索时可以为其推荐包含相关API序列的代码示例。李宇琨等[8]将Stack Overflow中的问答信息对应到相关代码元素上,再利用代码元素从Github中搜索代码示例。

与上述研究相比,本文方法可以在开发者不指明替换API的情况下为其提供替换API的描述和代码示例。同时,为了便于开发者参考,结果将以特定的规则进行排序。此外,该方法会根据替换API简化代码示例,使得代码示例更加清晰。

2 方法总览

图1展示了弃用API迁移建议推荐技术的方法流程,其中:圆角矩形表示组件;矩形表示输入与输出;箭头上的文字表示组件的输入与产出。该过程以弃用API的相关信息为输入,经过问答帖收集器、快照生成器、分类器和优化器等组件的加工步骤后,生成迁移建议。

图1 弃用API迁移建议推荐技术方法流程

弃用API的相关信息不仅包含弃用API的所属类、方法名、参数的类型与数量,还包括API文档中的迁移信息。问答帖收集器可以根据弃用API的元素从Stack Overflow中抽取相关帖子及其附加信息,并对帖子进行筛选过滤,生成回答列表。快照生成器以特定的规则分析帖子中的回答,生成回答快照。回答快照记录了帖子中某个回答的关键信息,包括文本信息、代码示例、该回答的附加信息。分类器可以从替换API的角度对快照进行分类,产生不同的快照集。最后,优化器根据特定的规则,参考文档中的迁移信息,从两个维度上对快照进行排序。同时还会对回答中的代码示例进行简化,移除无意义的语句或表达式,从而使迁移建议更加清晰。

3 迁移建议推荐技术的实现

3.1 弃用API问答帖的收集

问答帖收集包括搜索和筛选两个步骤。搜索步骤是指根据弃用API和关键词组成的搜索条件从Stack Overflow中搜索相关问答帖的过程。筛选步骤的目的是去除搜索结果中的重复帖子或与目标弃用API无关的帖子。

Stack Overflow提供了不同类型的搜索功能,用户可以从不同的维度上搜索相关问题,例如标签、回答、用户、投票数、是否有被接受的回答、关键词等维度。本文工作以“[deprecated]+{alternative deprecate…}+{弃用API名称}”作为搜索模板,根据弃用API填充搜索模板生成搜索条件,调用Stack Exchange提供的接口从Stack Overflow中搜索问答帖,之后经过筛选过滤选取足够数量的回答。

在搜索问答帖的过程中经常会遇到搜索结果太少或结果中排序靠后的帖子相关性不高的情况。针对这一问题,本文结合Stack Overflow的某些特征来改善搜索策略。Stack Overflow会为相似问题的帖子打上“[duplicate]”标记。同时会在问题的开始部分展示与该问题相似的帖子链接。利用这一特征可以收集到更多的问答帖,在搜索帖子时,如果发现标题中有该标记,则同时收集此帖子中指示的相似问答帖。除此之外,本文还通过变更搜索条件来扩大搜索范围,此方式称为降维搜索,即删减部分关键词或去除搜索条件中的“[deprecated]”标签来重新组织搜索条件。

搜索结果中包含一些不相关的问答帖,例如非Java语言或讨论内容与输入的弃用API不一致的帖子。因此需要对搜索结果进行过滤。此过程从两个方面进行,一方面去除无关问答帖,只保留与弃用API有关的帖子,另一方面移除帖子中低质量的回答。

筛选问答帖的规则如下:1) 移除没有回答的讨论帖。迁移建议主要从回答中产生,因此只考虑有回答的讨论帖。2) 筛选Java语言(包括安卓)相关的讨论帖。本文工作提出的技术只适用于Java语言,暂不考虑对其他语言的支持。3) 筛选与输入弃用API相关的讨论帖。尽管讨论其他API的帖子可能存在一些有用的信息,但这种情况很少出现,故排除此情况。具体操作是首先移除回答数为0的帖子,之后通过判断问答帖标签中是否包含与编程语言有关的标签来确定帖子关联的编程语言,若没有此类标签则从标题和文本中提取编程语言关键词,移除非Java语言的帖子。最后通过文本匹配的方式在帖子的标题和正文中匹配弃用API的名称,将匹配失败的帖子从列表中移除。

筛选回答的规则是将投票数少于0且没有代码示例的回答从列表中移除。具体操作是根据帖子得到回答的ID列表,再根据ID列表依次得到回答的信息,例如文本信息、投票数或回答用户。在回答的文本中匹配

标签,帖子中的代码示例都是用此标签包裹的,若没有此标签则证明该回答中不包括代码示例。将上述两个条件都不满足的回答从帖子中删除,之后再次判断各个帖子的回答数重新筛选问答帖。

在问答帖收集的过程中需要记录帖子的相关信息,例如帖子在搜索结果中的顺序、投票数、回答数、回答的投票数、回答有无代码示例。这些信息将作为对迁移建议进行排序的依据。

3.2 回答分析与快照生成

快照生成器可以分析帖子中的回答并生成回答快照。回答快照包括文本部分、代码部分、附加信息。文本部分指回答文本中包含方法调用或代码元素的语句。这些语句通常包含着对弃用API的替换建议,甚至是对替换API使用方法的介绍。代码部分指与迁移建议有关的Java代码示例。附加信息指回答的额外信息,例如回答中包含的API集合、回答所属帖子的相关信息、回答本身的相关情况等信息。

文本部分由回答中包含方法调用的语句组成。对于回答中的文本信息,首先以句子为单位将文本分割成语句列表。语句列表中的语句除了包含纯本文之外,还包括HTML标签,例如

等。接着依次对语句列表中的语句进行分析。对于任意语句,如果符合任意以下规则则属于文本部分:1) 语句中包含方法调用。使用表示方法调用的正则表达式进行匹配,如果匹配成功则表示语句中包含方法调用。2) 语句中包含标签。以包裹的单词表示代码元素(例如方法调用或类型名称),这些元素通常代表了可供选择的替换建议。3) 被
标签包裹的语句。此类型的语句通常是引用API文档或其他官方说明的语句。4) 语句中存在超链接。在语句中通常以超链接的形式表达关键信息,如果该超链接不是URL则将其认定为关键信息。5) 语句中存在replaced with/by等表示替换的单词或短语。该步骤的实现方式是首先判断语句中是否包含
标签,如果包含则属于文本部分。之后判断语句中是否包含非URL的超链接,如果包含满足条件的超链接,则此语句属于文本部分。接着使用表示方法调用的正则表达式匹配语句文本,若匹配成功则此语句属于文本部分。最后判断语句中是否存在表示替换含义的单词或短语,若存在这些单词或短语则此语句属于文本部分。

代码部分由回答中所有的Java代码片段组成。Stack Overflow中使用

标签组合包裹代码片段。一个回答中可能包含多个代码片段且部分代码片段可能与替换API无关,例如由其他语言编写的代码或不包含API的代码。对于任意代码片段,如果符合以下规则则属于代码部分:1) 代码由Java语言编写。2) 至少包含一个方法调用语句。3) 内容不是Exception输出信息。

附加信息是对回答进行排序的重要依据,包括回答包含的API集合、回答所属的帖子、回答所属帖子在搜索结果中的排序、回答的时间、是否被接受和投票数等信息。API集合由文本部分和代码部分中出现过的方法调用组成。附加信息中的其他部分可以很容易地通过解析HTML文本获得。

图2展示了Stack Overflow中关于迁移弃用API CharMatcher.javaDigit()的回答。该回答中回答者引用了官方文档对该弃用API的解释,同时提出了迁移该弃用API的建议,最后给出了替换API的代码示例。通过上述步骤为该回答生成回答快照,图中下划线选中的语句为文本部分,矩形框选中的部分为代码部分,图中下半部分展示了分析该回答得到的附加信息。

图2 回答快照示例

3.3 回答快照的分类

在生成回答快照后,按照附加信息中的API集合对其进行分类。API集合中的API可以分为两种类型:关键API(K_API)和普通API(N_API)。如果某个API同时存在于一个回答的文本部分和代码部分中,或该API是弃用API文档的迁移信息中指示的替换API,则此API为关键API。若该API只存在于两个快照中的其中一个,则为普通API。

在本文工作中,我们认为同时出现在文本部分和代码部分中的替换API应该是回答者更推荐的API,同时官方文档中描述的替换API同样值得被推荐。因此,为了得到更加精准、有价值的替换API,回答快照将根据关键API进行分类。回答快照的分类结果是若干个快照集,快照集的类型由关键API决定,即一个关键API对应一个快照集。在分类之前,首先收集所有回答快照中的关键API,对关键API进行去重后为每一个关键API生成快照集。在对快照进行分类时,依次遍历API集合中的API。对于任意一个API,如果有对应的快照集,则将该API所属的回答快照放入对应的快照集。对于没有对应快照集的API,则将其忽略。由于回答快照中可能包含多个API,因此一个回答快照可能会被放入多个快照集。

图3是对回答快照进行分类的示意图。图中n个快照中有四个关键API(A,B,C,D),因此可以分为四类并产生四个快照集。快照1有五个API(A,B,C,E,F),其中A、B、C分别能找到对应的快照集,可以将快照1放入相应的快照集。剩余的两个API(E,F)无法找到对应快照集,因此将它们忽略。其余的快照可以使用相同的规则将其加入到快照集。

图3 回答快照分类示意图

3.4 回答快照的排序

对回答快照进行排序可以帮助开发者更快地确定替换API进而完成迁移工作。本文从两个维度上对其进行排序:1) 对同一个快照集内的回答快照排序。2) 对代表不同替换API的快照集排序。

快照集包含多个回答快照,可以根据快照的附加信息对其打分并根据最后的分值进行排序。表1展示了快照集内回答快照的评分规则,并列出了各个规则下可能的分值。以下是对评分标准的详细介绍。

1) 所属帖子在搜结果中的顺序。帖子在搜索结果中越靠前则分值越高。排名最高帖子中的回答评分为5,随着排名下降,分值依次减1,最低为1分。不同的搜索轮次有不同的权值。使用完整的搜索条件搜索到的帖子权值为4,在减少搜索条件后,权值相应减少。删减部分关键词权值为3,移除标签[deprecated]或完全删除关键词权值为2,若只使用弃用API的名称进行搜索则权值为1。搜索过程中重复的帖子(即被[duplicate]标记的帖子)拥有相同的权值。回答快照在此部分中的评分是权值与分数的乘积。

2) 回答是否被接受。被提问者接受的回答应该有更高的分数。在此部分中,被接受的回答快照的评分为10,其余的回答快照没有评分。

3) 投票数。投票数的高低表明回答被认可的程度。回答快照在此部分中的评分为获得投票的数量。

4) 回答快照的完整性。代码部分通常比文本部分更具有参考价值。若快照中包含代码部分,则评分加2,若包含文本部分,则评分加1。因此,如果回答快照同时包含上述两个部分,则评分为3。

5) 回答下的评论。评论在一定程度上可以反映回答被关注的程度。若包含两条以上非作者本人的回答,则评分为3。若除作者以外的评论者大于等于两人,则评分为5。其余情况在此部分中的评分为1。

6) 回答者的声望。回答的质量与回答者的声望有关联。若回答者的声望大于10 000,则评分为3。若回答者的声望处在1 000至10 000之间,则此回答的评分为2。声望小于1 000的回答者的回答评分为1。

表1 快照集内回答快照的评分规则

回答快照的最终评分等于以上各部分评分的和。评分高的回答更具备参考价值。快照集中的回答快照最终将以评分逆序的形式进行排序。在此过程中可能会出现评分相同的回答快照,本文根据回答时间对评分相同的快照进行排序,回答时间越晚则排名更靠前。

每一个快照集代表一个替换API,对快照集进行排序可以使开发者在迁移过程中快速选择合适的替换API。此步骤同样以评分的方式对快照集进行排序。表2展示了快照集的评分规则,并列出了各个规则下可能的分值。以下是对评分标准的详细介绍。

1) 文档迁移信息中的替换API。文档中的迁移信息由类库的维护者提供,相比其他途径,从迁移信息中获得的替换API更能够满足开发者的需求。因此,此过程中文档提供的替换API对应的快照集评分为10。代表其他替换API的快照集没有评分。

2) 快照集包含的快照数。快照集中的回答快照数量反映了对应替换API被推荐的程度。包含最多快照数量的快照集评分为10,随数量的降低依次减少1分,最低评分为1分。

3) 快照集中排名前三的快照评分总和。回答快照的评分已经反映了替换API被认可的程度,可以参考快照评分对快照集进行排序。由于不同快照集包含的回答快照数量不同,同时为了避免低质量的回答对平均值的影响,此过程中使用每个快照集中排名前三快照的评分总和作为评分依据。评分总和最多的快照集评分为10分,随着评分总和的降低依次减少1分,最低评分为1分。

表2 快照集的评分规则

与对回答快照进行排序的方式相同,此步骤同样以各部分的评分和作为排序依据,并以评分逆序的形式作为最终结果。因为快照集的数量有限,此步骤不需要对评分相同的快照集进行额外的排序。

3.5 代码示例的简化

回答快照中的代码示例通常包含着很多API,使得替换API的用法不能被很清晰地呈现出来。为了帮助开发者快速掌握替换API的使用方法,本工作中会根据替换API对回答快照中的代码示例进行简化。

抽象语法树是代码分析的基础,该步骤需要为待简化的代码示例建立抽象语法树,以此来分析示例中替换API与上下文的关系。然而,Stack Overflow中的代码示例通常是无法单独编译运行的代码片段。传统的抽象语法树解析器(例如JavaParser)无法解析这些代码片段[18]。本文通过正则表达式从示例中匹配代码结构并将其组织成抽象语法树的形式,从而为代码片段生成抽象语法树。

代码示例通常是以方法声明或语句(Statement)为单位呈现的,因此本文忽略了方法声明及以上的结构类型,同时也忽略了不常见的结构,例如Lambda表达式等。表3展示了部分结构类型及相应的示例。其中包含常见的选择结构(if,switch)和循环结构(while,do-while,for,foreach),也包含了普通的表达式结构,例如变量声明(VarDeclare)、方法调用(MethodCall)和赋值表达式(Assign)。此外还包含一些语句结构,例如方法返回值结构(ReturnStmt)和异常处理结构(TryStmt)。除了表3中列出的结构,该步骤还对一些更基础的结构(例如二元表达式、字符串表达式等)做了相似的处理。

表3 抽象语法树的部分结构类型

本文通过分析代码示例中不同语句与替换API关系来对代码示例进行简化。首先从抽象语法树中定位替换API的使用位置,并从替换API中抽取元素(即API调用者和参数)。之后遍历树中的节点,找到与这些元素相关的节点。元素与节点之间的相关性分为两种类型:1) 运行该节点的代码会导致元素的状态发生改变,这种相关性称为写相关。2) 该节点的代码只是使用元素进行了其他的操作,未改变元素的状态,这种相关性称为读相关。写相关的节点包括元素被赋值的赋值表达式、声明元素的变量声明语句、元素作为调用者或参数的方法调用。读相关的节点包括元素参与的赋值表达式或变量声明等语句。该步骤仅考虑写相关的节点,从写相关的节点中分离出会决定这些元素的其他元素。例如变量A是变量B经过一系列操作后得到的,则变量B的改变会导致变量A改变,即变量A由变量B决定。重复上述过程,找到其他元素对应的写相关的节点,直到找到所有与替换API元素有写相关关系的节点。最后将这些写相关节点的访问类型设置为“WRITE”,从抽象语法树中移除访问类型不为“WRITE”的节点,剩余的节点可以转化为简化后的代码示例。简化结果取决于替换API,根据不同的替换API简化同一段代码示例会产生不同的结果。

算法1展示了简化代码示例的过程。该算法以rAPI(替换API)和AST(抽象语法树)为输入,通过分析后确定AST中与替换API元素具有写相关关系的节点,在修改这些节点的访问类型后返回整个AST。首先根据替换API从AST中定位对应的节点(第2行),并从该节点中提取替换API的元素,放置到有序集合elements中(第3行)。依次遍历elements中的元素,对于每一个元素,从AST中搜索所有与该元素有写相关关系的节点,并放置到列表nodes中(第5行)。之后遍历nodes中的节点,从这些节点中搜索可以决定elements中元素的相关元素,并将这些元素添加至elements的末尾(第6-第9行)。在添加元素时,elements会过滤重复的元素,因此不会出现死循环的情况。最后,将AST中与elements中的任意元素有写相关关系节点的访问类型设置成“WRITE”并返回AST(第11-第16行)。

算法1根据替换API简化代码示例算法

1 function Code_Simplify(rAPI,AST)

2 rNode ← find(rAPI,AST)

3 elements ← extract(rNode)

4 for all e∈elements do

5 nodes ← findNodeByElement(e,AST)

6 for all n∈nodes do

7 relatedElements ← findRelatedElement(n,elements)

8 elements.addAll(relatedElements)

9 end for

10 end for

11 for all n∈AST do

12 if accessWrite(n,elements) then

13 n.accessType ← WRITE

14 end if

15 end for

16 return AST

17 end function

算法1中判断节点之间的关系是通过数据流的方式实现的。现有技术无法对代码片段生成数据流图,因此,本文采用了较为简单的文本匹配的方式来匹配不同语句中相同的变量,以此为不同节点中的变量建立数据流关系。该方法建立的数据流关系基本可以满足确定节点之间关系的需求。

图4展示了根据替换API简化代码示例。图中左半部分是未简化过的代码示例,右半部分是使用上述方法对其进行简化后的代码示例。该示例中的替换API是Calendar.get()。该代码示例对应的抽象语法树如图4所示。其中括号中的数字表示该节点对应代码中的行号。在对该代码示例进行简化时,首先确定替换API的使用位置。从替换API中可以提取出元素cal和Calendar.YEAR,由于参数Calendar.YEAR是常量,因此只需要对cal进行分析。根据算法1,与cal有关的节点对应的代码是第5-第7行。在这几行中,可以决定cal的元素只有date,对date进行分析后得出第3行对应的节点与该元素有写相关关系。最终将第3、第5-第7行代码对应节点的访问类型设置为“WRITE”。图5中矩形框选中的节点表示访问类型为“WRITE”的节点。将这些节点翻译成代码得到简化后的代码示例。

图4 简化代码示例

图5 代码示例的抽象语法树

4 工具与实验

4.1 工具介绍

基于上文介绍的技术,我们设计并开发了弃用API迁移辅助工具,图6展示了该工具的用户界面。该工具是一个桌面客户端应用,用户可以很方便地使用该工具对弃用API进行迁移。

图6 弃用API迁移建议推荐工具用户界面

用户首先点击左上角的“打开项目”按钮,选择客户端项目加载到工具中。工具会扫描项目中的Java文件并检测弃用API,同时以删除线的形式标记弃用API。用户点击弃用API所在行的“迁移”按钮后,该工具会显示替换API和迁移建议。替换API列表展示了问答帖中所有回答推荐的替换API。点击其中的替换API,右下方会显示对应的迁移建议。迁移建议展示了一个快照集中经过排序的回答快照,每个迁移建议包含所属问答帖的标题、文本信息、代码示例。用户可以点击标题右侧的“打开原帖>>”即可跳转至Stack Overflow中该帖子的网页。此外,用户点击“迁移建议”右侧的“只看代码”即可屏蔽迁移建议的文本信息。

此外,该工具还提供了一些额外的基础功能,例如打开项目、代码文本编辑器、访问外部链接和弃用API定位等功能。这些功能可以为开发者带来更好的体验。

4.2 实验准备

为验证本文方法和技术的有效性和实用性,设计了用户实验。我们选择了12个在Stack Overflow中有相关讨论的弃用API,根据这些API的功能和所属类库将它们分为5组。分别为这5组弃用API添加代码上下文形成5个可以成功编译的代码片段。每个代码片段对应一个任务,表4展示了5个任务中的弃用API与其所属的类库。

表4 实验任务介绍

本实验邀请了10名Java开发者并将他们分为实验组和控制组,每组5名实验者。实验组的任务是使用工具为弃用API生成迁移建议,并且参考生成的迁移建议迁移代码片段中的弃用API。控制组的任务是在Stack Overflow中搜索弃用API的相关讨论帖,参考帖子中的讨论迁移代码片段中的弃用API。迁移成功的标准是代码片段中的弃用API全部被迁移且代码片段仍然可以被成功编译。

实验过程中会记录参与者完成每个任务的耗时,如果参与者完成某个任务超过20 min或放弃任务,则将耗时记录为20 min。同时,实验组成员需要对工具生成的迁移建议进行评分。评分共分为四个档:1分表示生成的迁移建议完全没有参考价值,例如生成的迁移建议可读性差或推荐了完全错误的替换API。2分表示迁移建议仅推荐了正确的替换API,但参与者无法从文本部分或代码部分中学习替换API的使用方法。3分表示迁移建议推荐了正确的替换API且文本部分和代码部分具有一定的参考价值,但参与者仍然需要打开原帖查看原始信息才能完全迁移弃用API。4分表示参与者只需要参考工具生成的迁移建议即可完成迁移任务。实验组成员需要对5个任务中所有为弃用API生成的迁移建议进行评分。

4.3 实验结果分析

表5展示了两组成员在用户实验中的耗时以及实验组成员对迁移建议评分的平均值、最大值和最小值。从时间角度来看,实验组成员在任务1、2、4中的平均耗时大约比控制组少2 min左右,原因是控制组成员需要耗费额外的时间去Stack Overflow中寻找相关讨论帖,同时要总结多个讨论帖中的内容并选择最合适的替换API。而从评分角度来看,在这三个任务中,实验组成员给分最高的为4分,最低为2分,平均分均在3分以上,说明工具为这三个任务中的弃用API生成的迁移建议具有较高的参考价值。部分参与者在实验2、实验4中给了2分,原因是他们认为生成的迁移建议过滤掉了原帖对替换API参数的介绍,导致他们无法直接通过参考代码示例完成任务。

表5 用户实验结果

实验3和实验5中实验组成员的平均耗时与控制组相差不大。两组成员同时表示在迁移实验3中的弃用API Component.mouseDown(Event,int,int)时耗费了大量时间,甚至部分参与者直接放弃任务。尽管在Stack Overflow中可以找到关于该API的讨论帖,然而大部分帖子中的回答并未提供替换API及其使用方式。两组成员仅用帖子中少量的替换API描述信息迁移该API,因此都耗费了大量的时间修改替换API使其符合代码上下文语法规范。迁移实验5中的两个弃用API难度较小,且Stack Overflow中关于两个API迁移建议的讨论较为集中,回答者的观点也类似,因此两组成员在任务5中的耗时较少。从评分角度来看,实验组成员对实验3的迁移建议评分较低,平均分只有2.5分,表明工具对迁移难度大或Stack Overflow中讨论较少的弃用API支持力度不足。实验组成员对难度较低的实验5给出了较高的评分,表明该工具对迁移难度较低或帖子讨论集中的弃用API具有良好的支持度。

总体而言,该实验中实验组成员的表现优于控制组。实验结果表明,本文提出的方法和工具可以显著提高客户端开发者迁移弃用API的效率。

5 结 语

本文提出基于问答平台的弃用API迁移建议推荐技术,该技术根据弃用API从问答网站中收集相关讨论帖,对帖子中的回答进行过滤、分类、排序、简化代码示例等操作后生成可供开发者参考的迁移建议。基于此技术设计并实现了弃用API迁移辅助工具,实验结果表明该工具可以显著提高开发者迁移弃用API的效率。

本文的方法仍然具有不足之处。首先,该方法对迁移难度较大或讨论较少的弃用API支持度有待提高,之后的工作会结合自然语言处理技术来应对复杂的文本结构,以此来提供更好的迁移支持。其次,该方法仅能将迁移建议以文本和代码示例的方式推荐给用户,不能从这些信息中抽取出可以自动化适配到客户端的迁移策略,之后的工作中会结合一些机器学习相关技术根据文本和代码生成迁移策略,提高方法的智能化程度,进一步减少开发者的工作量。