亚洲免费av电影一区二区三区,日韩爱爱视频,51精品视频一区二区三区,91视频爱爱,日韩欧美在线播放视频,中文字幕少妇AV,亚洲电影中文字幕,久久久久亚洲av成人网址,久久综合视频网站,国产在线不卡免费播放

        ?

        基于變更類型和相似性比較的代碼重構(gòu)模式識(shí)別

        2018-05-23 11:46:20孫美榮楊春花

        孫美榮 楊春花

        摘 要: 在現(xiàn)代軟件開(kāi)發(fā)和維護(hù)中重構(gòu)是提高軟件可維護(hù)性和軟件質(zhì)量的常用手段。而大量重構(gòu)模式摻雜在日常的bug修復(fù)、功能增加等代碼變更中,使得變更理解變得非常復(fù)雜。因此,提出一種對(duì)常見(jiàn)的抽取方法和抽取類重構(gòu)模式的識(shí)別算法。研究基于工具ChangeDistiller和JDiff分別獲取變更類型和抽取代碼塊,通過(guò)判斷移動(dòng)后的代碼塊與原文件變更代碼的關(guān)系,識(shí)別采取的重構(gòu)模式。該算法在4個(gè)開(kāi)源項(xiàng)目中進(jìn)行實(shí)驗(yàn),其平均準(zhǔn)確率在80%左右。

        關(guān)鍵詞: 重構(gòu)模式;抽取方法;抽取類

        Abstract:Refactoring is a common way of improving software maintainability and software quality in modern software development and maintenance. In daily revision refactoring patterns are usually mixed with code changes accomplishing other tasks such as bug fixing and feature addition which makes the change understanding very complicated. The paper proposes an identifying algorithm for refactoring patterns including the extract method and extract class. It is based on ChangeDistiller and JDiff that are used to get code changes types and extract code blocks respectively. Then the algorithm will identify the refactoring pattern according to the characteristics of the relationship between the changed codes and the original codes. The algorithm has been tested on 4 open source projects with an average 80% accuracy.

        Key words: refactoring patterns;extract method;extract class

        引言

        重構(gòu)[1]是現(xiàn)代軟件開(kāi)發(fā)和維護(hù)中用于提高軟件可維護(hù)性和軟件質(zhì)量的常用手段?,F(xiàn)代的軟件開(kāi)發(fā)一般基于版本管理系統(tǒng)設(shè)計(jì)實(shí)現(xiàn),軟件工程師為了維護(hù)系統(tǒng)或提高系統(tǒng)的性能每天會(huì)提交大量的代碼。而大量重構(gòu)模式摻雜在日常的bug修復(fù)、功能增加等代碼變更中,使得代碼評(píng)審者和軟件工程師在理解代碼時(shí)不得不對(duì)代碼進(jìn)行人工探查,以區(qū)分哪些變更的代碼是重構(gòu),哪些不是。因此,為了使得變更的代碼易于理解,將重構(gòu)模式從代碼變更中隔離出來(lái)是非常必要的。

        重構(gòu)[2]是一種基于規(guī)則、經(jīng)過(guò)訓(xùn)練、有條不紊的程序整理方法,在整理過(guò)程中可以將不小心引入的錯(cuò)誤降低。重構(gòu)是處理代碼壞味的一種常用手段。當(dāng)前,在對(duì)重構(gòu)方法的研究方面包括基于K-最近鄰的C克隆代碼重構(gòu)方法[3]、使用抽象語(yǔ)法樹(shù)和靜態(tài)分析的克隆代碼自重構(gòu)方法[3]、基于抽象語(yǔ)法樹(shù)和多態(tài)機(jī)制的復(fù)雜條件語(yǔ)句自動(dòng)重構(gòu)研究[4]、長(zhǎng)方法壞味重構(gòu)選擇策略[5]等等。

        重構(gòu)模式的識(shí)別是在變更后的代碼中尋找符合特定重構(gòu)模式的代碼修改,是重構(gòu)的反過(guò)程。劉陽(yáng)[6]等人提出了一種重構(gòu)檢測(cè)算法,是基于版本元素匹配原理,對(duì)函數(shù)抽取重構(gòu)進(jìn)行了識(shí)別,但是并沒(méi)有涉及其它類型的重構(gòu)模式。

        通過(guò)對(duì)4個(gè)開(kāi)源項(xiàng)目的變更代碼進(jìn)行探查,研究發(fā)現(xiàn)抽取方法、抽取類等是最為常見(jiàn)的重構(gòu)模式。因此,本文對(duì)這2種重構(gòu)模式進(jìn)行了研究,提出了識(shí)別的算法。

        1 抽取方法與抽取類的重構(gòu)模式的識(shí)別

        1.1 抽取方法與抽取類模式

        圖1是抽取方法(Extract Method)模式的示例。其中,V1是變更前的版本,V2是變更后的版本。對(duì)比兩版本,V2中多了一個(gè)含參數(shù)的新增方法printDetails,且V1 中4~5行的內(nèi)容抽取到V2的新增方法5~7行中,則在V2相對(duì)于V1刪除代碼的位置有對(duì)方法printDetails進(jìn)行調(diào)用。

        抽取方法的表現(xiàn)形式有3種,分別是:沒(méi)有局部變量的代碼塊移動(dòng)、有局部變量的代碼塊移動(dòng)、對(duì)局部變量再賦值。圖1中的抽取方法重構(gòu)是有局部變量代碼塊移動(dòng)模式。

        抽取類(Extract Class)[7]重構(gòu)模式,一般用于處理過(guò)長(zhǎng)的類。一個(gè)類如果包含過(guò)多的功能及屬性,會(huì)導(dǎo)致這個(gè)類過(guò)于臃腫。為了提高類的高內(nèi)聚,低耦合,就會(huì)將一些不必要的或不常用的方法提煉到另一個(gè)類中,來(lái)為這個(gè)類服務(wù)。如圖2 是一個(gè)抽取類模式的示例,用類圖形式展示。類Person中過(guò)多的屬性officeAreaCode和officeNumber以及功能代碼getTelephoneNumber()被抽取到了一個(gè)新類TelephoneNumber中,且在移動(dòng)代碼的地方增加對(duì)新類的引用。

        1.2 識(shí)別方法

        1.2.1 抽取方法模式識(shí)別

        根據(jù)上述抽取方法和抽取類模式的例子,不難發(fā)現(xiàn),屬于抽取方法和抽取類兩種模式的代碼變更具備如下3個(gè)特性:

        (1)文件中有新增方法或提交的revision_id中含有新增類文件。

        (2)抽取代碼塊移動(dòng)到某個(gè)方法中。

        (3)在刪除代碼的位置有對(duì)該方法的引用。

        為了識(shí)別這3個(gè)特性,研究借用ChangeDistiller(https://bitbucket.org/sealuzh/tools-changedistiller/src/)工具獲得一個(gè)文件變更前后所有的代碼變更類型。這是Fluri[8]等人編寫(xiě)的一個(gè)Tree differ 算法,對(duì)變更前后抽象語(yǔ)法樹(shù)進(jìn)行對(duì)比,獲取分類的變更。同時(shí),也可以區(qū)別多種方法類型的變化或類等級(jí)上的變化。

        但是ChangeDistiller只能獲取原有方法中的新增語(yǔ)句,不能獲取新增方法中的語(yǔ)句體。為此,研究又對(duì)ChangeDistiller進(jìn)行了些許擴(kuò)展,使其可以返回每個(gè)代碼變更的代碼行或代碼行范圍。例如,對(duì)于一個(gè)新增方法printDetails,ChangeDistiller返回的變更類型為ADDITIONAL_FUNCTIONALITY: printDetails()。擴(kuò)展后,將返回該方法的行號(hào)范圍5~10。

        基于每個(gè)新增方法變更的行號(hào)范圍,研究中借用文本比較工具JDiff(https://maven.apache.org/archives/maven-1,x/plugins/jdiff)來(lái)獲取該方法的方法體。JDiff是一種面向行的文本比較(text diff)工具,用于顯示同一文件2個(gè)版本之間的更改。

        另外,對(duì)于新增方法中的代碼塊和刪除的代碼塊之間的移動(dòng)關(guān)系判斷,進(jìn)一步借助了Levevshtein(https://en.wikipedia.org/wiki/Levenshtein_distance)算法。Levevshtein是一種計(jì)算2個(gè)字符串間的差異程度的字符串度量(string metric)算法,即一個(gè)單詞變成另一個(gè)單詞要求的最少單個(gè)字符編輯數(shù)量(如:刪除、插入和替換)。

        圖3顯示了該算法的框架,其中l(wèi)eft,right分別表示變更前后的兩文件,left是變更前版本,right表示變更后版本。研究可得算法設(shè)計(jì)流程如下:

        (1)代碼變更抽取。通過(guò)ChangeDistiller獲取所有類型的代碼變更,包括新增的方法、刪除的語(yǔ)句、原方法中新增的語(yǔ)句等。一個(gè)代碼變更由變更類型(ChangeType)、變更實(shí)體(ChangeEntiy)和變更雙親實(shí)體(ParentEntity)構(gòu)成。根據(jù)研究中對(duì)ChangeDistiller的擴(kuò)展,對(duì)每個(gè)新增方法madd,將對(duì)應(yīng)一個(gè)行號(hào)范圍(beginline endline)。

        (2)方法體語(yǔ)句的獲取。根據(jù)新增方法的行號(hào)范圍通過(guò)JDiff獲取代碼塊。此步驟的結(jié)果是一個(gè)元組的集合EMADD={ |。 madd是一個(gè)新增方法,ladd =ladd1 ... laddn是madd方法體中的所有語(yǔ)句}。

        (3)代碼變更分組。通過(guò)上述步驟(1),所有刪除的語(yǔ)句行,以及原方法中新增的語(yǔ)句行都已經(jīng)獲得。然后就可將所有刪除和新增的語(yǔ)句根據(jù)有關(guān)的方法父類實(shí)體進(jìn)行分組。此步驟的結(jié)果是一個(gè)元組的集合MCHANGE={ < mname linsert ldelete >| mname是方法名稱,linsert =linsert1 ... linsertn是該方法內(nèi)部增加的語(yǔ)句,ldelete = ldelete1 ... ldeletem是刪除的語(yǔ)句}。

        (4)代碼塊抽取判定。步驟(2)中獲得的所有新增方法的代碼行塊,與步驟(3)中獲取的所有刪除的代碼塊,進(jìn)行相似度比較,判斷是否存在代碼塊抽取。

        (5)模式判定。若塊b1=和塊b2=< mname linsert ldelete >滿足抽取關(guān)系,即b2.ldelete 與b1.ladd具有相似度,則通過(guò)如下關(guān)系判斷是否存在抽取方法模式:對(duì)方法mname內(nèi)的每條新增語(yǔ)句linsert i∈b2. LINSERT,判斷方法是否調(diào)用madd,調(diào)用語(yǔ)句如圖1,即:

        V2:METHOD_INVOCATION:printDetails(outstanding

        1.2.2 抽取類模式識(shí)別

        抽取類模式識(shí)別與抽取方法模式識(shí)別的步驟基本相似;算法框架略。在此,可給出算法步驟分述如下。

        (1)代碼變更抽取。通過(guò)ChangeDistiller獲取所有類型的代碼變更。擴(kuò)展方法獲取revision_id中新增類文件fnew,及所有方法MADD。

        (2)代碼變更分組。 同抽取方法步驟(3)。

        (3)方法體語(yǔ)句的獲取。根據(jù)步驟(2)中的MCHANGE,在fnew中獲取與ldelete相似的代碼塊ladd。根據(jù)ladd歸屬的方法分組EMADD={ |madd是方法名稱,ladd =ladd1 ... ladd n是madd方法體中的所有語(yǔ)句}。

        (4)同抽取方法步驟(4)。

        (5)模式判定。若塊b1=和塊b2=< mname linsert ldelete >滿足抽取關(guān)系,即b2.ldelete 與b1.ladd存在相似度,則通過(guò)如下關(guān)系判斷是否存在抽取方法模式:對(duì)方法mname內(nèi)的每條新增語(yǔ)句linsert i∈b2. LINSERT,判斷方法是否調(diào)用madd,調(diào)用語(yǔ)句如圖2,即:

        V2:FIELD: person.officeTelephone: TelephoneNumber;officeTelephone.getTelephoneNumber()

        1.3 算法

        編寫(xiě)抽取方法與抽取類重構(gòu)模式識(shí)別的偽代碼算法。本次研究中,關(guān)鍵設(shè)計(jì)的偽代碼可見(jiàn)如下:

        對(duì)給定某個(gè)程序的2個(gè)相鄰版本進(jìn)行重構(gòu)模式識(shí)別的判定,revision_id表示一次提交。其中,兩版本中的變更集合存放在Schange中,Schange是一個(gè)元組的集合;Schange ={ < ctype centity ,cparententity>| cd是一條代碼變更,ctype = ctype1 ... ctypen是語(yǔ)句變更的類型,centity = centity1 ... centitym是語(yǔ)句變更的實(shí)體,cparententity = cparententity1 ..., cparententityk是語(yǔ)句變更位置的雙親}。

        算法偽代碼中第5行通過(guò)ChangeDistiller可知f是否為變更文件;第13行中的mname是根據(jù)Schange.cparententity獲得;第28行中的新增文件fnew是根據(jù)本次提交的revision_id與上次revision_id-1進(jìn)行比較獲得;第29行根據(jù)類的反射機(jī)制獲取fnew中的所有方法Madd;第47行返回所有成功識(shí)別的重構(gòu)模式集合P。

        2 實(shí)驗(yàn)驗(yàn)證

        2.1 數(shù)據(jù)源

        為了驗(yàn)證實(shí)驗(yàn)的可執(zhí)行性,過(guò)程中通過(guò)minigit(https://github.com/3ofcoins/minigit/)工具獲取了4個(gè)開(kāi)源項(xiàng)目進(jìn)行驗(yàn)證。分別為:jEdit、maven、goole_guice、eclipse,利用MySql根據(jù)各項(xiàng)目提交的日志篩選出將近10年的重構(gòu)revision_id,然后對(duì)篩選出的重構(gòu)revision_id進(jìn)行人工檢測(cè),表1即為篩選出的抽取方法、抽取類兩種重構(gòu)模式的基本詳細(xì)信息。具體內(nèi)容詳述如下。

        (1)jEdit( http://sourceforge.net/project/jedit/)是一個(gè)跨平臺(tái)的文本編輯器。數(shù)據(jù)獲取時(shí)間段為:1998/09/27~2012/08/08,本次實(shí)驗(yàn)人工檢測(cè)JEdit發(fā)生重構(gòu)的revision_id數(shù)目為45個(gè)版本,含有的總文件數(shù)目548個(gè)。

        (2)maven(http://maven.apache.org/dowload.cgi)是對(duì)象模型(POM),可以通過(guò)一小段描述信息來(lái)管理項(xiàng)目的構(gòu)建、報(bào)告和文檔的軟件項(xiàng)目管理工具。數(shù)據(jù)獲取時(shí)間段為:2003/09/02~2014/01/29,本次實(shí)驗(yàn)人工檢測(cè)maven發(fā)生重構(gòu)的revision_id數(shù)目為123個(gè)版本,含有的總文件數(shù)目為1 494個(gè)。

        (3)goole_guice(https://github.com/apress/goo-gle guice),讀作"juice")是超輕量級(jí)的,下一代的,為Java 5及后續(xù)版本設(shè)計(jì)的依賴注入容器。數(shù)據(jù)獲取時(shí)間段為:2006/08/23~2013/12/12,本次實(shí)驗(yàn)人工檢測(cè)goole_guice發(fā)生重構(gòu)的revision_id數(shù)目為25個(gè)版本,含有的總文件數(shù)目為567個(gè)。

        (4)eclipse(http://www.eclipse.org/downloads/eclipse-packages/)是一個(gè)開(kāi)放源代碼的、基于Java的可擴(kuò)展開(kāi)發(fā)平臺(tái)。數(shù)據(jù)獲取時(shí)間段為:2001/06/23~2013/10/16,本次實(shí)驗(yàn)人工檢測(cè)eclipse發(fā)生重構(gòu)的revision_id數(shù)目為20個(gè)版本,含有的總文件數(shù)目為175個(gè)。

        2.2 結(jié)果及實(shí)驗(yàn)分析

        圖4、5是變更前后的兩文件,圖6是該算法對(duì)這一變更檢測(cè)的詳細(xì)信息輸出。

        圖4、圖5給出了ChangeDistiller獲取的新增方法injectMirror,以及由JDiff結(jié)合Levenshtein獲取的抽取代碼塊,ML(502~514)方法體行號(hào)范圍。

        該實(shí)驗(yàn)對(duì)4個(gè)Java開(kāi)源項(xiàng)目中的數(shù)據(jù)進(jìn)行驗(yàn)證,每個(gè)項(xiàng)目中有30~100個(gè)重構(gòu)revison_id版本,對(duì)表1中的數(shù)據(jù)進(jìn)行驗(yàn)證,因?yàn)槊總€(gè)revison_id版本中包含多個(gè)文件,所以重構(gòu)檢測(cè)不止對(duì)一個(gè)文件進(jìn)行操作。通過(guò)實(shí)驗(yàn)后檢測(cè)得到的實(shí)驗(yàn)結(jié)果,可見(jiàn)表2。

        通過(guò)表2可以得出,該實(shí)驗(yàn)測(cè)定運(yùn)行的抽取方法和抽取類的檢測(cè)結(jié)果的平均準(zhǔn)確率為80%,準(zhǔn)確率在75%~82.5%之間略有波動(dòng)。準(zhǔn)確率沒(méi)有達(dá)到100%的原因與相似度值選取有關(guān)。本文是借用Levenshtein算法比較兩字符串的相似性,對(duì)于閾值的選取是關(guān)鍵原因。閾值選取過(guò)高,降低了準(zhǔn)確率;閾值選取過(guò)小,則會(huì)大大降低查準(zhǔn)率。因此,對(duì)代碼相似度算法的選取也是后續(xù)研發(fā)的重要工作之一。

        3 結(jié)束語(yǔ)

        本文中,研究提出一種基于ChangeDistiller和文本差異工具識(shí)別變更代碼中重構(gòu)模式的算法,并通過(guò)4個(gè)開(kāi)源試驗(yàn)成功識(shí)別了抽取方法和抽取類兩種重構(gòu)模式。未來(lái)工作可有針對(duì)性地圍繞如下工作展開(kāi)研究:

        (1)獲取更多的相關(guān)數(shù)據(jù)進(jìn)行驗(yàn)證。

        (2)對(duì)Extract Superclass、Move Method等模式進(jìn)行研究。

        參考文獻(xiàn)

        [1] MURPHYHILL E PARNIN C BLACK A P. How we refactor and how we know it[J]. IEEE 31st international conference on Software Engineering. Vancouver BC Canada:IEEE 2009:287-297.

        [2] FOWLER M BECK K ROBERTS D et al. Refactoring improving the design of existing code[M]. Sebastopol CA:Addison-Wesley Professional 1999.

        [3] 于冬琦 彭鑫 趙文耘. 使用抽象語(yǔ)法樹(shù)和靜態(tài)分析的克隆代碼自動(dòng)重構(gòu)方法[J]. 小型微型計(jì)算機(jī)系統(tǒng) 2009 30(9):1752-1760.

        [4] 劉偉 胡志剛 劉宏韜. 基于抽象語(yǔ)法樹(shù)和多態(tài)機(jī)制的復(fù)雜條件語(yǔ)句自動(dòng)重構(gòu)研究[J]. 電子科技大學(xué)學(xué)報(bào) 2014 43(5):736-741.

        [5] 馬飛飛 吳海濤. 長(zhǎng)方法壞味重構(gòu)選擇策略[J]. 計(jì)算機(jī)應(yīng)用 2014,34(s1):284-286,293.

        [6] 劉陽(yáng) 劉秋榮 劉輝. 函數(shù)抽取重構(gòu)的自動(dòng)檢測(cè)方法[J]. 計(jì)算機(jī)科學(xué) 2015 42(12):105-107.

        [7] FOKAEFS M TSANTALIS N STROULIA E et al. Identification and application of Extract Class refactorings in object-oriented systems[J]. Journal of Systems & Software 2012 85(10):2241-2260.

        [8] FLURI B GALL H C. Classifying change types for qualifying change couplings[C]//International Conference on Program Comprehension (2006). Athens Greece:IEEE 2006:35-45.

        亚洲天堂手机在线| 无套熟女av呻吟在线观看| 国产精品兄妹在线观看麻豆| 国产第19页精品| 啊v在线视频| 白嫩少妇高潮喷水av| 无码熟妇人妻av在线影片最多| 欧美日韩视频无码一区二区三| 欧美xxxx新一区二区三区| 麻豆三级视频网站在线观看| 国产av无码专区亚洲a∨毛片| 熟妇人妻无乱码中文字幕 | 日韩精品夜色二区91久久久| 久久精品国产色蜜蜜麻豆国语版| 成人做受视频试看60秒| 在线综合网| 丰满人妻一区二区三区免费| 一区二区三区四区国产99| 四虎国产精品免费久久| 97福利视频| 亚洲天堂男人的av天堂| 亚洲中文字幕久久精品蜜桃| 亚洲中文字幕无码久久2020| 久久久久久AV无码成人| 久久久亚洲免费视频网| 日本乱偷人妻中文字幕| 日本免费人成视频播放| 国产一级黄片久久免费看| 精品无码国产一区二区三区麻豆| 人人爽人人爽人人爽| 亚洲人成网站18男男| 国产国语按摩对白av在线观看| 免费看黑人男阳茎进女阳道视频| 久久久久久人妻精品一区百度网盘| 日韩精品有码中文字幕| 欧美日韩午夜群交多人轮换| 国产肉体ⅹxxx137大胆| 久久综合一本中文字幕| 国产人妖网站在线视频| 国产精品v欧美精品v日韩精品| 男性一插就想射是因为啥|