用自定義代碼分析來標準開發人員的開發規範

 
代碼分析
(關於代碼分析詳見http://msdn.microsoft.com/zh-cn/library/3z0aeatx(VS.80).aspx),是visual studio開發工具中提供的一種規範代碼的工具,系統提供了200多條規則,從命名習慣,安全性,屬性使用等方面來對咱們編寫的代碼進行分析,而後以默認警告的形式在「錯誤列表」窗口中提示咱們書寫的代碼是否符合規範,並提示出爲何。固然這種規範是MS給的一種通用的規範,不必定適合全部的公司。
下圖是Visual Studio提供的代代碼分析的11種規範。
(圖-1)
開發規範是每軟件開發公司都有的,可有每一個公司在開發方面都積累了適合本身的一套規範,有的多是通用的,有的多是根據實際狀況適合本身的。好比,公司要求全部的方法的第一個字符必須是大寫,字段不能定義成公有,可能對其餘公司來講這些規範不適合,但對於本公司來講,就是一種規範,是一種要求。(這裏是舉個例子,不是實際存在的公司規範)
公司的開發規範是這樣要求的,但對於一些新手,或一些其餘公司跳過來的程序員,能很快習慣嗎?固然,經過開會,指正,再開會,再指正,開發人員的習慣會造成,但又沒有更好的辦法呢?用一種量化的約定來讓開發人員儘快適應本公司的開發規範呢?答案是確定的。就用自定義代碼分析來規範咱們的開發人員。
 
自定義代碼分析,就是讓Visual Studio中的代碼分析模塊按照自定義的分析方式去分析公司程序寫的代碼,而後給出相應的Warnning(也能夠是Error,根據設定來分類),就像每一個方法的首字母都得是大寫,若是是小寫或非字母的話,就在錯誤列表中給出該方法一個Warnning(或Error)。
 
有了前面的背景,就進入正式的主題。
代碼分析,本質就是把開發人員寫的代碼拿出來,看看那些不符合公司規範,而後把不符合的提示出來,讓開發人員改。你們都知道refection,能夠很好的把別人的代碼檢索出來。但有更好的一個技術,introspection,與refection功能同樣,但它比refection更快,而且支持多線程,分析開發人員程序集時還不獨佔。看來很不錯。咱們只知道這麼多就好了,由於咱們不直接用introspection來作自定義代碼分析,咱們用BaseIntrospectionRule這個封裝了introspection的基類來作代碼分析,這樣以來,會提高我們的開發速度。BaseIntrospectionRule的類層次結構爲:父類是StandardVisitor,再向上是Visitor(一個抽象類),再上就是Object了。
(如下我使用的是visual studio 2008)
首先建立一個CustomCodeAnalysisRules的解決方案,在這個解決方案下建立一個NameRuleCodeAnalysisRules類庫項目。而後給這個項目添加引用,由於BaseIntrospectionRule這個類以及後面用的到的一些類都在將要引用的程程集下面。選中項目的「引用」右鍵「添加引用」,找到visual studio的安裝目錄(有可能你在安裝時修改了安裝目錄)「D:\Program Files (x86)\Microsoft Visual Studio 9.0\Team Tools\Static Analysis Tools\FxCop」(這是個人目錄),引兩個dll進來,一個是FxCopSdk.dll,另外一個是Microsoft.Cci.dll
接下來,咱們要對前面提到的兩個規則進行編程,「方法首字母大寫」和「字段不能是公有」
在項目中添加一個類文件 NameRuleCodeAnalysisRules (爲了方便,咱們把方法驗證和字段驗證都放到一個類中)
using System;
using Microsoft.FxCop.Sdk;

namespace NameRuleCodeAnalysisRules
{
         /// <summary>
         /// 驗證方法類
         /// </summary>
         public class ServiceSoftNameRuleMethod : BaseIntrospectionRule
        {
                 public ServiceSoftNameRuleMethod()
                        : base( "ServiceSoftNameRuleMethod", "NameRuleCodeAnalysisRules.Rules", typeof(ServiceSoftNameRuleMethod).Assembly)
                { }
                 /// <summary>
                 /// 驗證方法首字母
                 /// </summary>
                 /// <param name="member">類型成員</param>
                 /// <returns></returns>
                 public override ProblemCollection Check(Member member)
                {
                        Method method = member as Method;
                         if (method == null)
                        {
                                 return null;
                        }
                         else
                        {
                                 if (!method.IsSpecialName && !Char.IsUpper(method.Name.Name, 0))
                                {
                                        Problems.Add( new Problem(GetResolution(member.Name.Name)));
                                }
                        }
                         return Problems;
                }
        }
         /// <summary>
         /// 驗證字段類
         /// </summary>
         public class ServiceSoftNameRuleField : BaseIntrospectionRule
        {    
                 public ServiceSoftNameRuleField()
                        : base( "ServiceSoftNameRuleField", "NameRuleCodeAnalysisRules.Rules", typeof(ServiceSoftNameRuleField).Assembly)
                { }
                 /// <summary>
                 /// 驗證字段訪問修飾符
                 /// </summary>
                 /// <param name="member">類型成員</param>
                 /// <returns></returns>
                 public override ProblemCollection Check(Member member)
                {                            
                         if (member.DeclaringType is EnumNode)
                        {
                                 return null;
                        }
                        Field field = member as Field;                
                         if (field == null)
                        {
                                 return null;
                        }
                         else
                        {
                                 if (field.IsPublic)
                                {
                                        Problems.Add( new Problem(GetResolution(member.Name.Name)));
                                }
                                 return Problems;
                        }
                }
        }
}
其實 check 方法有多種重載,這裏由於咱們驗證的方法和字段,都是類型成員因此只重寫 check(Member member) 這種方法就能夠了。在方法體中,若是類型成員不知足要求,
 
就以它名字爲 Problem 構造參數的對象,添加到 Problems 中,最終,這個 Problem 對象的相應信息,會在錯誤列表中顯示出來。這裏要注意, member.Name.Name ,也就是類型成員的名字。
C# 代寫完成,要寫一個每一個規範類對應的 Rules.xml
<? xml version ="1.0" encoding ="utf-8" ?>
< Rules FriendlyName ="ServiceSoft公司命名規範" >
     < Rule TypeName ="ServiceSoftNameRuleMethod" Category ="ServiceSoft.NameRule" CheckId ="SS0001" >
         < Name >方法名規則 </ Name >
         < Description >方法名必須首字母大寫,若是首字符小寫將提示警告。 </ Description >
         < Url />
         < Resolution >方法 「{0} 」的首字母應爲大寫 </ Resolution >
         < MessageLevel Certainty ="99" >Error </ MessageLevel >
         < Email >axzxs2001@163.com </ Email >
         < FixCategories >NonBreaking, DependsOnFix </ FixCategories >
         < Owner >ServiceSoft </ Owner >
     </ Rule >
    
     < Rule TypeName ="ServiceSoftNameRuleField" Category ="ServiceSoft.NameRule" CheckId ="SS0002" >
         < Name >字段名規則 </ Name >
         < Description >字段的訪問修飾符不能是公有的。 </ Description >
         < Url />
         < Resolution >字段 「{0} 」的訪問修飾符是public </ Resolution >
         < MessageLevel Certainty ="99" >Error </ MessageLevel >
         < Email >axzxs2001@163.com </ Email >
         < FixCategories >NonBreaking, DependsOnFix </ FixCategories >
         < Owner >ServiceSoft </ Owner >
     </ Rule >
</ Rules >
 
每一個類對應一個 <Rule> 標記。最外面是 <Rules> 標記,這裏要注意這個標記的 FriendlyName 這個屬性值,最終會在圖 -1 中的規則中顯示出來。
<Rule> 中有以下子標記, <Name> 名稱, <Description> 描述, <Url> 連接, <Resolution> 解決方案,這個標記會最終在錯誤列顯示出來,因此對這個標記的內容要描述清楚,而且在這個標記的內容中有{ 0 }這樣的佔位符,這是爲前面方法中的 member.Name.Name 所佔的。 <MessageLevel> 信息級別, Categories 0 99 範圍的值,內容爲   MessageLevel 枚舉的值,<Email>郵箱, <FixCategories> 更正規則的方式,內容爲 FixCategories 枚舉的值, <Owner> 全部者。
如今主能夠生成類庫集了,如今須要把 Rules.xml 一塊兒生成到程序集的 dll 中,選中 Rules 右鍵「屬性」,在屬性的窗體中選中「生成操做」,下拉改爲「嵌入的資源」,最終就會把這個 Rules.xml 打包到 dll 的元數據中。
再返回頭來看一下規則類和 xml ,它們的關聯是經過在規則類的構造函數中的第二個參數 NameRuleCodeAnalysisRules.Rules namesapce+xml 名和 xml <Rule> Typ eName 屬性爲規則類名關聯起來的。
複製上 NameRuleCodeAnalysisRules.dll ,到 visual studio 的安裝目錄 D:\Program Files (x86)\Microsoft Visual Studio 9.0\Team Tools\Static Analysis Tools\FxCop\Rules 下,這個目錄下放的全是代碼分析的規則類。
到此,爲咱們的開發規範自定義代碼分析就作完了,好用嗎?
 
新建一個控制檯應用程序,名稱自已決定
代碼以下:
 
using System;

namespace ConsoleApplication1
{
         class Program
        {
                 public int i = 10;        
                 static void Main( string[] args)
                {
                }
                 public void ff()
                {
                }
                 static void _gsw()
                {
                }
                 public int Sx
                { get; set; }
        }
         class abc
        {
                 public string k= "12";
                 public abc()
                { }
        }
         abstract class bcd
        {    
             public abstract int ffs();
        }
}
 
而後打開代碼分析,以下圖:
(圖-2)
這時,就能看到咱們自定議的規則「 ServiceSoft 公司命名規範」(這裏的名稱就是 Rules.xml 中的 FriendlyName 屬性的值),爲了測試明顯,能夠先把其餘的規則關閉。生成以下圖
(圖-3)
說明中就會把咱們自定議的規則以警告的形式提示出來。
 
有幾個問題:
一、  當第一次代碼分析時每每不進行,當源代碼有一點改動,代碼分析才起做用,我估計系統檢測出源代碼文件有變更,纔去分析,這裏應該用一點問題。
二、  還有全部的代碼分析警告都不顯示第幾列。
相關文章
相關標籤/搜索