基于实体识别的软件开发问答网站中的API讨论主题分析

2019-07-15 11:18和晓健赵文耘
计算机应用与软件 2019年7期
关键词:开发人员帖子类别

和晓健 彭 鑫 赵文耘

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

0 引 言

开发人员在论坛与博客中经常分享自己的编程经验,或者提出在程序开发运行中遇到的问题,寻求专业人员的帮助与解答。Stack Overflow作为世界上最大的软件开发问答网站,目前已经有来自230多万注册用户的超过1 700万帖子讨论关于编程语言、操作系统、数据库、算法等各类与程序设计相关的问题。如果能够挖掘网站中包含的软件开发知识,将给后续的研究带来巨大帮助。

要抽取出开发人员讨论中的有用知识,就需要有效的技术识别出讨论文本中的计算机软件领域实体。实体识别属于自然语言处理中的关键性基础任务,在通用领域的文本中对人名、地名、机构名、日期、时间等的识别已经有了成熟的技术并达到了较高的准确度。但是由于语言习惯以及个人偏好等方面的差异,开发人员在问答网站中提及某个计算机软件领域相关实体时,往往将它以纯文本的形式混杂在自然语言文本中,而且经常使用非规范化的表示,从而影响了其他开发人员的阅读并且妨碍了自然语言处理程序对文本的自动化分析,最终造成了知识抽取的不准确。

API是编程语言中极为重要的一个部分,它封装了某个功能的实现细节,使得开发者只需调用该接口就能快速方便地编写程序而无需了解其具体实现。然而关于问答网站中开发人员对于API的讨论情况,如API在文本中所属的句子成分以及API是在什么情况下被讨论的研究还比较缺乏。所以为了帮助后续研究者更好地聚焦开发者在讨论不同API时所关心的问题,以及更好地构建自然语言处理程序解析软件领域的文本,同时考虑到Java API与Android API作为目前流行的智能设备中广泛使用的编程语言类库,所以本文选择对Stack Overflow中包含这两类标签的帖子进行分析。通过收集当前流行版本中包括的Java与Android API,并且使用一些规则生成这些API对应的一系列别名,然后对帖子的文本内容进行匹配识别,最终得到对应的API。通过对开发者常用的10个API进行具体分析,发现开发人员在讨论中最常见的三类情形依次是:程序出错求助、原理及使用方法询问、不同API比较差异。而在句式上,开发者倾向于在主语、宾语和状语中提及API,词组形式出现的API别名还面临着与其他同名API混淆的情况。

1 相关工作

1.1 API相关研究

Robillard等[1]使用正则表达式和启发式规则将项目文档中的词与代码中相似的术语如类、方法等进行链接。Rigby等[2]利用正则表达式识别Stack Overflow讨论中涉及的API,然后借助决策树模型训练分类器,最终得到与讨论内容最相关的API。Subramanian等[3]针对Stack Overflow帖子中的代码片段,设计了一个简单地迭代式算法,先通过名字匹配找到候选的API,然后结合参数个数、参数类型、返回值类型等,缩小候选集直到输出唯一结果。Treude等[4]提出机器学习的方法提取Stack Overflow帖子中的某些特征并进行有监督训练,然后将得到的相关度排序结果进行比较,最终筛选出与某个API相关的有意义的句子补充显示在官方文档中。Jiang等[5]对API官方文档中的文本进行实体识别、代词和变量消解、句子识别和句子类型识别,最后使用主题模型和PageRank进行相似度计算,从而给用户推荐与查询API相关的文本片段。Gall[6]针对API官方文档与源代码可能有差异的问题,利用程序分析从源代码中获取抽象语法树并归纳代码中包含的约束,再使用自然语言处理技术人工归纳文档中的规则并自动化的抽取约束,最终对范围约束、控制约束、类型约束这三类的约束进行文档中和代码实现的差异对比,从而帮助用户正确使用API。APIBot[7]在现有的人工智能助手SiriusQA的基础上进行修改,将API官方文档上的结构化信息提取出来,然后归纳可回答的问题类型;再判断问题语句中的API名字是否包含在文档中方法筛选候选集,然后使用通用问答模式和领域知识两种方法计算相似度;最后进行与问题相关的官方文档内文本推荐。可以发现在项目内以及官方文档上的API研究较多,而在Stack Overflow上进行的API研究则是集中于API的识别以及与官方文档内容的匹配,缺少对于开发人员的API讨论主题与习惯的研究。

1.2 Stack Overflow相关研究

Anderson等[8]将Stack Overflow帖子中的一个问题与它的所有回答作为基本单元,然后随着社区活动的不断进行,观察帖子的最佳回答与一些特征的关系,最后归纳投票与声誉机制的一系列特点。Vasilescu等[9]认为问答网站能够帮助开发人员提高知识并加快开发过程,但参与问答过程也可能影响正常工作的效率,所以针对Github内的用户代码修改过程以及其在Stack Overflow的发帖情况进行了分析。Movshovitz-Attias等[10]挖掘出Stack Overflow中不同声誉的用户的发帖模式,并通过对用户的交互网络进行图分析,发现能对网站做出长期贡献的开发人员。Ye等[11]使用CRF模型,综合了字典、词形、词语聚类特征,通过有监督训练得到实体识别模型并将Stack Overflow帖子中的软件实体分成预定义的5类,从而帮助用户更好地理解不同概念。可以看到之前的研究偏向Stack Overflow本身的机制及用户发帖行为上的研究,而本文的研究将在更细的粒度上针对用户发帖中涉及的API领域进行句式和语义上的归纳分析。

2 API实体识别

API实体识别整体流程如图1所示。先解析官方文档页面进行API实体集合的收集,然后定义别名生成规则构造API别名库,最后进行文本匹配识别出Stack Overflow帖子中用户讨论的API。

图1 API实体识别流程概述

2.1 API实体集合收集

本文依据Java和Android官方文档页面的布局样式,构建包装器对其页面结构进行解析,得到当前使用广泛的Java 8以及Android 26版本中的所有API实体(即包、类、接口、方法、字段)及其全限定名。代表API实体的全限定名示例如下:

(1) java.util代表包含Java中常用工具类的包;

(2) java.lang.Integer代表Java中基本数据类型int的封装类;

(3) java.lang.Cloneable代表Java中需要实现clone方法的类所需要的接口;

(4) android.widget.TextView.setText(java.lang.CharSequence text)代表Android中文本组件设置文本的方法(方法内的参数类型除基本数据类型外均使用类的全限定名);

(5) java.lang.Integer.MAX_VALUE代表Java中整数数据类型中的最大整数值。

2.2 API别名库构造

由于开发人员在问答网站中交流问题时,或因为自己的表达习惯,或因为某些API的广泛使用性以及对其他用户专业水平的认可,会使用各种各样的别名来替代API实体的全限定名形式。所以为了分析开发人员对于较为通用的别名的讨论情况,本文定义如下形式的规则生成API别名:

(1) API实体的全限定名;

(2) API实体全限定名最后一个点号之后的部分;

(3) 简单方法名与简单参数类型;

(4) 简单方法名与参数名;

(5) 简单API名按照驼峰式命名拆分后的词组;

(6) 简单API名按照下划线拆分后的词组。

其中:(3)、(4)仅针对API方法。以方法API android.widget.TextView.setText(java.lang.CharSequence text)为例,除第1类别名外可以生成别名:setText(java.lang.CharSequence text);setText(CharSequence);setText(text);set text。而字段API java.lang.Integer.MAX_VALUE不能生成第5类别名,但是存在第6类别名integer max value。通过对所有API根据相匹配的规则生成别名,最终得到API别名库。

2.3 文本内API识别

使用Beautiful Soup对Stack Overflow帖子进行去标签处理,然后借助NLTK对文本内容进行分词及大小写转换等处理,最后对文本内容与别名库中别名在同为小写的形式下进行最大匹配(即别名完全出现在文本的某个词语中),则代表该用户在帖子中提及别名对应的API实体。

3 Stack Overflow内API提及情况分析

3.1 实验准备

根据网络上常用Java和Android API的讨论,本文选择表1中所列的10个API作为研究对象。通过上述提出的API实体识别方法,在包含Java和Android标签的Stack Overflow帖子内对每个API识别出的100个帖子进行人工分析。为了公平探讨不同别名形式的API的使用情况,对于API的不同别名取包含该别名的同等数量帖子进行分析(即API有5个别名,则取含有每个别名的20条帖子)。

表1 常用API介绍

续表1

3.2 实验结果分析

对于android.app.Activity API,50个包含第1类别名的帖子中,32次别名出现在词语cast to之后,即用户出现了类型转换的程序错误;7次别名出现在import之后,作为基础类进行引用;7次别名出现在assignable to之后,表示用户遇到了方法参数类型使用错误的情况;有个别的别名出现在class之后,表示用户特指该类;以及有用户对该API有设计原理上的提问如图2所示。可以发现,Activity API的第1类别名在句子中以宾语的成分出现较多,偶尔存在主语情况。另外50个第2类别名activity中,别名基本以in activity、an activity、my activity和main activity的形式出现,且在句子中作为状语,而此时用户帖子一般讨论的内容并非以该API为中心,而是其他出现在此组件中的元素。

图2 Activity类全限定名形式别名出现情况

对于java.lang.String API,50次第1类别名中,22次作为方法参数出现;5次作为方法返回值在方法名前出现;剩下的情况则作为主语和宾语,搭配不固定。第1类的别名提及主要是关于Java中String类型的特点讨论以及作为其他API的组成部分出现较多。第2类别名String,18次出现在convert to词组中,表现了用户们对于String与其他类型的转换比较关心;18次以Java表达式的赋值类型出现;剩余的出现情况则是如String a and b、getText()(returns String) method这样的非规范的自然语言形式。

java.util.Scanner API的第1类别名21次出现在import之后;与using搭配作为状语出现了7次;其他大多是以宾语形式出现。从整体语义上来看,将近70%的讨论是关于导入该类后编译的错误,其他的多为使用方法上的问题讨论。而以scanner为表现形式的别名中,13次是表达式赋值类型;12次是以scanner class整体词组的形式出现;其他的则非固定地后接method、object等词。该类别名依然是与异常错误相关的讨论最多,其次则是对于不同输入读取方法的比较优劣,最后是对功能的介绍讨论。

java.lang.NullPointerException API由于本身所代表的报错含义,所以100个帖子中83个是各种情况下程序出错的求助,且用户们出现最多的错误是数据库相关错误、字符串相关错误以及swing控件出现的错误,剩下17个则是与其原理相关的继承使用、捕获顺序等方面的讨论。该API的三类别名形式均以宾语的形式出现最多,其中第1类、第2类别名在receive、get等词语后出现较为常见。

java.io.InputStreamReader API对应的第1类别名中,半数以上的别名出现在in和at之后作为状语表示报错情况,剩余的大部分情况是作为import的对象进行导入。经分析发现,绝大多数报错是与XML格式数据解析相关的,少数是其使用方法的讨论。第2类别名常出现在with、using、in之后作为状语,大部分是与该API使用时的缓冲区机制与编码格式的讨论,少数是与其他流读取API的比较,很少有程序报错相关的提问。第5类别名词组以主语及宾语的形式较多出现,且大多是与网络通信及多线程读取相关的API特性讨论如图3所示,极少是程序出错的提问。

图3 InputStreamReader类驼峰式分词别名出现情况

对于点击事件注册方法的API,第1类、第2类全限定名别名可能是由于书写过于繁琐的原因,分别只有1个和2个帖子以这样的形式提及该API,且出现在代码片段中。除去第2类别名括号中的形参l的形式在帖子中较常见,其与第3类别名在句子中的成分大多为句子主语或宾语,且两者基本都在讨论程序出错。第4类别名由于符合Android语言规范中方法调用的形式,所以全部出现在代码片段中。第5类别名虽然以set词语开头,但是除70%情况是以谓语的形式出现外,还有30%的情况是以词组整体作为主语和宾语。第4类、第5两类别名均以使用方法的介绍问答为主。

java.util.Date.getTime() API的33次包含第1类别名的帖子中,21次作为主语,剩下的情况为宾语。其中,宾语出现的帖子基本是位于词语method后描述调用该方法时程序出错,主语情况则以解释功能居多,少数是不同获取时间戳的方法之间的比较以及对于输出格式的讨论。第2类别名中半数以Date类型对象的方法调用形式出现,其余大多在using、with、from后作为状语。用途上多为不同API之间的比较,少数为相同条件下多次调用该方法结果不一致的讨论。第5类别名get time由于较为符合日常交流的方式,多为谓语动词词组,且在语境中表示用户意图为主,很少特指该API。

android.view.View.findViewById(int id)第1类别名没有被用户提及,但是去除了括号内的形参id后的形式出现十分广泛,且均会以如图4所示的Android标准空指针异常的形式作为文本出现。第2类别名以主语和宾语的成分对半出现,大多数是与方法返回值类型的转换有关的问题,少数是方法原理讨论与程序出错。第3类别名均为程序错误问题,绝大多数为实际情况下方法参数不正确的错误,少数为该非静态方法在静态上下文中调用的错误。第4类别名出现极少,观察发现用户习惯用实际参数来代替形参id。第5类别名中主语、谓语、宾语、状语出现的情况较为平均,主要为程序错误描述和使用方法询问。

图4 findViewById方法特殊别名出现情况

Android文本框文本设置API的第1类别名与findViewById的第1类别名情形比较相似,也是去除形参text的形式出现广泛,且是以相同句式讨论异常错误。第2类别名在帖子中也极少出现,考虑到可能是因为CharSequence类型属于开发者较为熟知的类型,所以无需以全限定名的形式出现在方法中。第3类别名基本以主语形式出现,且20个帖子中18个是与程序出错相关,其余2个则为与其他重载方法的对比。第4类别名只有1次出现,且作为状语出现在with后,值得注意的是开发者们倾向于使用无参的方法setText()在文中指代该方法。第5类别名在帖子中常作为谓语,而语义上开发者们更倾向于与文本的其他属性相关的讨论,如文本大小、文本颜色等,而不是使用该API设置文本。

在Java获取数据库连接的API中,前两类别名可能是因为过于冗长,没用实际使用的样例。第3类、第4类别名基本作为主语和宾语进行使用介绍。第5类别名大多数属于谓语成分,且由于略去方法参数,所以大部分的讨论是关于同名无参的HTTP API方法的讨论,剩余的一部分有如何建立数据库连接的讨论以及连接中包导入路径错误等的问题。

综合分析Stack Overflow中对于API的用户讨论,如图5所示,在句子成分上,不符合自然语言表达习惯的文本很多,其中API常作为导入的语句以及赋值表达式;在正常文本中,宾语形式的API出现最多,之后是相差不太大的主语和状语,最后是谓语。且前四类单词式别名以主语、宾语、状语为主,后两类词组式别名多为谓语。如图6所示,从语义上来看,用户们最常见的讨论还是关于程序出错求助,其次是使用原理及方法探讨,最后是同类型API间的比较。值得注意的是,用户们还常常使用实参或无参的方法来指代有参方法,对于名称过长或是其中参数类型过长的API,用户们习惯简写形式,所以后续研究者在进行API识别时需要特殊考虑。

图5 Stack Overflow用户API讨论所属句子成分分布

图6 Stack Overflow用户API讨论语义分布

4 讨论与分析

基于本文的研究结果,后续研究者可以针对Stack Overflow中用户在API讨论中句式上的习惯和偏好,有针对性地修改现有的如StanfordNLP、ClausIE等依存语法分析工具,更好地自动化抽取Stack Overflow数据中与API讨论相关的主谓宾三元组,从而获取更多在实际开发中用户发掘的API特性。

针对不同API讨论中涉及的语义主题,编程语言的开发者可以深入挖掘,探索不同API引发不同类型的程序异常的原因,分析用户对于API的使用需求,以及细化相似API所适用的不同场景,从而优化后续API版本的开发以及更好地编写官方文档,最终方便用户的使用。

实体链接是实体识别之后对于API识别的最终步骤,而在越来越多深度学习的技术被应用在该领域的情况下,本文发现的不同API在被用户讨论时的语法和语义的特点,将有助于探索那些特征更有利于构建深度学习的模型,从而更好地解决广泛存在的同名API链接困难以及API与概念难区分的问题。

5 结 语

本文针对软件开发问答网站中对于开发者关于API讨论的研究较少的问题,收集Java与Android API集合,定义别名规则构造别名库,通过文本匹配进行文本内API的实体识别。分析了10个常用的Java和Android API 在Stack Overflow中的讨论主题,得到了一系列对于后续研究人员有帮助的Stack Overflow中用户关于API的语法和语义偏好。

猜你喜欢
开发人员帖子类别
一起去图书馆吧
Semtech发布LoRa Basics 以加速物联网应用
简析基于概率预测的网络数学模型建构
暴力老妈
后悔了?教你隐藏开发人员选项
选相纸 打照片
三星SMI扩展Java论坛 开发人员可用母语
高手是这样拍马屁的
我是怎样在坛子里堕落的