當前位置:
首頁 > 知識 > 六種可定量分析的代碼味道

六種可定量分析的代碼味道

Sunny近年主要從事軟體度量、設計模式、代碼分析和優化、雙向工程、代碼自動重構等領域的研究工作,部分研究心得和研究成果也將通過本博客發布,我的研究宗旨是:軟體工程研究應該為應用服務,不能脫離工程實踐空談理論。,因此,Sunny非常希望能夠得到大家的意見和建議(特別是一線開發人員),包括代碼自動生成、正向工程、逆向工程、代碼缺陷和味道自動分析、代碼自動重構、軟體度量和質量、設計模式推薦、設計模式探測、設計模式標註、設計模式驗證等領域。

傳統的代碼味道(Bad Smells in Code)識別主要依賴開發人員的經驗,這將導致代碼味道識別效率低,且容易漏掉很多代碼味道。因此,設計和開發自動化的代碼味道識別工具已成為軟體工程研究的一個分支。國內外學者已經陸續提出了一些代碼味道自動識別方法,其中有一類方法是基於軟體度量和統計量的,可以通過定量分析和計算來探測代碼中是否存在這些代碼味道,而且很多商業和開源的代碼分析和優化工具也使用了其中一些方法,例如iPlasma、inFusion、PMD、Checkstyle、JDeodorant等中,本文將介紹六種可定量分析的代碼味道,並介紹在一些常用的工具中它們的實現情況。【工具介紹參見:七款代碼味道識別工具【簡介】】

(1) 重複代碼 (Duplicated Code)

重複代碼是指相同的代碼結構出現在多個地方。

發現重複代碼可以通過度量一個系統中重複代碼行數所佔百分比來實現。探測重複代碼最大的問題在於存在多種不同的重複類型。完全相同的代碼探測起來很容易,已存在不少技術。但是有一些重複代碼存在重命名、使用別名等情況,導致探測技術需要對程序代碼進行語義分析,例如,重命名局部變數等,這些探測方法需要更多的計算時間去檢測各種可能的重命名。還有一些重複代碼存在一些細微的修改或者中間混合了少量的其他代碼,這導致探測的難度變大,可以引入相似度計算等技術。還有一種更複雜的重複代碼,功能相同,結構不同,這種重複代碼的檢測需要深入分析程序代碼的語義,尋找功能相同或相似的結構片段,無疑將導致探測過程更加複雜,探測難度加大,也需要更多的探測時間。

在工具iPlasma和inFusion中,探測重複代碼的策略是使用一組關於代碼重複的度量指標,考慮到重複片段的長度和兩段重複代碼之間的距離。Checkstyle的實現非常簡單,它簡單統計程序源代碼中的連續重複行數,設定的閾值為12,也就是說當有12行代碼重複時則認為存在重複代碼,重複代碼的掃描可以跨方法甚至跨類。在PMD中,當一個代碼片段重複至少一次且其中包含至少25個標記(tokens)時,則認為出現了重複代碼壞味道。

(2) 依戀情節 (Feature Envy)

依戀情節是指一個方法對另一個類的興趣比對它所在類的興趣還大。因為它與其他類之間具有更高的耦合度,故這個方法放在了錯誤的位置。

依戀情節代碼味道的探測可以通過度量一個方法對屬於其他類中的方法(或數據)的耦合程度來實現。

2006年,Lanza和Marinescu提出了如下方法來探測依戀情節:

(1) 一個類中的方法直接使用了另一個類中的一些屬性,可以通過訪問外部數據個數(Access to Foreign Data, ATFD)來度量;

(2) 一個類中的方法使用另一個類中的屬性比使用自己本身的屬性多得多,可以通過局部屬性訪問值(Locality of Attribute Accesses, LAA)來度量;

(3) 一個類中所使用的「外部」屬性屬於少數幾個其他類,可以通過使用外部數據提供者數(Foreign Data Providers, FDP)來度量。

他們通過如下條件來探測依戀情節:

FDP ≤ FEW ∧ ATFD> FEW ∧LAA < 1/3

此處,Lanza和Marinescu設定FEW的值為5。

iPlasma和inFusion採用了上述規則來識別依戀情節。在JDeodorant工具中,該問題轉成了一個尋找Move Method(搬移方法)重構時機問題:它試圖去尋找那些一旦搬移到另一個類中就很少使用外部(其他類中的)資源的方法。

Object-Oriented Metrics in Practice

(3) 萬能類/上帝類(God Class)

萬能類通常也認為是一種設計缺陷,它指的在系統中集多種功能於一身的類,它試圖成為整個系統的中心。一個萬能類承擔了太多的職責,而只將很少的功能委託給其他不重要的類,並且萬能類還需要從其他類那裡獲取數據。

與依戀情節相同,2006年,Lanza和Marinescu還提出了一種通過計算三種度量指標來探測萬能類的方法,這三種度量指標如下:

(1) 加權方法計數(Weighted Method Count, WMC): 一個類中所有方法的統計複雜度的和。

(2) 類內聚的緊密度(Tight Class Cohesion, TCC):通過訪問相同的屬性而直接發生聯繫的方法個數。

(3) 訪問外部數據個數(Access to Foreign Data, ATFD):對於一個給定的類,它所訪問的外部類的個數,它可以直接訪問這些外部類的屬性,也可以通過訪問器方法(Accessor Method)訪問這些屬性。

在Lanza和Marinescu的方法中,當一個類滿足如下條件時它就是一個萬能類:

WMC ≥ VERY_HIGH∧ATFD > FEW ∧TCC < 1/3

在此,Lanza和Marinescu設定VERY_HIGH的值為47,FEW的值為5,在他們的Object-Oriented Metrics in Practice一書中詳細描述了這兩個值是怎麼獲得的。

iPlasma和inFusion採用了上述規則來識別萬能類。JDeodorant通過其他類來判斷一個類是否是萬能類,並提出了Extract Class(提取類)的重構時機識別方法,這種探測方法與一個類本身的規模沒有直接關係。

(4) 過大類(Large Class)

過大類是指一個類試圖去做太多事情,這些類通常包含大量的成員變數和方法。

類規模的度量方法有很多種,最傳統的方式是度量源代碼行數,如NLOC(Number of Lines Of Code)或者度量一個類中的屬性數和方法數。像NLOC這種簡單的度量指標可以表示一個類的規模,但是並不能判斷一個類是否承擔了多項職責,例如有些GUI類,對於一些複雜的界面,GUI類確實會比較大,但是這些代碼基本上都是自動生成的,我們不應該認為它們存在過大類這一壞味道。

PMD和Checkstyle等工具使用簡單的NLOC作為過大類的探測策略。前者設定的源代碼行數的閾值為1000,後者的閾值為2000。

(5) 過長方法 (Long Method)

過長方法是指那些很長的方法。由於太長,導致難於理解、改變和擴展。也可以指一個方法承擔了太多職責,使之成為一個類,甚至一個子系統的中心方法。

度量過長方法看起來是一件很容易的事情,但是事實並非如此,依賴於一些簡單的度量方式(例如源代碼行數NLOC)可能會帶來一些錯誤的結果,例如:有一些類的初始化方法(如構造函數)可能會比較長,由於它們的圈複雜度一般比較低,理解和修改較為容易,因此通常沒有必要去重構那些長的初始化方法。M?ntyl?建議使用圈複雜度(Cyclomatic Complexity)和Halstead度量(Halstead Measures)去識別過長方法,因為它們可以度量操作數和操作符的個數,並且提供了一些重要的有關方法複雜性的信息。根據M?ntyl?的建議,最好的度量過長方法的度量指標應該是由源代碼行數(NLOC)、圈複雜度和Halstead度量組合而成的一個多項式度量指標。

Checkstyle和PMD等工具探測過長方法用的是最簡單的源代碼行數(NLOC),但是使用了不同的閾值,例如PMD的閾值為100而Checkstyle的閾值是150。JDeodorant使用了切片技術來判斷一個類是否滿足Extract Method(提取方法)重構時機。

(6) 過長參數列表 (Long Parameter List)

過長參數列表是指一個方法的參數列表太長以致難以理解。

過長參數列表的探測可以通過統計每個方法中參數的個數來實現。 探測過長參數列表的要點在於參數個數閾值的設定。例如,在PMD中默認的閾值數量為10,而在Checkstyle中為7。

六種可定量分析的代碼味道

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 程序員小新人學習 的精彩文章:

從主機 Windows 上無法遠程訪問 Linux 的 Tomcat 伺服器解決方法
使用Kubespray部署生產可用的Kubernetes集群

TAG:程序員小新人學習 |