[Tool]SourceMonitor - 程式碼掃瞄
前言
怎麼樣看code的品質或好壞,
通常程式碼複雜度也是其中一個頗重要的因子。
但不完全代表,
複雜度低,就是品質好或好維護的 Code。複雜度高,就是代表品質不好或可讀性低的 Code。
但是,複雜度還是可以像健康檢查一樣,反應出程式裡面是否有哪裡可能有問題。
Visual Stuido 裡面也有『計算程式碼度量』的功能,
不過今天要介紹的 SourceMonitor,是免費的,而且支援的語言比較多,
也比較不需要為了測量複雜度,而去安裝 Visuual Studio 這麼大的工具。
介紹
SourceMonitor 下載網址:http://www.campwoodsw.com/sourcemonitor.html
Features介紹:
- Collects metrics in a fast, single pass through source files.
- Measures metrics for source code written in C++, C, C#, VB.NET, Java, Delphi, Visual Basic (VB6) or HTML.
- Includes method and function level metrics for C++, C, C#, VB.NET, Java, and Delphi.
- Saves metrics in checkpoints for comparison during software development projects.
- Displays and prints metrics in tables and charts.
- Operates within a standard Windows GUI or inside your scripts using XML command files.
- Exports metrics to XML or CSV (comma-separated-value) files for further processing with other tools.
Size:安裝完在C槽佔3.81MB。
可搭配 SubVersion 跟 Continue Integration Server 一起運作,當 SubVersion 有更新時,自動掃瞄最新的程式碼,產出 Report。
而 SourceMonitor 採用的複雜度是 cyclomatic complexity,主要是針對每一個 Method 裡所有可能執行的路徑來定義複雜度。
也就是 if、for、while、and、or、else 等有判斷邏輯導致路徑分歧,都會增加複雜度。
以人的角度來看,就是腦袋需要更多的空間來暫存可能會跑那些情況。(也就是 SourceMonitor 所定義的『複雜』)
使用方式
使用方式相單簡單,只要給 Source Code 的路徑,就會把裡面的檔案都抓出來,就可以進行掃瞄分析。
-
執行 SourceMonitor 程式後,新建一個專案,選好語言。(上方的框框也有步驟的說明與引導)
-
指定要掃瞄的 Source Code 路徑,可選擇全部或是只掃瞄部分資料夾底下的 Code。
-
給這個 SourceMonitor Project 一個名字,並決定是否要忽略 Comment
-
決定 SourceMonitor Project 位置
-
是否直接執行第一次 checkpoint,以及是否允許 parse UTF-8 的檔案
-
最後的 confirm
以上就是操作過程,其實幾乎就只是給了路徑,下一步下一步到結束。
接著我們來看分析的結果。
分析結果
先選好要掃瞄的相關檔案,一開始的清單是 filter 後的結果。
點下OK!就會出現掃瞄後的結果。
右鍵清單可以看分析後的detail資訊以及圖表
View Checkpoint Files
還有一些其他功能就不細部解說了,有興趣朋友自己可以去玩玩看囉。
結論
程式碼分析軟體,就像健康檢查報告一樣,
檢查出來異狀,並不一定代表有問題。
但要瞭解該數據是否為自然現象,是否需持續觀察。
對了,我們家建議複雜度是在10以內,算是良性。
50以上叫做極難維護....
補充
有人反應什麼情況下,不同寫法可以做到同樣的效果,而且複雜度下降。
在什麼樣的情況『複雜度』與『可維護性』,不一定複雜度低就好維護。
我先舉個例子,例如最常見的把1~10用”;”串起來。
思考邏輯可能是最後一個10後面不加『分號』。
string result = string.Empty;
for (int i = 0; i < 10; i++)
{
if (i == 9)
{
result += (i + 1).ToString() ;
}
else
{
result += (i + 1).ToString() + ";";
}
}
上面這例子,複雜度就是3。常寫code的人碰到這需求,就可能會習慣性寫成這樣:
string result2 = string.Empty;
for (int i = 0; i < 10; i++)
{
result2 += (i + 1).ToString() + ";";
}
result2 = result2.TrimEnd(';');
這樣複雜度就只有1。
會比較好維護嗎? 不一定…見仁見智。
再舉個例子,哪一種寫法比較好懂
//第一種,一行幹掉
string myViewState =(string)this.ViewState["myViewState"] ?? string.Empty;
//第二種,if+else
string myViewState2="91";
if (this.ViewState["myViewState2"] == null)
{
myViewState2 = string.Empty;
}
else
{
myViewState2 = this.ViewState["myViewState2"].ToString();
}
再舉另外一個例子,哪一種好?如果連未來擴充性也納進來,那就不一定誰好誰壞了…
public bool ReadOnly { get; set; }
//第一種
if (this.ReadOnly)
{
this.txtipLoginID.Enabled = false;
}
else
{
this.txtipLoginID.Enabled = true;
}
//第二種
this.txtipLoginID.Enabled = !this.ReadOnly;
想要降低 SourceMonitor 複雜度,其實也很簡單,把判斷的片段抽出去當 void 就可以了,
但是這樣程式碼就會被切的碎碎的,好維護嗎?也不一定。
一直抽到最後,一個 method 原本只呼叫深度為2的 Statck ,為了降低複雜度搞到深度變成8,值得嗎?這也有待商榷。
如何抓好 Balance ,因應不同的適用狀況來 Refactoring ,這才是寫出好 Code 的必要條件。
[註]2010/04/07:SourceMonitor一次僅能針對某一種語言掃瞄,也就是假設專案裡面,有VB也有C#,便無法一次全分析完。
blog 與課程更新內容,請前往新站位置:http://tdd.best/