[StyleCop] 如何設計屬於團隊的 StyleCop Source Analyzer Rule (Coding Standard)

在規劃好團隊的 StyleCop Source Analysis Rules 後,開發人員除了可以在開發階段透過 StyleCop 掃描自己撰寫的程式碼是否符合團隊所制定的 Coding Standard 外,在 Check-In 每日開發的工作項目的程式碼,除了 Team Build 外,開發主管接著會想做的事應該就是,如何將 StyleCop Source Analysis Rule 與 TFS Check-In Policy 整合,也就是說只有符合 StyleCop 掃描且通過的程式碼才允許簽入 TFS 中

前言

軟體開發是一個複雜的工藝過程,其中牽涉到不少流程、工法,還有使用的工具、平台、作業系統、執行環境的不同,而在開發流程上隨即稍有不同。且軟體開發從1968 年的 [北大西洋公約組織(North Atlantic Treaty Organisation, NATO) 的學術會議中提出了軟體工程這個名詞來界定,軟體開發是一種類似於工程的活動,因為這個過程中,需要許多相關知識。

 

從整個軟體開發的生命週期來看,發展出來的模型就有『瀑布式模型』、『反覆式與漸進式模型』`『雛型模型』、『螺旋模型』等,微軟所提倡的 ALM 裡面的 Agile 就是一種『反覆式與漸進式』的模型。

 

系統分析設計開始,也有許多不同的方法論 (UML、OOAD 等),這之間牽涉到的的領域知識極廣。但這不是本篇的重點,有興趣可以參考筆者先前與 UML 相關的文章 UML塑模化應用程式設計系列

 

軟體開發中的 (Programming) 階段

軟體開發的生命週期中,定義了許多階段,如:需求訪談(Requirement Interview)、需求分析(Requirement Analysis)、系統設計(System Design)、開發(Programming/Coding)、測試(Testing)、上線(Production)、維護(Maintain) 等階段,個階段關注、牽涉的領域知識也都不同,最後的 Programming 則為軟體開發實際的產出,當然個階段環環相扣,如果系統分析、設計即有錯誤,那麼就算你在最後的開發階段把關所有的產出,即使程式寫的再好,沒有 Bug ,但如果不是使用者要的,哪也是枉然。因為軟體最終是要給人用的。

 

前期的階段不為本文討論的重點,筆者若有機會,再另闢章節來探討近代軟體開發生命週期相關議題,本篇就開發階段,在需求確定、清楚、確定實作架構情況下,軟體開發如何做好品質把關?軟體不管是多人開發,或是一人開發,都可能因為需求認知的誤解、對實作的技術 (程式語言/環境架構/作業平台) 的不了解,而產生一些隱憂、臭蟲 (Bug),因此近代對於解決開發階段的品質把關,從軟體測試開始把關,如何做好測試、從測試角度產生的方法可說是變化最多,幾乎每幾年不斷改變、不斷有新的實作理論、或新的方法、新的工具 (Testing Tools) 的出現,因為這與軟體品質息息相關。

 

但如前面所說,開發這件事,都可能因為需求認知的誤解、對實作的技術 (程式語言/環境架構/作業平台) 的不了解,而產生一些隱憂、臭蟲 (Bug),所以近代開始將Code Review 視為軟體品質把關的一個重要環節。

 

code review 的目的?

所謂的 Code Review 就是邀請其他人來幫你審查,原始碼上是否存在著不妥之處,例如風格是否與團隊一致、程式碼是否有哪邊可讀性不佳、有壞味道、不容易維護、不好擴充、有安全性疑慮、或效能不佳、甚至壓根就誤解需求的問題存在。

而為什麼要進行 Code Review 呢?因為這幾十年來軟體開發的經驗告訴我們,軟體修復成本越到後期成本越高,

 

所以我們盡量能夠在開發階段時:

  • 提早發現bug並進行修復
  • 凝聚團隊共識
  • 藉著 Code Review 更了解 Domain Knows-how 需求 (這樣的學習比起單向的一對多專案分享或教育訓練,來得有效率地多)

 

圖(一)、軟體修復成本與時間關係

image

資料來源 (https://msdn.microsoft.com/zh-tw/dn751507.aspx)

 

Code Review 的幾個時機點

一般來說並沒有特定的時機點,只有根據團隊資深人員、新進人員人數的多寡、團隊編制的方式、工作分工的方式、使用的 Code Review 次數、每次 Code Review 的時間有所不同,所以團隊應該要找尋適合自己的 Code Review 的方式。

通常可以開始進行 Code Review 的時機點有,

  • 團隊有產出時

當團隊有產出時,這表示可以週期性的進行 Code Review ,看團隊狀況,可以由 Leader 主導,但相關人員參與即可,通常新進人員也可共同餐與,同時了解哪些錯誤以後不該犯。

當團隊由某開發的資深 Leader 主導,也可採用抽籤的方式,每週由六個團隊中,對抽到的團隊 (也許是負責某項 Function 的小團隊)

  • 有Bug出現時

當 QA 回報有 Bug 時,這也許就是一個進行 Code Review 的切入點,但是多人開發的團隊每周還是有固定的時間來進行 Code Review 會比較恰當。

  • 程式碼是有瑕疵、或效能不佳時

當程式碼有瑕疵,或效能不佳時,如果是在 UAT 環境才發現這個問題,通常表示專案可能已經進行到後期,所以這就是為什麼希望能在開發階段中就發現問題,來讓瑕疵根本不會發生,或是在第一時間點就被修復,

這也是近期 TDD (test-driven development) 測試驅動開發會如此盛行之原因,在軟體開發中盡早做測試的方法,就算團隊不使用 TDD,但也必須要求開發人員須寫 Unit Test ,又或者透過一些原始碼的掃瞄工具在開發階段發現已知問題,當然這麼做並不容易,因為開發人員又要開發,要撰寫程式,又要撰寫測試,但這在實務上更是挑戰工程師的人性以及管理者的極限,以上方圖表角度來看 Bug 修復成本,這的確花費的成本最低,也是極限編程(eXtreme Programming)中所提倡的搭檔編程(pair programming)

 

Code Review 的前置作業

再進行 Code Review 會議之前,有一些前置作業是可以先做的,比如團隊的 Coding Standard 的制定,如基本命名規則、程式碼風格 (換行、縮排方式)、註解等,團隊在開發前就須有這部分的共識才會開始進行。且開發人員在開發進行時,也可以透過如:StyleCop、FxCop 等程式碼風格掃描工具,讓開發人員在 Code Review 會議開始之前就可以對自己的程式進行初步 Review,千萬不要在 Code Review 的時候還要花時間調整程式碼風格 Style、這樣就無法做到輕量化敏捷的 Code Review。

 

與 Code Review 相關資訊可參考筆者投影片

 

 

設計屬於團隊的 StyleCop Source Analyzer Rules

使用 StyleCop 可對對程式碼做基本命名規則、程式碼風格 (換行、縮排方式)、註解等的掃描,指示內建的 Rule 種類繁多,因此不見得每一個 Rule 都適用所有團隊,所以開發團隊應該要制定符合自己開發團隊的 StyleCop Source Analysis Rules。

SNAGHTML1b1b3a6

 

StyleCop 的 Rules 的所有說明文件,請參閱線上說明,本篇無法一一介紹。

http://www.stylecop.com/docs/StyleCop%20Rules.html

 

將  StyleCop Source Analysis Rule 與 TFS Check-In Policy 整合的方式

在規劃好團隊的  StyleCop Source Analysis Rules 後,開發人員除了可以在開發階段透過 StyleCop 掃描自己撰寫的程式碼是否符合團隊所制定的 Coding Standard 外,在 Check-In 每日開發的工作項目的程式碼,除了 Team Build 外,開發主管接著會想做的事應該就是,如何將 StyleCop Source Analysis Rule 與 TFS Check-In Policy 整合,也就是說限制開發人員,只有符合 StyleCop 掃描且通過的程式碼才允許簽入 TFS 中。

 

這應該怎麼做呢?其實 StyleCop 早就有提供可供 TFS 使用的 Check-in Policy ,這個 Policy 目前還沒上 GitHub ,還可以到 CodePlex下載:

https://stylecopcheckinpolicy.codeplex.com/

image

 

安裝完畢後,在 Team 專案的『原始檔控制』裡的『簽入原則』就會看見『StyleCop Source Analysis Policy』,如下:

SNAGHTMLb302dfb

 

在設定視窗哩,你也可以設定在 TFS 中的 Check-In Policy 要使用的原則為何?不過實務上通常會使用團隊定義的 StyleCop 設定,因為 StyleCop 其實是一個 Settings.StyleCop 的 XML 檔案存放在你的專案中,只不過在預設,你如果有設定 TFS 的 Check-In Policy,那麼它預設簽入時,會以 TFS 設定的 Check-In Policy 為主,不會去讀你專案裡所設定的 Settings.StyleCop 檔案。解決方式也簡單,就是將 『Allow project StyleCop settings override the parent StyleCop settings.』勾選起來即可。

SNAGHTMLb352289

下圖是將『Allow project StyleCop settings override the parent StyleCop settings.』勾選起來的畫面。

SNAGHTMLb3b5023

 

如何開發自己的 StyleCop Source Analysis Rules?

如果要完全自訂自己的 StyleCop Source Analysis Rules 可能需要撰寫一些程式碼。

 

需求:

筆者希望做一個檢查 C# Method 中,如有執行任意的 .Open() 方法,就必須在該 Method 結束前,呼叫它的 .Close() 方法。

 

第一步、建立 Class Library 專案

SNAGHTMLea47f2c

眼尖的朋友可能會注意到,疑~ 怎麼是 .NET Framework 3.5 呢?沒錯,由於目前最新的 StyleCop v4.7 仍然是使用.NET Framework 3.5 編譯出來的,所以您在開發自訂 Rule 的時候請使用 .NET Framework 3.5 ,否則當開發完畢丟到 StyleCop 的執行目錄中,會抓不到這一顆 DLL。當然,你也可以從 CodePlex 下載 StyleCop 完整的 Source Code 並自行編譯為 .NET 4.5.1 以上的版本。

 

第二步、加入 StyleCop.dll 與 StyleCop.CSharp.dll

加入下面兩個 DLL 的參考:

  • StyleCop.dll
  • StyleCop.CSharp.dll

SNAGHTMLeaf764d

 

第三步、定義 StyleCop 的 XML 定義檔

   1:  <?xml version="1.0" encoding="utf-8" ?>
   2:  <SourceAnalyzer Name="Custom Rules">
   3:    <Description>
   4:      Custom rules added to analyzer.
   5:    </Description>
   6:    <Rules>
   7:      <RuleGroup Name="Database">
   8:        <Rule Name="MyCustomRule" CheckId="HE3333">
   9:          <Context>Always close connection object.</Context>
  10:          <Description>Always close connection object rule.</Description>
  11:        </Rule>
  12:      </RuleGroup>
  13:    </Rules>
  14:  </SourceAnalyzer>

 

這個 XML 文件非常的簡單,主要為先設定 SourceAnalyzer Name 也就是要顯示在 StyleCop Settings 視窗上 Rule 的名稱,RuleGroup 是如果有子分類,會用資料夾的方式分類,CheckID 則是讓您決定一個可是別唯一的 RuleID。

比較需要注意的是,這個 XML 檔案必須加入到專案中,並設定為『內嵌資源』,因為 StyleCop Settings 的引擎會自掃描目錄下的 DLL 是否包含這個 XML 的資訊。

image

 

第四步、撰寫程式

首先,繼承 SourceAnalyzer,並 override AnalyzeDocument(CodeDocuemnt) 方法,這方法會將目前要分析的 C# 程式碼以 CodeDocument 傳入,因為 CsDocument 是繼承自 CodeDocument ,所以請自行轉換型別為 CsDocuemnt。

接著呼叫 CsDocuemnt 的 WalkDocument 方法,表示 go through 整個 CS 檔案,

SNAGHTMLf66ea98

從 CodeWalkerElementVisitor 的的原始程式碼可以看的出來,他是一個 delegate 類型,並傳遞目前自身的 CsElement 與父項的 CsElement

   1:  using System;
   2:   
   3:  namespace StyleCop.CSharp
   4:  {
   5:      public delegate bool CodeWalkerElementVisitor<T>(CsElement element, CsElement parentElement, T context);
   6:  }

 

因為每一個 CodeWalkerElementVisitor 代表一個 ElementType 項目,而這裡我們只處裡 Method,所以我們可以透過 ElementType 來判別目前處裡的是不是 C# Method,如果是,就一行一行讀進來,並做您想要的處裡與檢查。

image

 

第五步、編譯,並放置在 StyleCop 的安裝目錄下

SNAGHTMLee6337c

 

第六步、測試是否可以在 StyleCop Settings 視窗下看見新增的 Custom Rules

請重新啟動 Visual Studio 2013 後測試,此時應該會看見如下:

SNAGHTMLee85310

 

第七步、測試是否可以使用我們的 Custom Rules 掃描程式碼

在 StyleCop Settings 設定視窗裡,只勾選 MyCustomRule ,然後掃描一段只有 Connection Open 沒有 Close 方法的程式碼。

image

如上,可以順利秀出這個 Issue 的訊息。

 

結語:

在每一個開發團隊裡都應該要有規範自己的 Coding Standard,以確保交付的程式碼在內部具備基本的可讀性、可維護性,這與工程師在程式碼發揮創意並不互相衝突。且再利用工具的支援來快速的分析程式碼,如上我們順利的完成了一個自訂 StyleCop Source Analyzer 的 Custom Rule,也順利地測試成功,接著,再將這個 Rule 與 TFS Check-In Policy 整合,更可以確保簽入到 TFS 中的不是只是可以 Compile,還要是具備團隊自訂的 Rule 的程式碼,開發過程中,適時的進行適當的 Code Review 會議,在前密工具的支援下,Code Review 會議重點更能夠放在 Domain Known-how、程式碼效能問題、安全問題,也能夠使 Code Review 更有效率,對建立團隊文化與開發規範更有幫助。


 

簽名:

學習是一趟奇妙的旅程

這當中,有辛苦、有心酸、也有成果。有時也會有瓶頸。要能夠繼續勇往直前就必須保有一顆最熱誠的心。

軟體開發之路(FB 社團)https://www.facebook.com/groups/361804473860062/

Gelis 程式設計訓練營(粉絲團)https://www.facebook.com/gelis.dev.learning/


 

如果文章對您有用,幫我點一下讚,或是點一下『我要推薦,這會讓我更有動力的為各位讀者撰寫下一篇文章。

非常謝謝各位的支持與愛護,小弟在此位各位說聲謝謝!!! ^_^