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