代码要恰如其分——记一次代码审查

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

下面是一个在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     }

这段代码有几个问题:

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     }

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

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

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

代码要恰如其分——记一次代码审查

时间: 2024-11-29 00:10:27

代码要恰如其分——记一次代码审查的相关文章

个人博客作业2 - 代码规范讨论与个人项目代码审查

对于是否需要有代码规范,请考虑下列论点并反驳/支持: 这些规范都是官僚制度下产生的浪费大家的编程时间.影响人们开发效率, 浪费时间的东西. 我是个艺术家,手艺人,我有自己的规范和原则. 规范不能强求一律,应该允许很多例外. 我擅长制定编码规范,你们听我的就好了. 对于论点1,我认为是不正确的.对于一个独立的开发者来说,代码风格可以完全遵从个人意愿,代码规范也没有存在的必要,强调代码规范可能睡些许降低个人的开发效率.但是现代软件工程中,一个开发团队往往少则几个人,多则数百人,一个项目需要多个人同时

代码审查 本地测试经验汇总

软件测试虽然辛苦,但是掌握了一定的技巧之后将使你事半功倍. (1) 边界测试,测试用户输入框中的数值的最大数和最小数,以及为空时的情况. (2) 非法测试,例如在输入数字的地方输入字母. (3) 跟踪测试,跟踪一条数据的流程,保证数据的正确性. (4) 在开始测试时应保证数据的正确性,然后在从系统中找出各种BUG. (5) 接口测试,程序往往在接口的地方很容易发生错误,要在此模块测试勿掉以轻心. (6) 代码重用测试,在开发过程中有些模块功能几乎相同,程序员在重用代码时可能忘记在原有代码上修改或

32位汇编第三讲,RadAsm,IDE的配置和使用,以及汇编代码注入方式

32位汇编第三讲,RadAsm,IDE的配置和使用,以及汇编代码注入方式 一丶RadAsm的配置和使用 用了怎么长时间的命令行方式,我们发现了几个问题 1.没有代码提醒功能 2.编写代码很慢,记不住各种声明 那么现在有大神,已经帮我们做了一个IDE环境,就是RadAsm,首先简单介绍一下界面 (对于这个IDE(最新版是3.0)我已经打包好了,有中文版本,和英文版本) 我们需要配置一下环境 1.配置编译环境,配置lib文件库,配置Debug调试器 打开后会弹出 首先这里我们注意下面的几个选项 1.

[译]Quora是如何维持高质量代码的

原文链接:Moving Fast With High Code Quality译者:杰微刊—程慧 一个高质量的代码库可以加快长期开发的速度,因为它会使得迭代.协作和维护更加容易.在Quora,我们十分重视代码库的质量. 除了会取得收益之外,要维护高质量的代码,会带来一大笔间接费用,还会牺牲实际开发周期.很多人发现,实际产生的收益很难抵消这一间接费用,这时人们会面临两个选择:要么以低质量代码提升开发速度,要么维护高质量代码而牺牲开发速度.而对于初创公司来说,他们希望开发速度能快一些,所以就不得不使

看代码网备份|利用WebClient|eKing.CmdDownLoadDbBakOper|实现定时拷贝数据库备份文件到文件服务器

摘要: 1.有两台服务器 (1)看代码网(记为A):内网IP:10.186.73.30 (2)文件服务器(记为B):内网IP:10.135.87.157 2.在A架设一个网站,端口8088(防火强设置B才能访问) 3.在B运行计划任务,每天定时从A的8088端口网站下载数据库备份文件到B 优点: 1.利用iis,无需架设ftp 2.利用防火墙,确保只能指定IP和端口可以访问 3.利用windows计划任务,每天定时备份 4.备份成功邮件定时提醒 原文链接: http://www.lookdaim

Java程序员注意——审查Java代码的六种常见错误

代码审查是消灭Bug最重要的方法之一,这些审查在大多数时候都特别奏效.由于代码审查本身所针对的对象,就是俯瞰整个代码在测试过程中的问题和Bug.并且,代码审查对消除一些特别细节的错误大有裨益,尤其是那些能够容易在阅读代码的时候发现的错误,这些错误往往不容易通过机器上的测试识别出来.本文就常见的Java代码中容易出现的问题提出一些建设性建议,以便您在审查代码的过程中注意到这些常见的细节性错误. 通常给别人的工作挑错要比找自己的错容易些.别样视角的存在也解释了为什么作者需要编辑,而运动员需要教练的原

我是如何进行code review的

众所周知,代码审查是软件开发过程中十分重要的环节,楼主结合自己的实际工作经验,和大家分享一下在实际工作中代码审查是如何开展的, 笔者水平有限,若有错误和纰漏,还请大家指正. 代码审查的阻力 我想不通公司不同部门对代码审查这项工作的重视程度还是不一样的,对于代码审查的阻力总结了以下几点: 国内的整体环境,国内的公司,尤其是互联网公司,讲究速度致上,软件开发的迭代周期周期短,速度快,因为竞争太大,开发的产品要求快速上线,对代码审查不是很重视,先上线,出了问题再解决. 公司的规模,大公司重视流程,把代

谈一下我们是如何开展code review的

众所周知,代码审查是软件开发过程中十分重要的环节,楼主结合自己的实际工作经验,和大家分享一下在实际工作中代码审查是如何开展的, 笔者水平有限,若有错误和纰漏,还请大家指正. 代码审查的阻力 我想不通公司不同部门对代码审查这项工作的重视程度还是不一样的,对于代码审查的阻力总结了以下几点: 国内的整体环境,国内的公司,尤其是互联网公司,讲究速度致上,软件开发的迭代周期周期短,速度快,因为竞争太大,开发的产品要求快速上线,对代码审查不是很重视,先上线,出了问题再解决. 公司的规模,大公司重视流程,把代

个人博客作业2

一.是否需要有代码规范.对于是否需要有代码规范,请考虑下列论点并反驳/支持: 1.这些规范都是官僚制度下产生的浪费大家的编程时间.影响人们开发效率, 浪费时间的东西. 这种说法并不是太合适的.也许写更多的规范是需要消耗一定的时间,但是在之后阅读别人代码,或者是维护和检查的时候,就会大大减少所需要的时间,从而是可以达到一个提高开发效率,节约时间的效果.在现在的软件基本上都不是那种小的程序了,基本上都是需要数人一起合作开发的庞大的工程.而这种庞大的工程,就会要求团队成员都能够通力配合,而不是各写各的