程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 演化架構與緊急設計: 通過指標進行緊急設計

演化架構與緊急設計: 通過指標進行緊急設計

編輯:關於JAVA

簡介: 軟件指標可以幫助您尋找代碼中隱藏的設計元素,讓它們能夠成為慣用模式。 演化架構與緊急設計 的這一期講解如何使用指標和可視化發現被復雜性掩蓋的重要代碼元素。

緊急設計的難題之一是尋找隱藏在代碼中的慣用模式和其他設計元素。指標和可視化有助於識別代碼的重要部分,從而提取出一些設計元素。本文主要討論兩個指標,圈復雜度(cyclomatic complexity) 和傳入耦合(afferent coupling)。圈復雜度度量方法的相對復雜度。傳入耦合表示有多少個其他類使用當前類。本文要介紹顯示和理解這兩個指標的一些工具,以及如何通過組合指標幫助發現設計特征。

我在 “測試驅動設計,第 2 部分” 中討論過圈復雜度,但是有一些細節沒有討論。通過 Java™ 工具度量圈復雜度的一個難點是工作單元。圈復雜度是方法級度量,但是 Java 編程中的工作單元是類。因此,圈復雜度指標通常表示為類中所有方法的總復雜度或平均復雜度。這兩種形式都是有意義的。

例如,可能會出現以下情況。假設一個類包含一個非常復雜的方法 (CC = 40),但是還有許多非常小的方法(比如 Java 代碼中常見的 get/set 方法對)。JavaNCSS等工具報告所有方法的總復雜度,因此整個類的圈復雜度很高。如果使用 Cobertura 等工具(它們報告類的平均圈復雜度),那麼這個類看起來並不糟糕,因為大量簡單方法掩蓋了那個復雜方法的復雜度。由於工作單元不匹配,所以同時觀察圈復雜度的總值和平均值是有意義的。如果單獨考慮它們,可能會得出錯誤的結論。同時使用這兩個指標有助於消除這種可能性。

軟件指標與物理指標

在軟件中,指標是指應用客觀的度量開發工件,從而判斷粗粒度的特征。與物理指標(比如量尺)不同,大多數軟件指標並不反映真實環境中的一些特征。圈復雜度值(比如 5)沒有度量單位;它並不說明代碼的任何物理性質。這個數字只在與其他代碼的圈復雜度進行比較時才有意義。

對於設計有意義的其他指標是兩個耦合數:傳出(efferent) 和傳入 耦合。傳出耦合度量當前類引用的類的數量。很容易通過簡單的檢查判斷傳出耦合:打開要檢查的類,統計(字段和參數中)對其他類的引用。傳入耦合比較難判斷,但是更有價值。它度量使用當前類的其他類的數量。可以使用命令行 fu 判斷它,也可以使用理解這個指標的其他工具。這種工具包括 ckjm,這是一個用於運行 Chidamber & Kemerer 面向對象指標集的開放源碼工具。盡管 ckjm 的設置和運行有點兒復雜,但是能夠提供圈復雜度(報告類中所有方法的圈復雜度總和)以及傳出和傳入耦合數。

但是,獲得了這些數字之後,如何發揮它們的作用呢(尤其在設計方面)?指標數字只提供關於代碼的一個信息維,數字本身往往意義不大。可以以兩種方式通過指標獲得有用的信息。一種方式是觀察數值隨時間的變化和趨勢。還可以把指標組合起來,提供更豐富的信息,本文介紹這種方式。

指標和設計

我在本系列的幾篇文章中以 Struts 代碼庫作為示例,這不是因為我偏愛 Struts,而是因為它是一個著名的開放源碼項目。相信我:在世界上的大多數代碼中都能夠找到隱藏的設計特征!既然前面使用 Struts,本文繼續使用它說明我的觀點。

ckjm 的輸出是文本,這些文本可以轉換為 XML(也可以使用 XSLT 轉換為其他格式)。圖 1 顯示幾個 ckjm 指標的組合,其中的 WMC (Weight Methods per Class) 是類的方法的圈復雜度,Ca 是傳入耦合。

圖 1. 表格形式的 ckjm 指標結果

圖 2 顯示按 WMC 排序的同一個表:

圖 2. 按 WMC 排序的 ckjm 指標

通過觀察這個結果可以發現,DoubleListUIBean 是 Struts 代碼庫中最復雜的類。這說明應該考慮對它進行重構,消除一定的復雜性,尋找可提取出的重復的模式。但是,WMC 值不能指出花時間重構這個類是否值得。注意,這個類的 Ca 是 3。只有 3 個其他類使用這個類,這說明不值得花費大量時間改進這個類的設計。

圖 3 顯示按 Ca 排序的 ckjm 結果:

圖 3. 按傳入耦合排序的 ckjm 結果

這個組合視圖表明,Struts 中最常用的類是 Component(由於 Struts 是 Web 框架,這是很正常的)。盡管 Component 並不復雜,但是有 177 個類使用它,所以它是改進設計的好目標。改進 Component 的設計會影響其他許多類。

WMC 和 Ca 的組合是了解 圖 3 提供的信息的最佳方法。這在一個視圖中同時指出代碼庫中最重要和最復雜的部分。即使您以前並不了解這個代碼庫,也可以通過這個視圖了解在哪些方面進行改進會產生最好的結果。盡管這不一定准確,但是與只查看代碼相比現在掌握了關於代碼庫的更多信息。

數字指標提供關於代碼的信息,但是它們處於相當低的層次上;它們提供特定類的信息,而不提供代碼庫的全局視圖。現在,有許多工具可以通過可視化把指標提高到下一個層次。

指標可視化

指標的可視化為特定的維提供替代視圖,包括單一維和多個維的聚合。Smalltalk 社區開發了許多指標可視化工具。Smalltalk 開發的許多指標技術已經遷移到了 Java 語言。

iPlasma 和行業標准

與圈復雜度相關的常見問題包括 “我的代碼與別人的代碼相比怎麼樣?” 和 “對於一個類,多大的數值是合適的?” iPlasma 項目能夠回答這些問題。iPlasma 是一個用於面向對象設計的質量評估的平台,是羅馬尼亞的一個大學項目。它為項目生成許多重要的指標,並與行業標准范圍進行比較。

在運行 iPlasma 時,指定一個源代碼目錄,它就會生成一個指標金字塔,見 圖 4(這是 Struts 2.0.11 代碼庫的結果):

圖 4. iPlasma 指標金字塔

這個金字塔包含大量信息,您要學會如何理解它。每行包含一個彩色的百分數;這個百分數是這一行上的數字和下一行上的數字的比值。表 1 按從上到下的次序說明數字的含義:

表 1. iPlasma 金字塔的含義 編碼 說明 NDD 直接後代的數量 HIT 繼承樹的高度 NOP 包的數量 NOC 類的數量 NOM 方法的數量 LOC 代碼行數 CYCLO 圈復雜度 CALL 每個方法的調用數 FOUT 分散調用(給定的方法調用的其他方法數量)

數字表示比值;顏色表示比值是否在行業標准范圍內(行業標准范圍來自大量開放源碼項目)。比值是綠色(處於范圍內)、藍色(低於范圍)或紅色(在范圍之外)的。對於 Struts 代碼庫,NDD 和 CYCLO 的值處於行業標准范圍之外,LOC 和 NOM 低於標准范圍。表 2 列出使用的范圍:

表 2. iPlasma 的行業指標范圍   低 中等 高 CYCLO / 行 0.16 0.20 0.24 LOC / 方法 7 10 13 NOM / 類 4 7 10 NOC / 包 6 17 26 CALLS / 方法 2.01 2.62 3.20 FANOUT / 調用 0.56 0.62 0.68

iPlasma 還根據金字塔提供建議,見金字塔下面顯示的內容。圖 5 顯示針對 Struts 的建議:

圖 5. iPlasma 建議

iPlasma 生成的數字有兩個用途。首先,可以通過它們比較自己和別人的代碼庫。第二,這些數字指出應該在哪些方面改進代碼質量和設計。例如,對於 Struts,iPlasma 指出繼承樹的深度非常大,而且方法往往太復雜了。但是,必須根據上下文理解這些數字。像 Struts 這樣的 Web 框架往往具有非常細致的層次結構,這意味著 NDD 值高可能不要緊。但是,CC 值與上下文關系不大,它太高了,就說明方法級的設計不太合理。

為了進行比較,圖 6 顯示 iPlasma 為 Vuze 項目生成的金字塔,這是一個用 Java 語言編寫的開放源碼 BitTorrent 客戶機:

圖 6. iPlasma 為 Vuze 生成的金字塔

Vuze 是一個大型項目(超過 500,000 行代碼),它在繼承樹的深度、每個類中的方法數量、每個方法的代碼行數和每個方法的調用數方面可能有設計問題。

依賴性

緊急設計需要查看代碼中的關系和其他高級抽象。試圖從源代碼調用中看出這些高級概念就像是盲人摸象。這種做法只能了解局部特征,無法獲得全局視圖。

這種局部化問題使我們很難判斷類和對象之間的依賴性。iPlasma 這樣的工具可以顯示代碼的總體特征,但是不能指出哪些部分應該進一步研究。幸運的是,其他工具可以幫助您從不同的角度了解代碼。

Smalltalk 社區開發了一個稱為 CodeCrawler 的工具。它基於 Moose 平台,用圖形顯示一些代碼指標,包括類的大小、方法長度等等。可以讓 CodeCrawler 檢查 Java 代碼,但是很麻煩。幸運的是,因為已經出現了 X-Ray 項目,現在不用費勁兒了。

X-Ray 是一個 Eclipse 插件,它生成有助於了解代碼總體結構的一些信息,包括類之間依賴性的圖形表示,圖 7 是 Struts 的依賴性視圖:

圖 7. X-Ray 類依賴性視圖

圓周上的每個點是一個類,線表示類之間的依賴性。線的粗細表示依賴性的強度。單擊類會顯示這個類的相關信息,雙擊它會在 Eclipse 編輯器中打開它。這個視圖包含的信息太多,不容易找到有用的信息。可以放大它以查看各條線。粗線表示類之間的依賴性很強(傳出耦合),如果兩個類的關系太緊密,可能說明有設計缺陷。

X-Ray 還為包依賴性提供相似的視圖,見圖 8:

圖 8. X-Ray 包依賴性視圖

總體結構

還有一個 X-Ray 視圖顯示有用的代碼信息,它也基於 CodeCrawler。系統復雜度視圖通過圖形顯示代碼庫的情況,繼承層次結構顯示為自頂向下的樹視圖,框的大小表示類中的行數,框的寬度表示方法數。圖 9 給出系統復雜度視圖。

圖 9. X-Ray 系統復雜度視圖

這個視圖還把向外調用(傳出耦合)顯示為粉紅線,把向內調用(傳入耦合)顯示為紅線。與前面的視圖一樣,單擊一個框會在 Eclipse 中打開這個類。這個代碼視圖可以提供獨特的視角,僅僅查看代碼很難了解到這些信息。如果可以沿著某些維快速地篩選,收縮應該進一步研究的范圍,就很容易找到某些方面的設計缺陷。

結束語

X-Ray 和 iPlasma 只提供了 Java 代碼可用的一小部分可視化特性。適當地使用它們可以快速地收縮關注的范圍,有助於找到項目代碼中隱藏的設計。尋找慣用模式是緊急設計的關鍵活動之一,工具有助於輕松地找到模式(包括好的和糟糕的),可以顯著降低研究工作量,為重構代碼留出更多時間。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved