• 用自定义代码分析来标准开发人员的开发规范


    代码分析(关于代码分析详见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(为了方便,我们把方法验证和字段验证都放到一个类中)

     

    代码
     1using System;
     2using Microsoft.FxCop.Sdk;
     3
     4namespace NameRuleCodeAnalysisRules
     5{
     6    /// <summary>
     7    /// 验证方法类
     8    /// </summary>

     9    public class ServiceSoftNameRuleMethod : BaseIntrospectionRule
    10    {
    11        public ServiceSoftNameRuleMethod()
    12            : base("ServiceSoftNameRuleMethod""NameRuleCodeAnalysisRules.Rules"typeof(ServiceSoftNameRuleMethod).Assembly)
    13        { }
    14        /// <summary>
    15        /// 验证方法首字母
    16        /// </summary>
    17        /// <param name="member">类型成员</param>
    18        /// <returns></returns>

    19        public override ProblemCollection Check(Member member)
    20        {
    21            Method method = member as Method;
    22            if (method == null)
    23            {
    24                return null;
    25            }

    26            else
    27            {
    28                if (!method.IsSpecialName && !Char.IsUpper(method.Name.Name, 0))
    29                {
    30                    Problems.Add(new Problem(GetResolution(member.Name.Name)));
    31                }

    32            }

    33            return Problems;
    34        }

    35    }

    36    /// <summary>
    37    /// 验证字段类
    38    /// </summary>

    39    public class ServiceSoftNameRuleField : BaseIntrospectionRule
    40    {  
    41        public ServiceSoftNameRuleField()
    42            : base("ServiceSoftNameRuleField""NameRuleCodeAnalysisRules.Rules"typeof(ServiceSoftNameRuleField).Assembly)
    43        { }
    44        /// <summary>
    45        /// 验证字段访问修饰符
    46        /// </summary>
    47        /// <param name="member">类型成员</param>
    48        /// <returns></returns>

    49        public override ProblemCollection Check(Member member)
    50        {             
    51            if (member.DeclaringType is EnumNode)
    52            {
    53                return null;
    54            }

    55            Field field = member as Field;        
    56            if (field == null)
    57            {
    58                return null;
    59            }

    60            else
    61            {
    62                if (field.IsPublic)
    63                {
    64                    Problems.Add(new Problem(GetResolution(member.Name.Name)));
    65                }

    66                return Problems;
    67            }

    68        }

    69    }

    70}

    71

     

    其实check方法有多种重载,这里因为我们验证的方法和字段,都是类型成员所以只重写check(Member member)这种方法就可以了。在方法体中,如果类型成员不满足要求,

    就以它名字为Problem构造参数的对象,添加到Problems中,最终,这个Problem对象的相应信息,会在错误列表中显示出来。这里要注意,member.Name.Name,也就是类型成员的名字。

    C#代写完成,要写一个每个规范类对应的Rules.xml

     

    代码
     1<?xml version="1.0" encoding="utf-8" ?>
     2<Rules FriendlyName="ServiceSoft公司命名规范">
     3  <Rule TypeName="ServiceSoftNameRuleMethod" Category="ServiceSoft.NameRule" CheckId="SS0001">
     4    <Name>方法名规则</Name>
     5    <Description>方法名必须首字母大写,如果首字符小写将提示警告。</Description>
     6    <Url/>
     7    <Resolution>方法 “{0} ”的首字母应为大写</Resolution>
     8    <MessageLevel Certainty="99">Error</MessageLevel>
     9    <Email>axzxs2001@163.com</Email>
    10    <FixCategories>NonBreaking, DependsOnFix</FixCategories>
    11    <Owner>ServiceSoft</Owner>
    12  </Rule>
    13  
    14  <Rule TypeName="ServiceSoftNameRuleField" Category="ServiceSoft.NameRule" CheckId="SS0002">
    15    <Name>字段名规则</Name>
    16    <Description>字段的访问修饰符不能是公有的。</Description>
    17    <Url/>
    18    <Resolution>字段 “{0} ”的访问修饰符是public</Resolution>
    19    <MessageLevel Certainty="99">Error</MessageLevel>
    20    <Email>axzxs2001@163.com</Email>
    21    <FixCategories>NonBreaking, DependsOnFix</FixCategories>
    22    <Owner>ServiceSoft</Owner>
    23  </Rule>
    24</Rules>
    25

     

    每个类对应一个<Rule>标记。最外面是<Rules>标记,这里要注意这个标记的FriendlyName这个属性值,最终会在图-1中的规则中显示出来。

    <Rule>中有如下子标记,<Name>名称,<Description>描述,<Url>链接,<Resolution>解决方案,这个标记会最终在错误列显示出来,所以对这个标记的内容要描述清楚,并且在这个标记的内容中有{0}这样的占位符,这是为前面方法中的member.Name.Name所占的。<MessageLevel>信息级别,Categories099范围的值,内容为 MessageLevel枚举的值,<Email>邮箱,<FixCategories>更正规则的方式,内容为FixCategories枚举的值,<Owner>所有者。

    现在主可以生成类库集了,现在需要把Rules.xml一起生成到程序集的dll中,选中Rules右键“属性”,在属性的窗体中选中“生成操作”,下拉改成“嵌入的资源”,最终就会把这个Rules.xml打包到dll的元数据中。

    再返回头来看一下规则类和xml,它们的关联是通过在规则类的构造函数中的第二个参数NameRuleCodeAnalysisRules.Rulesnamesapce+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下,这个目录下放的全是代码分析的规则类。

    到此,为我们的开发规范自定义代码分析就做完了,好用吗?

    新建一个控制台应用程序,名称自已决定

    代码如下:

     

    代码
     1using System;
     2
     3namespace ConsoleApplication1
     4{
     5    class Program
     6    {
     7        public int i = 10;    
     8        static void Main(string[] args)
     9        {
    10        }

    11        public void ff()
    12        {
    13        }

    14        static void _gsw()
    15        {
    16        }

    17        public int Sx
    18        getset; }
    19    }

    20    class abc
    21    {
    22        public string k="12";
    23        public abc()
    24        { }
    25    }

    26    abstract class bcd
    27    
    28      public abstract int ffs();
    29    }

    30}

    31

     

    然后打开代码分析,如下图:

    (图-2)

     

    这时,就能看到我们自定议的规则“ServiceSoft公司命名规范”(这里的名称就是Rules.xml中的FriendlyName属性的值),为了测试明显,可以先把其他的规则关闭。生成如下图

    (图-3)

     

    说明中就会把我们自定议的规则以警告的形式提示出来。

    有几个问题:

    1、 当第一次代码分析时往往不进行,当源代码有一点改动,代码分析才起作用,我估计系统检测出源代码文件有变动,才去分析,这里应该用一点问题。

    2、 还有所有的代码分析警告都不显示第几列。

     

    源码下载:

     用自定义代码分析来标准开发人员的开发规范-源代码.rar

  • 相关阅读:
    Android TabHost(选项卡)
    监控工具之---Prometheus查询持久性(六)
    监控工具之---Prometheus表达式promQL生产中应用(五)
    Grafana Configuration 参数详解(1)
    监控工具之---Prometheus数据可视化Grafana(七)
    监控工具之---Prometheus 安装详解(三)
    监控工具之---Prometheus 配置exporter四)
    Kubernetes容器编排技术---kubectl命令行工具用法详解(三)
    Kubernetes容器编排技术---Kubernetes基于kubeadm安装与配置(二)
    Azure Iaas基础之---创建虚拟机
  • 原文地址:https://www.cnblogs.com/axzxs2001/p/1612112.html
Copyright © 2020-2023  润新知