文档章节

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

IT周见智
 IT周见智
发布于 2015/06/05 17:18
字数 3364
阅读 18
收藏 1
点赞 0
评论 0

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.如果你觉得我漏掉了某些重要的编码规范,可以在评论中给我留言,然后我会更新这篇博客,为快乐而编程:)

(以上翻译有删减)

© 著作权归作者所有

共有 人打赏支持
IT周见智

IT周见智

粉丝 10
博文 61
码字总数 185891
作品 0
西青
Windows: MSDN资源

Windows 7 and Windows Server 2008 R2 Application Quality Cookbook : http://msdn.microsoft.com/en-us/library/dd371778%28VS.85%29.aspx 其中: Tools, Best Practices, and Guidance T......

junwong
2012/03/09
0
0
5 More C# Extension Methods for the Stocking! (Plus a Bonus Method for Enums)

On the 15th day of C# Advent, I gave to my read-ers...fiiiiive Extension Methods. Sorry, I couldn't help it. In the spirit of the C# Advent calendar, and since my 10 Extremely U......

Jonathan Danylko
2017/12/14
0
0
WebSocket Server in C#

Download WebSockets - 47 KB (Relates to this article) Latest async version on Github (Targets .NetStandard 2.0) Set as the startup project. Introduction NEW - Complete refactor ......

Dave Haig
2017/12/24
0
0
Silverlight 2 End to End教程:创建Digg搜索客户端

Part0 Silverlight 2 End to End系列教程:创建Digg搜索客户端 翻译人:ttzhang(Technology Life) 翻译时间:2008/10/24 22:02:59 作者:ScottGu 出处:ScottGu's Blog Silverlight 2 End ......

56jobs
2008/10/24
0
0
Get Started Quickly With C# Logging

If you're interested in getting started with C# logging as quickly as humanly possible, you've come to the right place. Today, we'll look at just how to do that. Don't worry, we......

Erik Dietrich
2017/12/22
0
0
Selenium PageObjects and PageFactory

PageObject Design Pattern The PageObject design pattern models areas of a UI as objects within test code. The functionality classes (PageObjects) in this design represent a logi......

红焖鲤鱼
2016/03/24
133
0
97 Things Every Programmer Should Know

Welcome to the home page for the 97 Things Every Programmer Should Know project, pearls of wisdom for programmers collected from leading practitioners. You can read through the ......

晨曦之光
2012/03/09
0
0
转摘>

The following is from an EMail message that I sent to to an individual on 12-Apr-2001. You may find this EMail message useful. The Writer asked: Here is my reply: Thank you for ......

凌晨4点半
2014/10/27
0
0
基于 JVM 的编程语言--Coteline

Coteline 是一个全新的基于 JVM 的编程语言。Coteline 是 Ceylon 的超集,并保持对 Ceylon 的向后兼容。 比 Ceylon 改进的地方包括: " as a service", because is not a good keyword. , be...

红薯
2014/04/02
256
0
Creating Very Simple Console Chat App using C# and Redis Pub/Sub

Introduction This article is for beginner in Redis Pub/Sub. Actually Redis itself from its pub/sub documentation has a nice sample chat app written in Ruby here (try check it ou......

Garbel Nervadof
2017/12/20
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

50 行 Python 代码,带你追到最心爱的人

程序员世纪难题 人们一提到程序员第一反应就是:我知道!他们工资很高啊!但大部分都是单身狗,不懂得幽默风趣,只是每天穿格子 polo 衫的宅男一个。甚至程序员自己也这样形容自己:钱多话少...

猫咪编程
5分钟前
0
0
JAVA知识点随心记

1.Switch case具体的支持类型? Q:支持byte、short、char、int基本类型,枚举类型和String类型(JDK7以上支持),四种基本类型的包装类型也支持,但是原因在于触发了自动拆箱,将包装类型拆成了基本...

勤奋的蚂蚁
15分钟前
0
0
NoSQL

一、NoSQL介绍 NoSQL属于非关系型数据,mysql属于关系型数据库。 对于关系型数据库来说,是需要把数据存储到库、表、行、字段里,查询的时候根据条件一行一行地去匹配,当数据量非常大的时候...

人在艹木中
20分钟前
0
0
第17章MySQL主从配置

mysql安装总结 mysql主从准备工作: 准备两台机器,每台机器安装msyql服务,并启动mysql服务 mysql详细安装 1.首先下载二进制免编译的包,下载到/usr/local/src/目录下 2.解压压缩包 3.解压完...

Linux学习笔记
24分钟前
0
0
Redis高可用及分片集群

一、主从复制 使用异步复制 一个服务器可以有多个从服务器 从服务器也可以有自己的从服务器 复制功能不会阻塞主服务器 可以通过服务功能来上主服务器免于持久化操作,由从服务器去执行持久化...

Java大蜗牛
28分钟前
0
0
前端面试题汇总

最近在复习,准备找工作了,特此总结一下前端的相关知识。 1.获取浏览器URL中查询字符的参数: function getQuery(name){    var reg = new RegExp("(^|&)"+name+"=([^&]*)"(&|$));...

凛冬来袭
今天
0
0
可持续发展的学习道路

与其要求别人,不如提升自己 内心渴望进步 经常做出改变现有模式,不断学习 寻找资源,整合资源,不断熟练这种模式 渠道很重要 先打开新世界的航路

狮子狗
今天
0
0
apollox-lua开源项目 示例codepen2

今天在示例上增加了几个功能, 首先添加js array的标准库。 所有js array的方法目前都支持了。 添加查看code模式。 点击查看code可以看到生成的lua代码。默认web模式需要把标准库连接进来, ...

钟元OSS
今天
0
0
javascript性能优化之避免重复工作

javascript最重要也最根本的性能优化标准之一是避免工作,避免工作又包括两点,第一,不做不必要的工作,第二,不做重复的已经完成的工作。第一部分可以通过代码重构完成,第二部分不做重复的...

老韭菜
今天
0
0
缓存穿透、并发和雪崩那些事

0 题记 缓存穿透、缓存并发和缓存雪崩是常见的由于并发量大而导致的缓存问题,本文讲解其产生原因和解决方案。 缓存穿透通常是由恶意攻击或者无意造成的;缓存并发是由设计不足造成的;缓存雪...

Java填坑之路
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部