zoukankan      html  css  js  c++  java
  • 代码要恰如其分——记一次代码审查

    代码要恰如其分,说的是只实现当前需要的功能,保留一定的可扩展性,但不要为了在很长一段时间内都不会发生的事情实现可扩展性。
    不要预测将来,将来的新需求可以通过不断的重构来保持代码的健康和可扩展性。

    下面是一个在WCF内部服务中实现的类,这个前提很重要,这是一个服务的内部实现,不是契约,是不需要对外发布的组件(不含服务契约,契约通过另外的组件发布)。

     1 public static class PictureRecognizerFactory
     2     {
     3         private static PictureRecognizer[] m_Recognizers;
     4         private static object _oSync = new object();
     5 
     6         private static PictureRecognizer[] m_AllRecognizers
     7         {
     8             get
     9             {
    10                 if (m_Recognizers == null)
    11                 {
    12                     lock (_oSync)
    13                     {
    14                         if (m_Recognizers == null)
    15                         {
    16                             m_Recognizers = FindAllPictureRecognizer();
    17                         }
    18                     }
    19                 }
    20                 return m_Recognizers;
    21             }
    22         }
    23 
    24         /// <summary>
    25         /// 获取图片的类别
    26         /// </summary>
    27         /// <param name="picture"></param>
    28         /// <returns></returns>
    29         public static PictureType GetPictureType(Picture picture)
    30         {
    31             foreach (PictureRecognizer item in m_AllRecognizers)
    32             {
    33                 PictureType type = item.Reconize(picture);
    34                 if (type != PictureType.Unknown)
    35                     return type;
    36             }
    37             return PictureType.Unknown;
    38 
    39         }
    40 
    41         /// <summary>
    42         /// 寻找所有被标识了PictureRecognizerAttribute的类
    43         /// </summary>
    44         /// <returns></returns>
    45         private static PictureRecognizer[] FindAllPictureRecognizer()
    46         {
    47             Type[] typesWithRecognizer = GetTypesWithRecognizers();
    48 
    49             List<PictureRecognizer> list = new List<PictureRecognizer>();
    50             foreach (Type type in typesWithRecognizer)
    51             {
    52                 list.Add((PictureRecognizer)type.Assembly.CreateInstance(type.FullName));
    53             }
    54 
    55             return list.ToArray();
    56         }
    57 
    58         /// <summary>
    59         /// 获取所有标记为RecognizerAttribute的类型
    60         /// </summary>
    61         /// <returns></returns>
    62         private static Type[] GetTypesWithRecognizers()
    63         {
    64             List<Type> typesRecognizers = new List<Type>();
    65             Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
    66             foreach (Assembly ass in assemblies)
    67             {
    68                 try
    69                 {
    70                     Type[] types = ass.GetTypes();
    71                     foreach (Type type in types)
    72                     {
    73                         if (type.GetCustomAttributes(typeof(PictureRecognizerAttribute), true).Length > 0)
    74                         {
    75                             typesRecognizers.Add(type);
    76                         }
    77 
    78                     }
    79                 }
    80                 catch { }//如果在某个Assembly中加载不到类型,则不予理会,不处理异常
    81             }
    82             if (typesRecognizers.Count == 0)
    83                 throw new Exception("找不到任何图像识别器");
    84             return typesRecognizers.ToArray();
    85         }
    86     }
    View Code

    这段代码有几个问题:

    1、它通过AppDomain.CurrentDomain.GetAssemblies()来获取当前加载的所有程序集,也就是作者认为会有很多类被标记了PictureRecognizerAttribute。实际上,正如我们前提条件所说,PictureRecognizerAttribute是一个在非公开发布的服务组件中定义的类,它是属于服务的内部实现机制,在可以预见的将来都不需要发布给服务外部的类使用。因此,所有定义了PictureRecognizerAttribute的类都和PictureRecognizerAttribute在同一个程序集中。这点非常重要。

    2、基于第一个前提,也就是说所有被标记为PictureRecognizerAttribute的类对PictureRecognizerFactory都是可见的,并且可能被标记为PictureRecognizerAttribute类数量非常少,因此通过New来实现是最简单、高效的。

    3、实际上程序需要获取的是继承至PictureRecognizer的实现类,因此应该直接判断类型是否继承至PictureRecognizer,无需通过判断PictureRecognizerAttribute,引入一个无用的类。

    重构以后的代码:

     1 public static class PictureRecognizerFactory
     2     {
     3         static readonly PictureRecognizer[] _Recognizers = new PictureRecognizer[] 
     4         { 
     5             new PictureRecognizerImpl1(),
     6             new PictureRecognizerImpl2(),
     7         };
     8 
     9         /// <summary>
    10         /// 获取图片的类别
    11         /// </summary>
    12         /// <param name="picture"></param>
    13         /// <returns></returns>
    14         public static PictureType GetPictureType(Picture picture)
    15         {
    16             foreach (PictureRecognizer item in _Recognizers)
    17             {
    18                 PictureType type = item.Reconize(picture);
    19                 if (type != PictureType.Unknown)
    20                     return type;
    21             }
    22             return PictureType.Unknown;
    23 
    24         }
    25     }
    View Code

     如果将来需要一定的开放程度,可以通过暴露内部集合来增加一定的扩展性,参考 Asp.Net MVC ViewEngines 类的实现。

    不要对未来做过多(不是不要)的设想,保持代码的精简,增加代码的可读性、可维护性是软件开发过程中非常重要的一点。代码的行数越少,可能发生的Bug就越少,将来的维护(重构、扩展)难度就越低。

    本篇文章不讨论类的命名,代码规范等问题,如有此类问题请忽略。: )

  • 相关阅读:
    软件git装的过程
    深入理解多态
    深入.net框架
    深入C#数据类型
    JavaScript 性能优化(2)
    JAVA: 集合框架
    JavaScript 性能优化(1)
    JavaScript 常用进度条
    Java: 随机生成字符串并排序
    JAVA: String详解
  • 原文地址:https://www.cnblogs.com/wenhx/p/3928944.html
Copyright © 2011-2022 走看看