石偉 楊春花
摘 要:代碼變更的理解一般基于文本差異化工具,其處理輸出的基本對(duì)象是一個(gè)變更塊(hunk)。許多重構(gòu)都摻雜在日常的bug修改、功能特征的增加等代碼變更中,將重構(gòu)與其它工作隔離有利于對(duì)代碼變更的理解?,F(xiàn)有的代碼可視化方法僅展示變更文本,未進(jìn)行代碼變更前后重構(gòu)模式的展示,沒有發(fā)揮出可視化技術(shù)的優(yōu)越性。本文基于變更塊對(duì)代碼重構(gòu)模式進(jìn)行展示,以抽取方法為例,在4個(gè)開源項(xiàng)目中進(jìn)行實(shí)驗(yàn),并取得了理想的展示效果。
關(guān)鍵詞: 變更塊;重構(gòu);抽取方法;重構(gòu)模式展示
文章編號(hào): 2095-2163(2019)03-0085-04?中圖分類號(hào): TP311.5?文獻(xiàn)標(biāo)志碼: A
0?引?言
代碼變更的理解一般基于文本差異化工具,并且各種版本的管理工具中都集成了某種文本差異化工具,幫助用戶查看文本代碼變更情況,而文本差異化工具處理輸出的基本單位就是變更塊(hunk)。因此,基于變更塊對(duì)代碼重構(gòu)模式進(jìn)行分析展示,有利于將來(lái)可以較容易地集成到版本管理工具中。
重構(gòu)[1]是調(diào)整軟件結(jié)構(gòu)的一種手段,在不對(duì)軟件功能特征進(jìn)行更改的條件下,提高軟件的可理解性和可維護(hù)性。重構(gòu)在軟件演化過(guò)程中存在普遍性,檢測(cè)并移除復(fù)雜代碼已經(jīng)成為軟件生命周期中重構(gòu)階段的基本工作。在理解代碼變更時(shí),將變更數(shù)據(jù)抽取出來(lái)進(jìn)行相應(yīng)的可視化展示,將有助于代碼重構(gòu)分析人員區(qū)分哪些代碼存在重構(gòu)關(guān)系,幫助其高效地理解代碼是如何進(jìn)行變更的。目前,對(duì)于重構(gòu)檢測(cè)及可視化技術(shù)方面的研究,包括函數(shù)抽取重構(gòu)的檢測(cè)算法[2]、基于深度學(xué)習(xí)的代碼克隆檢測(cè)技術(shù)[3]、基于軟件度量的函數(shù)提取重構(gòu)方法[4]、基于索引的分布式代碼克隆檢測(cè)[5]、克隆代碼可視化的研究[6]等。
本文設(shè)計(jì)了一種基于變更塊的代碼重構(gòu)模式展示方法,將存在重構(gòu)關(guān)系的變更塊分組,并以恰當(dāng)?shù)姆绞秸故荆故咀兏鼔K類內(nèi)、類間重構(gòu)關(guān)系,以便于用戶對(duì)重構(gòu)數(shù)據(jù)進(jìn)行分析和研究。
1?基于hunk的代碼重構(gòu)模式展示方法
展示方法針對(duì)一個(gè)源代碼文件的2個(gè)連續(xù)修改版本進(jìn)行分析處理,利用文本差異化工具對(duì)這2個(gè)連續(xù)版本進(jìn)行變更塊數(shù)據(jù)信息的抽取,將變更塊數(shù)據(jù)進(jìn)行相應(yīng)的展示。然后,通過(guò)重構(gòu)識(shí)別分析工具對(duì)變更塊數(shù)據(jù)信息做出抽取、研究分析,判斷其是否存在重構(gòu)模式、存在哪種模式的重構(gòu)模式。最后,利用重構(gòu)模式識(shí)別過(guò)程獲取的重構(gòu)模式、變更內(nèi)容等參數(shù),結(jié)合不同的重構(gòu)模式使用不同展示方式選取對(duì)應(yīng)的重構(gòu)模式展示模板,對(duì)重構(gòu)模式給出相應(yīng)的展示。展示方法框架如圖1所示。展示方法的流程步驟描述見如下。
(1)hunk數(shù)據(jù)的獲取。hunk是一個(gè)代碼變更塊,可通過(guò)文本差異化工具進(jìn)行獲取,是文本差異化工具處理輸出的基本單位。其中包含了代碼變更前后刪除或增加的代碼信息及其行號(hào)范圍信息,如圖2和圖3所示,都是一個(gè)hunk。
(2)hunk展示。hunk展示方面普遍采用的方式有2種。一種是集中式展示,如圖2所示。另一種是并排式展示,如圖3所示。
(3)重構(gòu)模式識(shí)別。利用重構(gòu)模式識(shí)別算法對(duì)獲取的代碼變更塊數(shù)據(jù)進(jìn)行重構(gòu)模式識(shí)別,判斷其存在的重構(gòu)模式,并獲取重構(gòu)模式名稱、變更類型、變更實(shí)體、變更內(nèi)容、行號(hào)范圍等參數(shù)信息。
(4)重構(gòu)模式展示模板集。由于重構(gòu)模式的種類較多,不同的重構(gòu)模式具有不同的特征屬性,所以要對(duì)變更塊數(shù)據(jù)存在的重構(gòu)模式進(jìn)行展示就不能采用單一的展示模式,而是要根據(jù)各種重構(gòu)模式不同的特征屬性,對(duì)不同的重構(gòu)模式設(shè)計(jì)不同的展示模式。
(5)重構(gòu)模式的選取。根據(jù)重構(gòu)模式識(shí)別獲取的重構(gòu)模式參數(shù),對(duì)重構(gòu)模式展示模板集中的重構(gòu)模式模板進(jìn)行選取。
(6)重構(gòu)模式展示。界面布局采用JQuery EasyUI布局插件Layout布局,通過(guò)嵌套進(jìn)行復(fù)雜的界面布局,通過(guò)布局將界面分為相應(yīng)的區(qū)域,分別展示不同的信息。
2?展示方法的實(shí)現(xiàn)—以抽取方法為例
2.1?方法實(shí)現(xiàn)
2.1.1?變更塊獲取與展示
變更塊數(shù)據(jù)的獲取采用GNU Diff(http://www.gnu.org/software/diffutils/)文本差異化工具,其處理輸出的基本對(duì)象是一個(gè)變更塊(hunk)。GNU Diff文本差異化工具可以顯示文件是否不同,提供了一些方法來(lái)抑制某些看起來(lái)不重要的差異。最常見的是,這種差異是指文字或線條之間的空白量的變化。工具還提供了方法來(lái)抑制字母表中的差異,或者與匹配的正規(guī)表達(dá)式的行相匹配,將2個(gè)文檔的內(nèi)容參照比較,以便用戶對(duì)文檔內(nèi)容信息進(jìn)行分析和處理。
變更塊數(shù)據(jù)的展示采用普遍使用的集中式展示,將同一個(gè)源文件的2個(gè)連續(xù)版本中的變更塊數(shù)據(jù)信息進(jìn)行合并處理,變更塊前后變更數(shù)據(jù)代碼行用不同顏色標(biāo)注出來(lái),每個(gè)變更塊變更數(shù)據(jù)上下都保留3行未發(fā)生變更的代碼行數(shù)據(jù),并在變更塊數(shù)據(jù)代碼行前標(biāo)明變更前后的代碼行號(hào),以便后續(xù)用于對(duì)變更塊數(shù)據(jù)的理解、分析和處理。
2.1.2?重構(gòu)模式分析處理與展示
重構(gòu)模式的分析處理借鑒孫美榮等人[7]研究提出的識(shí)別變更代碼重構(gòu)模式算法,并引入一些改進(jìn)對(duì)重構(gòu)模式進(jìn)行識(shí)別。原算法利用ChangeDistiller(https://bitbucket.org/sealuzh/tools-changedistiller/src/)工具獲取變更類型,JDiff(http://javadiff.sourceforge.net/)文本差異化工具進(jìn)行變更塊抽取,Levenshtein(https://en.wikipedia.org/wiki/Levenshtein_distance)算法進(jìn)行字符串差異度量。其中,ChangeDistiller工具是Fluri等人[8-9]編寫的一個(gè)Tree differ算法。由于本文使用的文本差異化工具是GNU Diff工具,即需將該算法中的文本差異化工具JDiff工具換成GNU Diff工具,以達(dá)到文本比較、變更數(shù)據(jù)獲取的目的。重構(gòu)模式分析處理的基本過(guò)程是:先根據(jù)GNU Diff文本差異化工具獲取相應(yīng)的代碼變更塊數(shù)據(jù),再通過(guò)ChangeDistiller工具獲取代碼變更的所有類型,記錄其行號(hào)范圍,同時(shí)將根據(jù)相關(guān)的父類實(shí)體對(duì)新增語(yǔ)句和刪除語(yǔ)句進(jìn)行分組,獲得一個(gè)元組集合。根據(jù)GNU Diff文本差異化工具獲取相應(yīng)的代碼變更塊,將獲取的新增代碼變更塊和刪除代碼變更塊進(jìn)行相似度比較,判斷是否存在代碼變更塊抽取。最后,對(duì)存在變更塊抽取的文件進(jìn)行重構(gòu)模式判斷,判斷其是否符合相應(yīng)的重構(gòu)模式關(guān)系,并對(duì)相關(guān)重構(gòu)模式變更數(shù)據(jù)進(jìn)行抽取。
重構(gòu)模式的展示根據(jù)重構(gòu)模式識(shí)別獲取的重構(gòu)模式參數(shù)選取相應(yīng)的重構(gòu)模式模板進(jìn)行重構(gòu)模式展示。
2.2?方法驗(yàn)證
數(shù)據(jù)來(lái)源于通過(guò)MiniGit(https://github.com/Software Introspection Lab/MiniGit)工具獲取的4個(gè)開源項(xiàng)目數(shù)據(jù),以驗(yàn)證展示方法實(shí)現(xiàn)的可行性。4個(gè)開源項(xiàng)目分別為:eclipse.jdt.core、google-guice、jEdit、maven,各項(xiàng)目信息參見表1。
本文以抽取方法重構(gòu)模式為例,對(duì)存在重構(gòu)模式的代碼變更塊數(shù)據(jù)進(jìn)行展示。抽取方法重構(gòu)模式就是將一個(gè)過(guò)長(zhǎng)的方法或一段需要注釋用途的代碼放入一個(gè)獨(dú)立的方法中,用獨(dú)立方法的名稱解釋該方法的用途。此示例的源文件數(shù)據(jù)取自maven開源項(xiàng)目,2個(gè)連續(xù)的文件提交版本分別是:684eed4a0c97bbbcc6e01432105d5b15e0e4f9b2和a4 8ae318c671c9904801
0183227d078d19dc972b,文件名稱是DefaultMavenExecutionRequestPopulator.java。首先,通過(guò)GNU Diff文本差異化工具對(duì)2個(gè)文件進(jìn)行變更塊數(shù)據(jù)的獲取,然后通過(guò)重構(gòu)識(shí)別工具對(duì)變更塊數(shù)據(jù)開展重構(gòu)模式識(shí)別,獲取變更語(yǔ)句的詳細(xì)信息,包括變更類型、變更實(shí)體、變更內(nèi)容、行號(hào)等,對(duì)存在重構(gòu)模式的變更塊數(shù)據(jù)進(jìn)行提取,選擇抽取方法重構(gòu)模式的相應(yīng)展示模式實(shí)現(xiàn)效果展示。
抽取方法重構(gòu)模式展示有3個(gè)參數(shù),分別為:被抽取變更塊、抽取變更塊、新增方法名。其中,被抽取變更塊有時(shí)不止有一個(gè),是可增加的。如圖4所示。
此示例源文件的2個(gè)連續(xù)文件提交版本數(shù)據(jù)的獲取是利用XLoadTree 組件對(duì)數(shù)據(jù)庫(kù)數(shù)據(jù)按數(shù)據(jù)的倉(cāng)庫(kù)信息進(jìn)行分層,展示每個(gè)倉(cāng)庫(kù)中的所有文件修改版本,再對(duì)每個(gè)文件修改版本下的所有文件進(jìn)行分層展示得到的。XLoadTree 組件是基于AJAX和XML的動(dòng)態(tài)加載JS樹組件,通過(guò)對(duì)樹節(jié)點(diǎn)的source屬性定義指向一個(gè)xml文件,從而使數(shù)據(jù)進(jìn)行載入,還可以包含嵌套的子節(jié)點(diǎn)以及指向其它xml文件的子節(jié)點(diǎn),利用DOM進(jìn)行轉(zhuǎn)換。本地?cái)?shù)據(jù)目錄樹如圖5所示。
變更塊數(shù)據(jù)展示采用集中式展示的方式,將每個(gè)變更塊的數(shù)據(jù)信息展示到界面上,變更塊展示如圖6所示。
重構(gòu)模式展示通過(guò)對(duì)變更塊數(shù)據(jù)的分析處理,獲取存在抽取方法重構(gòu)模式的變更塊,本示例中被抽取變更塊有2個(gè),將重構(gòu)模式中被抽取變更塊數(shù)據(jù)填充到左邊框架,抽取變更塊數(shù)據(jù)填充到右邊框架,中間用箭頭和新增方法名解釋該方法的用途,以便對(duì)重構(gòu)模式的分析和理解。重構(gòu)模式展示如圖7所示。
3?結(jié)束語(yǔ)
本文設(shè)計(jì)了一種基于變更塊的代碼重構(gòu)模式的展示方法,以抽取方法為例實(shí)現(xiàn)了對(duì)一個(gè)源文件的2個(gè)連續(xù)版本中存在抽取方法重構(gòu)模式的相關(guān)展示,使代碼重構(gòu)變得更加簡(jiǎn)單、直觀,發(fā)揮出了可視化技術(shù)的優(yōu)越性,為理解代碼重構(gòu)提供了便利。
參考文獻(xiàn)
[1]FOWLER M,BECK K,BRANT J,et al. Refactoring: Improving the design of existing code[M]. Sebastopol,CA:Addison-Wesley Professional,1999.
[2]?劉陽(yáng),劉秋榮,劉輝. ?函數(shù)抽取重構(gòu)的自動(dòng)檢測(cè)方法[J]. 計(jì)算機(jī)科學(xué),2015,42(12):105-107.
[3]?劉復(fù)星,魏金津,任女爾. ?基于深度學(xué)習(xí)的代碼克隆檢測(cè)技術(shù)研究[J]. 電腦知識(shí)與技術(shù),2018,14(18):178-179,185.
[4]?馮燕,肖笛. 基于軟件度量的函數(shù)提取重構(gòu)初探[J]. 數(shù)字技術(shù)與應(yīng)用,2017(6):254,256.
[5]?林嬋,李俊杰,饒飛,等. 基于索引的分布式代碼克隆檢測(cè)[J]. 信息安全研究,2016,2(3):201-210.
[6]?何薔. 克隆代碼可視化系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)[D]. 哈爾濱:哈爾濱工業(yè)大學(xué),2015.
[7]?孫美榮,楊春花. 基于變更類型和相似性比較的代碼重構(gòu)模式識(shí)別[J]. 智能計(jì)算機(jī)與應(yīng)用,2018,8(2):25-29,34.
[8]?FLURI B,GALL H C.Classifying change types for qualifying change couplings[C]//Proceedings of the 14th International Conference on Program Comprehension.Athens, Greece:IEEE, 2006:35-45.
[9]?FLURI B,WUERSCH M,PINZGER M,et al. Change distilling:Tree differencing for fine-grained source code change extraction[J]. IEEE Transactions on Software Engineering,2007,33(11):725-743.