Some practices to write better C#/.NET code(译)

C#(.NET)中有关编码的一些建议,原文地址:http://www.codeproject.com/Articles/539179/Some-practices-to-write-better-Csharp-NET-code

目录

介绍

开发者之间经常喜欢争论“编码规范”,在整个项目周期中严格遵守编码规范是非常重要的。每个人都应该认识到这种约定是非常有用的,接下来我给大家分享一下这些年来我总结的一些编码规范,有些很基础但是对我们非常有用。

试一试

我们先举一个FizzBuzz的例子。现在我们需要写一段代码遍历1到100,如果遍历到的数值是3的倍数,那么输出“Fizz”,如果是5的倍数则输出“Buzz”,如果既是3的倍数也是5的倍数则输出“FizzBuzz”。其余情况下将原数值直接输出。

Examp1:

你觉得上面这段代码怎么样?我们可否写得更好一些呢?

Example2:

现在你觉得这段代码怎么样?我们可否还能写得再好一点呢?

好吧,让我来再将这段代码优化一下。命名这种事是我们工作中最困难的事情之一,因为我们要花很多时间来取名,属性、类、文件以及项目等等。其实我们也应该多花一些时间在命名这件事情上,因为一个好的名称可以具有显而易见的含义,让人一看就懂。

现在觉得怎么样?是不是比之前的例子都好,可读性更强了?

什么是更好的代码?

先为人而写代码,其次再为计算机。编写易读的代码比编写复杂难懂的代码用时长不了多少,至少从长远来看。如果你的代码很容易读懂,那么它肯定会工作得很好(译者注:这里指可读性好的代码说明思路清晰,逻辑大部分不会有问题)。这也是要编写易读代码的重要原因。另外,在我们回顾之前写的旧代码时,在别人需要修复一些bug时,在别人需要将你写的一部分代码移植到别的系统中时,也都需要能够读懂我们之前写的源码。

如果我们只为自己而写代码,为什么还要求编写易读懂的代码呢?

好吧,如果一个礼拜或者两个礼拜后,你要开发别的系统了(你不再负责原项目了)。那么其他人怎样修复原项目中的bug呢?(过这么长时间后)我想你大概也会完全迷失在你曾经写的糟糕代码之中吧。

我个人觉得,好代码应该包含以下特征:

  • 代码容易被修改,容易在原有基础上进行扩展;
  • 代码清晰简洁并能够表达清楚含义;
  • 代码质量高。

所以,请在满足机器需求的前提下,尽量编写更容易读懂的代码。

怎样提高代码的可读性?

首先你得多阅读他人写的代码,然后能够分辨出哪些是好的习惯哪些不是,什么编码风格能让你更容易读懂而什么让你更迷糊,接着将这些好的编码方式应用到自己的代码之中,当然最后你还是需要一些时间、一些经验以及多一些实践来提高你代码的可读性。

对于每个软件公司来说,让员工遵守一个好的编码标准是非常重要的,这可以通过一些培训、员工之间代码相互检查等方式来达到目的。下面介绍几款自动化代码检查工具:

  • FxCop
  • StyleCop
  • JetBrains ReSharper

什么是编码规范?

根据维基百科上的解释:编码规范是指针对某一种编程语言而总结出来的一系列编码指南,旨在约束人们的编码风格、编码实践以及书写每一段代码的方式。这些规范几乎涉及到文件组织、缩进、注释、声明、命名方式、编程原则等等各方面。软件开发者被要求严格遵守这些规则,从而提高源代码的可读性并使软件系统更易维护。编码规范可以以文档的形式分发给每个员工,每个编码人员必须遵守。注意编码规范对于编译器来讲并不是强制性的,因此编码过程中不遵守编码规范并不会影响软件系统的正常运行

你可能知道类名、方法名、局部变量名以及属性名之间的命名区别,因为它们通常使用不同的大小写规范。你可以在互联网上找到一门编程语言的编码指南,所以找到它并遵守它吧。

下面这些编码指南是微软团队指定的,我仅仅是增加了一些附加内容。

大写规范

下面是C#编程中的一些例子,命名规范以及最佳实践。大家可以参考。

  • PascalCasing

标识符中的每个单词的首字母均大写。

  • CamelCasing

标识符中的第一个单词首字母小写,其余单词首字母大写。

参见:https://msdn.microsoft.com/en-us/library/ms229043.aspx

一些命名示例

在互联网上你可以找到足够多的资料,我仅仅列举出一部分:

下面是我总结的一些最基本的规范:

1)对于类、方法、属性等,请使用PascalCasing方式

2)对于参数和局部变量,请使用CamelCasing方式

3)不要使用缩写(这里应该是毫无根据的缩写,不能很直观的看出意思,译者注)

4)在标识符中不要使用下划线

5)在接口名称前加I字母

6)类成员变量声明在类的最前面,其中静态成员在最上

7)枚举值使用单一的名称

8)枚举类型名称后不要加Enum后缀

开发者应该遵守的一些重要规范

不要定义太大的类

我曾经写过非常大的类,最后证明情况非常糟糕。后来我发现原来我让一个类型负责了太多的工作,这完全违背了单一指责原则,SOLID中的S(译者注:参见之前一篇博客)。

“单一指责原则提倡一个类型只负责单一、相似的功能,这个功能完全包含在该类型内部,并尽可能少的与外界交互。”

或者,依照Martin's 的定义:一个类如果需要修改,那么只应该有且仅有一种合理的原因。

为什么将多个功能拆分开来放在不同的类中非常重要呢?因为每个功能都是一个可变因素,当需求改变了之后,一个负责了太多功能的类需要改变的几率更大。

避免多余的注释

多余的注释指:

一个注释添加的时间太久、与源代码已经不相关或者完全不正确,那么该注释就多余了。”尽量不要在一个单独的方法或者比较简单的类前面添加注释,因为我见过的大多数这样的注释都只是为了说明方法(类)的实现的功能,很多时候这些注释都是无用的。虽然很多开发者添加注释是为了增加代码的可读性以及后期的可维护性,但是请确保你添加的注释不是在做无用功。如果你给方法定义了一个非常容易理解的名称,那么完全不需要多余的注释去解释它是干什么的。我这样说,是因为很多时候一个好的名字(方法名、类名)比注释高效多了。请看下面的例子:

如果我们将方法定义为CancelExportForDeletedProducts()怎么样呢?这时候就完全不需要多余的注释了。当然了,注释有些时候是不可少的,比如Visual Studio生成一些API文档时,就必须用到注释,你可以使用“///”来为代码添加注释,这样Visual Studio就会自动生成XML文档,为别人提供智能提示功能。

注意,我不是说任何时候都不需要注释。如果你添加的注释只是为了描述代码干什么用的,那么就完全没必要。如果你阅读一些包含大量注释的代码时,就会发现这些代码一般都写得比较糟糕。关于这方面的介绍,可以参见下面几本书:

  • Professional Refactoring in C# and ASP.NET by Danijel Arsenovski
  • "Refactoring: Improving the Design of Existing Code" by Martin Fowler, Kent Beck, John Brant, William Opdyke, don Roberts

类中避免多余的Region

Region块是VS提供的一个可以折叠代码的功能,它可以折叠一行或者多行代码。它出现的目的主要是为了在一些比较大的文件中更容易定位到某个具体的方法(代码段),因为它可以隐藏一些非常长的代码片段。但是如果一个类负责了太多功能,那么它就违背了单一指责原则,所以下次在你准备使用Region块来隐藏代码时,请先考虑一下是否应该将这个类拆分成多个类。

方法避免过长

一个方法如果行数过多,那么理解起来就会相当困难。理论上每个方法建议在20~25行代码之间,但是一些黑客(牛逼的人,译者注)喜欢定义1~10行的方法,这个完全取决于个人爱好。方法抽取是代码重构最基本的操作之一,如果你认为一个方法太长或者需要增加额外的注释才能解释它的作用时,那么你就可以考虑抽取方法了。其实代码行数太多并不是问题,问题是当你编写一个行数太多的方法时,你很难跟踪到方法中的每个临时变量。这时候你可以使用Visual Studio抽取方法功能,

  • 使用ReSharper

  • 使用Microsoft Visual Studio

有关更多的内容,可以参考MSDN

避免太多的参数

如果一个方法包含太多的参数,那么你可以定义一个类或者结构体将所有参数合并起来。这通常是一个优雅的做法:

然后详细说明我们定义的类(结构体),而非各种参数。

避免过于复杂的表达式

复杂的表达式内部隐藏了复杂的含义,我们可以将复杂的表达式封装到类的属性之中,之后任何地方都使用该属性。这样代码阅读起来更加容易。

将“警告”当作“错误”处理

上面代码中你会发现我们定义了一个变量但是从来没有使用过它。通常我们在编译项目时会发现有很多警告信息,但是项目仍然能够通过编译。这时候我们应该尽可能的处理掉这些警告,你可以将所有警告都当作错误来处理:

尽量减少函数返回点

在方法中尽量减少它的返回点,不然你很难掌握方法会在哪个地方返回。在有些代码分支中,一旦你知道了整个方法执行结果,你可能就会立刻返回结果。

你可以想象到,一个具有20~30行代码的方法中有4个返回点是个什么情况,在方法执行期间,你很难判断它会在什么地方返回。

使用变量时才声明它

许多开发者喜欢在一个方法开始的地方将所有临时变量全部定义完,但是这样是不提倡的。我们更应该在我们需要使用临时变量的地方才开始声明它们,这样可读性更高,因为我们很清楚就可以知道即将使用到的变量初始化的值。

循环结构的检查

通常测试一个循环包含三个关键点:循环开始点、循环结束点以及中间任意选取的一点。如果你写的循环结构还包含其它特殊的情况,那么请细心测试它们。如果循环比较复杂,循环次数较多,那么你可以手动算一下循环次数。

总结

在任何软件公司中,遵守一个编码原则都是非常重要的。所以我还是重复那句话:Find a Convention and stick with it.如果你觉得我漏掉了某些重要的编码规范,可以在评论中给我留言,然后我会更新这篇博客,为快乐而编程:)

(以上翻译有删减)

C#/.NET code的更多相关文章

  1. Visual Studio Code 代理设置

    Visual Studio Code (简称 VS Code)是由微软研发的一款免费.开源的跨平台文本(代码)编辑器,在十多年的编程经历中,我使用过非常多的的代码编辑器(包括 IDE),例如 Fron ...

  2. 我们是怎么做Code Review的

    前几天看了<Code Review 程序员的寄望与哀伤>,想到我们团队开展Code Review也有2年了,结果还算比较满意,有些经验应该可以和大家一起分享.探讨.我们为什么要推行Code ...

  3. Code Review 程序员的寄望与哀伤

    一个程序员,他写完了代码,在测试环境通过了测试,然后他把它发布到了线上生产环境,但很快就发现在生产环境上出了问题,有潜在的 bug. 事后分析,是生产环境的一些微妙差异,使得这种 bug 场景在线下测 ...

  4. 从Script到Code Blocks、Code Behind到MVC、MVP、MVVM

    刚过去的周五(3-14)例行地主持了技术会议,主题正好是<UI层的设计模式——从Script.Code Behind到MVC.MVP.MVVM>,是前一天晚上才定的,中午花了半小时准备了下 ...

  5. 在Visual Studio Code中配置GO开发环境

    一.GO语言安装 详情查看:GO语言下载.安装.配置 二.GoLang插件介绍 对于Visual Studio Code开发工具,有一款优秀的GoLang插件,它的主页为:https://github ...

  6. 代码的坏味道(14)——重复代码(Duplicate Code)

    坏味道--重复代码(Duplicate Code) 重复代码堪称为代码坏味道之首.消除重复代码总是有利无害的. 特征 两个代码片段看上去几乎一样. 问题原因 重复代码通常发生在多个程序员同时在同一程序 ...

  7. http status code

    属于转载 http status code:200:成功,服务器已成功处理了请求,通常这表示服务器提供了请求的网页 404:未找到,服务器未找到 201-206都表示服务器成功处理了请求的状态代码,说 ...

  8. Visual Studio Code——Angular2 Hello World 之 2.0

    最近看到一篇用Visual Studio Code开发Angular2的文章,也是一篇入门教程,地址为:使用Visual Studio Code開發Angular 2專案.这里按部就班的做了一遍,感觉 ...

  9. WebStorm 2016 最新版激活(activation code方式)

    WebStorm 2016 最新版激活(activation code方式) WebStorm activation code WebStorm 最新版本激活方式: 今天下载最新版本的WebStorm ...

  10. docker4dotnet #3 在macOS上使用Visual Studio Code和Docker开发asp.net core和mysql应用

    .net猿遇到了小鲸鱼,觉得越来越兴奋.本来.net猿只是在透过家里那田子窗看外面的世界,但是看着海峡对岸的苹果园越来越茂盛,实在不想再去做一只宅猿了.于是,.net猿决定搭上小鲸鱼的渡轮到苹果园去看 ...

随机推荐

  1. DOM操作应用

    创建元素 document.createElement("li"); 添加节点 oUl.appendChild(oLi); 在某个元素之前插入一个节点 oUl.insertBefo ...

  2. java多线程Future和Callable类的解释与使用

    一,描写叙述 ​在多线程下编程的时候.大家可能会遇到一种需求,就是我想在我开启的线程都结束时,同一时候获取每一个线程中返回的数据然后再做统一处理,在这种需求下,Future与Callable的组合就派 ...

  3. linux挂载U盘,及乱码问题解决

    1. 首先使用切换到root用户. 2. 使用fdisk -l命令查看磁盘信息,找到u盘(能够依据显示的大小确定) 3. 在/mnt下创建挂载点,比如创建usb目录:mkdir /mnt/usb 4. ...

  4. uboot的relocation原理具体分析

    近期在一直在做uboot的移植工作,uboot中有非常多值得学习的东西.之前总结过uboot的启动流程,但uboot一个非常核心的功能没有细致研究.就是uboot的relocation功能. 这几天研 ...

  5. Cocos2d-x 3.0final 终结者系列教程01-无论是从cocos2d-x2.x升级到版本cocos2d-x3.x

    诡谲的江湖,易变. 花花世界,车来人往. 最终确定.安家,将Cocos2d-x3.0final相关技术精加工的版本.并推出了博客文章, 不为他人,只为自己. 学习交流QQ群:301954471 --- ...

  6. IT忍者神龟之使用 PowerDesigner

    1. 启动 PowerDesigner 新建物理数据模型 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdmlweWhk/font/5a6L5L2T/fon ...

  7. nyoj 7 街区最短路径问题 【数学】

    找出横纵坐标的中位数,怎么找:先对x排序找x的中位数x0,再对y排序找y的中位数y0:最后统计各点到中位数点(x0, y0)的总距离: 街区最短路径问题 时间限制:3000 ms  |  内存限制:6 ...

  8. GitLab版本管理(转)

    GitLab是利用 Ruby on Rails 一个开源的版本管理系统,实现一个自托管的Git项目仓库,可通过Web界面进行访问公开的或者私人项目.它拥有与Github类似的功能,能够浏览源代码,管理 ...

  9. Django架设blog步骤(转)

    最近在研究Python,起初是因为想做个爬虫,昨天看了点基础教程,台湾辅仁大学的视频,了解了python的语法规范及语言特性,主要有三: 1.动态脚本语言: 2.语法简洁,强制缩进: 3.应用广泛,w ...

  10. Android技术——切换视图(两)随着ViewPage达到Tab幻灯片浏览

    Android技术--切换视图(一)~(四)在资源项目:https://github.com/YongYuIT/MeiNv_Liulanqi 一.早期android(android.support.v ...