InFusion錯誤類型分析


1       God Class

1.1     特征

上帝類通常過多的操縱其他類的數據,從而破壞了類的封裝性。上帝類從其他類中獲得功能,同時增加了自身的耦合性,通常會導致自己具有規模過大和較高的復雜度。

判斷一個上帝類的標准有:

 

  1. CPFD (Capsules Providing Foreign Data) 從多個不相關類(模塊)中引用數據
  2. WOC (Weighted Operation Count) 類的所有函數的圈復雜度之和超過65
  3. TCC (Tight Capsule Cohesion) TCC < 1/3 類需要具有低內聚的特性(類中直接相關的方法與全部方法之比小於1/3),也就是較少的private方法
  4. 需要同時滿足以上條件才可以被認定為上帝類

1.2     修改

破壞CPFD, WOC, TCC 中的一個。

2       Message Chains

2.1     特征

過度耦合的消息鏈

如果你看到用戶向一個對象索求(request)另一個對象,然后再向后者索求另一個對象,然后再索求另一個對象……這就是Message Chains。實際代碼中你看到的可 能是一長串getThis()或一長串臨時變量。采取這種方式,意味客戶將與查找過程中的航行結構(structure of the navigation)緊密耦合。一旦對象間的關系發生任何變化,客戶端就不得不做出相應修改。

Infusion通常會尋找具有較多調用其他類數據訪問接口的方法,而且會檢查返回值是否匹配。

2.2     修改

采用“隱藏委托關系”修改。

先觀察Message Chains最終得到的對象是用來干什么的,看看能否以 Extract Method 把使用該對象的代碼提煉到一個獨立函數中,再運用Move Method 把這個函數推入Message Chains。

3 FeatureEnvy

3.1 特征

函數對某個class的興趣高過對自己所處之host class的興趣。最通常的焦點便是數據,通常為某個函數為了計算某值,從另一個對象那兒調用幾乎太多取值函數(getting method)。

 

ATFD(Access To Foreign Data) 方法從外部獲取了數據

LDA(Locality of Data Accesses) 內部變量與所有可以獲取數據方法之比<1/3,也就意味着該方法過多的使用了外部數據,而非自身數據。

FDP(Access To Foreign Data) 數據來源於很少幾個類

3.2 修改

如果一個類A使用了類B的過多數據來完成某項操作或計算,那改操作就應該放在B類中。

針對ATFD,通常較難進行修改,除非該類不訪問其他類。

針對LDA,可以采用增加類本身的成員變量來進行修改,提高LDA比值。

針對FDP,可以考慮將類B拆分為多個類,從而增加FDP個數。

4     Blob Class

4.1      特征

可以譯為復雜類,它具有體積大,高度復雜的特征,因而難以維護。除此之外,如此大的類(通常超過千行)大大增加了與外部類耦合的可能性,並降低了自身的內聚性。

附加Infusion判斷blob class的標准:

 

 

 

 

4.2      修改

修改時可以根據4.1給出的標准破壞其判斷條件。

5 Blob Module

5.1 特征

類似於blob class,指模塊高度復雜且體積過大。它的檢測標准非常類似於blob class,只有稍微的不同:

在面向過程語言中,函數中的長參數列表是正常的。

 

 

5.2 修改

一般情況下通過拆分模塊或類降低規模和復雜度。

6 Cyclic Dependencies

6.1 特征

循環依賴,也即在依賴結構中存在有“環”。這種設計缺陷出現在系統及子系統級別,如果兩個或更多的子系統相互依賴,維護和重用幾乎是不可能的。

Infusion的檢測規則使用與面向對象和面向過程代碼。檢測工具會繪制依賴圖,並根據此圖判斷是否存在循環依賴。

6.2 修改

7 Data Class

7.1 特征

數據類是單純的數據持有者,它通常不包含復雜的功能,但是會被其他類頻繁和密切的引用。缺乏功能意味着這個類的數據和操作是分離的,不符合面向對象的特征。Data class缺乏封裝性,由於允許其他類較為自由的存取其內部數據,導致data class較為脆弱和難以維護。

Infusion在檢測時會判斷data class的特征:輕量級類,包含大量的get和set方法(或public屬性)。

 

 

7.2 修改

將它處的方法移到data class中,提高其封裝性;或編寫高復雜度函數。

8 Data Clumps

8.1 特征

數據泥團,是《重構》提到的代碼壞氣味的一種。

“喜歡成群結隊地待在一塊兒。你常常可以在很多地方看到相同的三或四筆數據項:兩個classes內的相同值域(field)、許多函數簽名式(signature)中的相同參數。”

也就是一組數據重復出現,如一組數據從一個方法傳遞到另外一個方法,這些數據完全可以抽取為一個對象來進行處理。

 

8.2 修改

將這些參數抽取為對象。

9 Data Module

類似於data class,可以翻譯為數據模塊。為面向過程的設計缺陷。一個模塊暴漏了太多數據,但自身卻沒有完成什么功能,也即太過開放。

檢測規則非常容易:提供了過多數據為外部訪問;復雜度過低

 

10. Distorted Hierarchy

10.1 特征

扭曲的層次

通常指繼承層次過窄和過深。研究表明人的記憶難以記住超過6的層次,因此此類缺陷常常導致代碼難以維護。

除此之外,它還可能預示着代碼存在封裝性的問題,或是划分的粒度太細。

 

10.2 修改

修改不合理的繼承層次,漸少深度和增加廣度(多個類繼承自某父類,則該父類具有較高的廣度)。

11 God Module

11.1 特征

類似於God Class,該module的規模和復雜度高,低內聚以及訪問過多的外部數據。

 

11.2 修改

破壞檢測條件,如拆包,降低復雜度和外部依賴。

12 Intensive Coupling

12.1 特征

過緊的耦合

一個經常被提到的緊耦合的例子是:某個方法與系統中的多個方法相關,而這些方法位於某個或很少幾個類之間。這表明該方法與其他方法提供類之間的通信太過冗長了。

這種設計缺陷通常意味着一個微妙的問題:provider類沒有抽象層邏輯提供合理的服務,導致耦合方法必須要頻繁通信。

在infusion的檢測方面:耦合方法調用了許多外部方法;外部方法位於一個類或少數幾個類。

 

12.2 修改

將耦合方法中依賴的外部方法提取和抽象,將邏輯封裝到provider類中。

13 Refused Parent Bequest

13.1 特征

被拒絕的遺贈

繼承關系是比類協作關系更為特殊和緊密的關系,它基於子類從父類繼承成員的基礎上(變量和方法),但如果子類拒絕使用父類中提供的方法或變量,這表明繼承關系存在問題。

 

 

 

13.2 修改

修改類的繼承關系,將不使用的屬性和方法拆分的另外的類。

14 SAP Breaker

14.1 特征

SAP Stable Abstractions Principle 穩定抽象原則,也即包的抽象程度與其穩定程度一致

這種缺陷表明包,或者類破壞了SAP原則。

SAP原則有兩種基本情況:

如果一個子系統提供了較多的抽象,則它更應位於層次設計的底層,由其他的子系統來引用,這也表明它具有較高的穩定性,也即高抽象性高穩定性。

另外,如果一個子系統的抽象較少,就是是他更多的處於調用者的角色,依賴下層子系統,則它位於層次設計的上層,且具有較低的穩定性,也即低抽象性低穩定性。

SAP Breaker破壞了這種抽象原則。

 

14.2 修改

修改層次設計,從抽象程度和穩定性上修改。一般在成型系統中,抽取接口較為簡單。

15 Schizophrenic Class

15.1 特征

精神分裂的類

一個類本應承擔一種抽象,完成一類責任,但該類確完成兩種或以上的抽象,會影響對類的理解和修改。

Infusion通過如下規則檢測該缺陷:

低內聚,定義大量接口,以及被不同的client使用。

 

15.2 修改

將不同的職責分割到其他類中去。

16 Schizophrenic Module

16.1 特征

精神分裂的模塊

檢測規則類似於“精神分裂的類”。

 

16.2 修改

將職責提取到不同的module

17 Shotgun Surgery

17.1 特征

霰彈式修改,直觀的講,就是修改該方法會引出其他大量的修改。而且這種修改是分布的,並不集中於某一類或某個包。

存在這種缺陷的方法常常被稱為“瓶頸方法”,該方法通常具有很高的復雜度,引用大量的外部方法並被眾多方法調用,極有可能引入bug。

在《重構》包含有對“霰彈式修改”的定義:

Shotgun Surgery類似Divergent Change,但恰恰相反。如果每遇到某種變化,你都必須在許多不同的classes內做出許多小修改以響應之,你所面臨的壞味道就是Shotgun Surgery。如果需要修改的代碼散布四處,你不但很難找到它們,也很容易忘記某個重要的修改。

下面給出infusion的檢測規則:

 

17.2 修改

“這種情況下你應該使用Move Method 和 Move Field 把所有需要修改的代碼放進同一個class。如果眼下沒有合適的可以安置這些代碼,就創造一 個。通常你可以運用Inline Class 把一系列相關行為放進同一個class。這可能會造成少量Divergent Change,但你可以輕易處理它。” -《重構》

18 Significant External Duplication

18.1 特征

顯著的外部重復,也即在系統包層面上的重復。代碼重復破壞了系統的唯一性,將導致代碼規模增大以及提高問題定位的難度。

 

18.2 修改

抽取公共代碼

19 Significant Internal Duplication

19.1 特征

顯著的內部重復

在類或模塊間的代碼重復,提高維護難度。

 

19.2 修改

提取公共代碼

20 Significant Sibling Duplication

20.1 特征

顯著的家族重復

即存在於繼承層次上的重復,一般指繼承層次中的同一層次。

 

20.2 修改

提取公共代碼到父類。

21 Tradition Breaker

21.1 特征

傳統破壞者,即子類拒絕父類提供的方法和屬性,也即破壞了“繼承”這一傳統。在JAVA中,可以通過在子類中重寫方法來完成。

這種缺陷意味着子類的定義或者繼承關系存在不合理。

檢測方式有兩個標准:子類重寫了父類方法或使用了非公用繼承。

 

21.2 修改

重新檢視和修改繼承關系。

22 Unnecessary Coupling

22.1 特征

不必要的耦合

通常指在C++中引用了不必要的頭文件,從而增加的耦合性。

22.2 修改

去掉不使用的頭文件。

23 Unstable Dependencies

23.1 特征

不穩定的依賴

值子系統需要依賴比其更為穩定的子系統,至少是同樣穩定,違反改原則則為不穩定的依賴。

Infusion通過比較不同的子系統中的IF來確定是否為穩定依賴。

IF Instability Factor The ratio of efferent coupling (Ce) to total coupling. IF = Ce / (Ce + Ca).

23.2 修改

修改依賴層次

參考文檔

《Infusion幫助文檔》 -  inFusion Hydrogen, Version 1.8.0

《重構 – 改善既有代碼的設計》 - Martin Fowler,Kent Beck,John Brant ,William Opdyke ,Don Roberts


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM