馮燕+肖笛
摘要:本文從軟件度量的角度分析了可被實(shí)施函數(shù)提取重構(gòu)的代碼序列特征,并提出了一種基于軟件度量的函數(shù)提取重構(gòu)方法。
關(guān)鍵詞:度量;代碼重構(gòu);方法提取
中圖分類號:TP311.53 文獻(xiàn)標(biāo)識碼:A 文章編號:1007-9416(2017)06-0254-01
軟件開發(fā)開發(fā)是一項(xiàng)智力活動(dòng),而且不同于一般的實(shí)體產(chǎn)品,軟件在開發(fā)過程中甚至在完成之后,仍會面臨客戶的需求變更。變更將導(dǎo)致軟件的修改。因此,隨著軟件開發(fā)的深入推進(jìn),隨著軟件系統(tǒng)的演化,軟件結(jié)構(gòu)也會越來越復(fù)雜。重構(gòu)是一種通過對代碼結(jié)構(gòu)進(jìn)行修改,能夠有效改善代碼質(zhì)量的行為。對軟件代碼中某些函數(shù)復(fù)雜臃腫的函數(shù)進(jìn)行函數(shù)提取重構(gòu),分解函數(shù)功能,降低函數(shù)復(fù)雜性,是一種提高代碼質(zhì)量的有效手段。
1 函數(shù)提取重構(gòu)的模型
1.1 函數(shù)提取重構(gòu)基本概念
函數(shù)提取重構(gòu)是軟件開發(fā)中最常用的重構(gòu)手段之一,是指從已有代碼序列中提取部分代碼創(chuàng)建一個(gè)新的函數(shù)。函數(shù)提取重構(gòu)通常發(fā)生在某個(gè)函數(shù)過長,或者包含多種不同功能的時(shí)候。在這些場景下,往往需要注釋才能讓人理解它的用途。在函數(shù)提取重構(gòu)中,首先需要判斷某個(gè)函數(shù)是否需要重構(gòu),可行性如何;然后,如果確定需要重構(gòu),則選取某些連續(xù)的代碼片段;之后,創(chuàng)建一個(gè)新的函數(shù),將所選中的代碼片段提取到新函數(shù)中,并為新函數(shù)確定參數(shù)和返回值;最后,在原函數(shù)中的代碼片段會被一個(gè)對新函數(shù)的調(diào)用所替代。雖然不連續(xù)的代碼片段也存在被重構(gòu)的可能,但這種重構(gòu)非常復(fù)雜,在實(shí)踐中往往極少實(shí)施,本文也只考慮連續(xù)代碼片段的重構(gòu)。函數(shù)提取重構(gòu)有多種好處:首先,減小函數(shù)粒度,增大函數(shù)的可復(fù)用性;其次,使得處于代碼高層的函數(shù)代碼簡單易懂;此外,單一功能且細(xì)粒度的函數(shù)的理解和維護(hù)都會容易些[1]。
1.2 函數(shù)提取重構(gòu)的可行性分析
重構(gòu)的基本目的是使代碼更易于理解和維護(hù)。除此之外,函數(shù)提取重構(gòu)的目的還包括增加代碼的可復(fù)用性,如果兩個(gè)或多個(gè)不同的函數(shù)包含一段相似的代碼,即可將這段代碼提取為一個(gè)新的函數(shù),在原來的代碼中調(diào)用新函數(shù)。因此,我們總結(jié)了適用于函數(shù)提取重構(gòu)的一些場景:函數(shù)過長或控制結(jié)構(gòu)過于復(fù)雜,導(dǎo)致閱讀和理解困難;某個(gè)函數(shù)完成了兩個(gè)或兩個(gè)以上的相對獨(dú)立的功能,這種情況下應(yīng)該將對函數(shù)進(jìn)行分解,將每個(gè)功能對應(yīng)的代碼提取成一個(gè)函數(shù),使每段代碼的含義更加清晰,增加了代碼的可復(fù)用性;多個(gè)函數(shù)具有相似或相同的代碼序列,這種情況可以實(shí)施函數(shù)提取重構(gòu)提高代碼復(fù)用性。
函數(shù)提取重構(gòu)的適用場景也是有限制的,需要滿足某些特定的抽取條件。一個(gè)基本條件是被提取的代碼都位于同一個(gè)函數(shù)內(nèi)部,不能起始于一個(gè)函數(shù),終止于另一個(gè)函數(shù),那樣的重構(gòu)會使程序出錯(cuò)。此外,之前所述的非連續(xù)代碼片段,其重構(gòu)也非常復(fù)雜。本文對函數(shù)提取重構(gòu)的可適用代碼片段進(jìn)行了更嚴(yán)格的界定,認(rèn)為滿足以下條件的代碼序列也不應(yīng)該進(jìn)行重構(gòu):代碼序列中含有終止執(zhí)行所在函數(shù)的代碼,比如return語句、exit語句、panic語句等終止語句;代碼序列中含continue、break等跳轉(zhuǎn)語句,但跳轉(zhuǎn)語句的目標(biāo)在該所選擇的代碼序列之外;代碼序列不完整的,例如開頭或結(jié)尾含有注釋但提取后注釋不完整,括號被拆分等,這類重構(gòu)會造成語法錯(cuò)誤。
2 程序復(fù)雜性度量模型
函數(shù)提取重構(gòu)的基本目的是便于軟件維護(hù),因此我們借鑒軟件度量中可維護(hù)性指數(shù)的概念,提出了面向該重構(gòu)的程序復(fù)雜性度量模型,用于判斷某個(gè)函數(shù)是否需要實(shí)施函數(shù)提取重構(gòu)。使用這個(gè)模型對軟件系統(tǒng)中的所有函數(shù)進(jìn)行檢查,判斷函數(shù)的可維護(hù)性,如果函數(shù)的可維護(hù)性過低,就認(rèn)為該函數(shù)應(yīng)該被重構(gòu)。
MI公式中,g是指控制流圖,avgV指程序的平均Halstead復(fù)雜度,Halstead復(fù)雜度用來測量程序操作的計(jì)算復(fù)雜度。如果一個(gè)程序一共有M個(gè)操作符與操作數(shù)并且有N個(gè)不同的操作符與操作數(shù),則它的Halstead復(fù)雜度V被定義為V=M*。aveV(g)是指平均圈復(fù)雜度(Cyclomatic complexity),是對程序的各個(gè)獨(dú)立的邏輯路徑的測量,圈復(fù)雜度計(jì)算公式為V(G)=e-v+2p,其中,e表示控制流圖中邊的數(shù)量,v表示控制流圖中節(jié)點(diǎn)的數(shù)量,p為控制流圖的連接組件數(shù)目(圖的組件數(shù)是相連節(jié)點(diǎn)的最大集合)。aveLOC是平均代碼行數(shù)。PerCM是平均注釋行數(shù)的百分比。MI指數(shù)值的范圍是從0到100。微軟在其Visual Studio工具中定義為值在20到100之間是高可維護(hù)性,10到19之間是中等可維護(hù)性,0到9之間是低可維護(hù)性。我們沿襲這個(gè)標(biāo)準(zhǔn),認(rèn)為低可維護(hù)性的函數(shù)都是需要重構(gòu)的,中等可維護(hù)性則由開發(fā)者自行決定是否需要重構(gòu)。
3 函數(shù)提取重構(gòu)方法
3.1 待提取語句序列分析
為了實(shí)施重構(gòu),我們首先要對待提取語句序列進(jìn)行分析,其中最重要的是獲取重構(gòu)后新函數(shù)的參數(shù)和返回值。我們?yōu)榇崛〉恼Z句序列構(gòu)建抽象語法樹,然后對該抽象語法樹進(jìn)行控制流和數(shù)據(jù)流分析,獲得該語句序列中所有的變量聲明和使用情況。抽象語法樹(AST,Abstract Syntax Tree)是程序的一種中間表示形式,它是源代碼的抽象語法結(jié)構(gòu)的樹狀表現(xiàn)形式。樹上每個(gè)節(jié)點(diǎn)都表示源代碼中的一種結(jié)構(gòu)。通過對變量的定義引用對分析,我們分別得到待提取語句序列的入口處變量和出口處變量,它們分別作為重構(gòu)后新函數(shù)的參數(shù)和返回值。全局變量既是參數(shù)也是返回值[2]。
3.2 局部變量分析
為了對局部變量進(jìn)行深入分析,我們將待提取的代碼序列分為四種情況:第一種是不含有局部變量;第二種是含有局部變量,但僅僅是被使用;第三種是含有局部變量,但僅僅是進(jìn)行賦值;第四種情況是第二和第三種情況的綜合,即包含了局部變量,且局部變量在代碼序列中既被使用又被重新賦值。
3.3 重構(gòu)后評價(jià)
在進(jìn)行方法提取重構(gòu)后,我們還需要對重構(gòu)進(jìn)行評價(jià),判斷程序結(jié)構(gòu)是否得到了改善。從直觀上看,原函數(shù)和新函數(shù)各自的代碼顯然都會比原有函數(shù)的代碼少,因此,單個(gè)函數(shù)對比,每個(gè)函數(shù)都變得更簡單,粒度更細(xì),單個(gè)函數(shù)的結(jié)構(gòu)得到了改善。當(dāng)然,由于一個(gè)函數(shù)變成了兩個(gè)甚至多個(gè)函數(shù),總的代碼量可能會增加,原有的代碼局部性可能也會被打破。為了對重構(gòu)進(jìn)行客觀的評價(jià),我們同樣可以使用軟件度量的方法進(jìn)行評估,例如,通過計(jì)算代碼行數(shù)、圈復(fù)雜度、Halstead復(fù)雜度等。通過度量的計(jì)算,我們能夠?qū)χ貥?gòu)前后軟件的復(fù)雜度、內(nèi)聚度和耦合度等特征做出更客觀的判斷,從而為是否實(shí)施重構(gòu)做出合理的選擇。
4 結(jié)語
綜上所述,基于軟件度量的函數(shù)提取重構(gòu)可以對代碼序列的復(fù)雜性和可維護(hù)性做出客觀的判斷,實(shí)施重構(gòu)后能夠簡化復(fù)雜代碼,或者使得功能交錯(cuò)的函數(shù)得到分解,有利于開發(fā)者對軟件的理解和維護(hù)。
參考文獻(xiàn)
[1]劉偉,胡志剛,劉宏韜.單例模式導(dǎo)向的源代碼自動(dòng)重構(gòu)研究[J].小型微型計(jì)算機(jī)系統(tǒng),2014(12):2664-2669.
[2]林治.軟件重構(gòu)在軟件開發(fā)過程中的作用分析[J].揚(yáng)州教育學(xué)院學(xué)報(bào),2007(3):21-24.
Abstract:from the point of view of software metrics, this paper analyzes the feature of code sequences that can be extracted and reconstructed by function, and proposes a method of function extraction and reconstruction based on software metrics.
Key Words:metrics; code reconstruction; method extractionendprint