代码规范
一:背景
随着公司的业务发展,项目越来越多,越来越大,复杂性也越来越高。查找一个BUG变得越发抓狂;新人熟悉一块代码也变得越发困难。有的时候顺手写下的一行充满坏味道的代码,可能当时不会出现什么影响,而且当事人也十分清楚自己写的东西。但是,当日积月累之后,这种坏代码越来越多,整个项目就变得混乱不堪,牵一发而动全身,各种错误,修复了这影响了那。
这是个老生长谈的话题,要解决前面说的这些情况,必须要有一个规范来进行约束。不以规矩不成方圆,而且,这些规范必须也要有比较持续稳定的代码审核机制来支持。一个公司、团队值不值得去做这些,这是后话,这里不讨论。今天我们只各自阐明一下个人的建议和看法
以下这些是自己从网上和实际开发经历中搜罗的一些开发规范,其中不乏一些已经被说得老掉牙的东西,在这里算是一起重温一下。大家也可以发表一下自己的看法和觉得不合理的地方,一起交流交流。
二:代码规范
1.当一个条件判断(if,while)比较复杂,请写好注释。
2.类中的方法放置顺序,按照public,internal,protected,private这样的顺序从上往下放置。并且public中把增删改方法放在最前,查询放在之后。
3.字段的确定性尽可能的明确,且尽量按照如下顺序定义:const > readonly > 无
4.一个方法中尽量只做一件事,并且命名可以知道这个方法做了什么【方法的命名配合类的命名可以尽可能的简洁】
优点: (1)避免进行重复造轮子,出现一些重复的冗余的代码功能块。
5.如果是一个比较重要或者复杂的方法,需要进行单元测试。
优点: (1)确保系统中从未加入不正确的。不适合的变更;
(2)并且在后期的维护中能够随意修改软件的一部分,而不必担心在修改的过程中破坏其他的东西。
(3)这也是提升我们勇于进行修改优化旧代码的信心(不怕改了这边。那边出现问题的情况)。
6.逻辑判断:一个方法里面不要嵌套太多的逻辑判断(if else或者switch case),嵌套达到三层的判断就可以考虑把其中的一部分独立成新方法调用,或者使用尽快返回的方式。
7.生命周期:尽量缩短变量的存活周期,不是必须使用尽量不要使用全局变量
8.变量跨度:变量声明定义开始到第一次使用该变量的代码行之间的行距尽可能短
9.在操作非托管对象(如流操作)的时候尽量使用using(),这样不论在过程中是否发生异常,对象会在该代码段的最后自动释放占用资源,这样能防止手动漏写相关释放资源的代码,让程序自动回收处理。
10.使用自描述的变量名和方法名(让命名变得有意义)
11.声明方法的参数类型时,应尽量指定最弱的类型,最好是接口而不是基类。例如,如果要写一个方法来处理一组数据项,最好是用接口(比如IEnumerable<T>)来声明方法的参数,而不要用强数据类型(比如List<T>)或者更强的接口类型(比如ICollecion<T>或IList<T>)。
原因是可传递的参数对象变多。当然,如果方法需要的是一个列表(而非仅仅是可枚举的对象),就应该将参数类型声明为IList<T>。但是,仍然要避免声明为List<T>。声明为IList<T>,调用者可传递实现了IList<T>的其他类型对象。
同理,有基类的尽量使用基类。除非有特定原因。
相反,返回的时候返回最强的类型。
12.当一个方法的参数数量大于5个的时候,如果可能,声明一个单独的类进行封装。
12.从数据库获取一个数据集合时,如果未获取到数据,那么返回一个空集合,不要返回null。
13.对于一个方法超出了整个屏幕可以显示的范围,尽量去分割它(这时候屏幕大的优势就体现出来了)。
14.尽可能的考虑到会出现异常的数据情景,多使用条件判断来处理异常,而不是更多的try catch。
15.避免出现上帝类,每个类做其类名该做的事情。
16.代码写完之后要习惯进行统一的格式化
17.添加注释
① 类注释
类的注释,需要描述类的功能、依赖和如何使用
②代码注释
复杂的逻辑应当添加注释
③使用Region
使用关键字region注释使代码更加整洁
④全局变量注释
每个全局变量需要写注释
⑤程序流程变化注释
switch, if, while 等条件判断地方必须写注释
⑥public方法注释
public的方法体中的代码,需要写好详尽的注释
二:命名规范
1.用Pascal规则来命名方法和类型。
public class DataGrid
{
public void DataBind()
{
}
}
2.用Camel规则来命名局部变量和方法的参数.
public class Product
{
private string _productId;
private string _productName;
public void AddProduct(string productId,string productName)
{
}
}
3.所有的成员变量前加前缀“_”。
public class DataBase
{
private string _connectionString;
}
4.接口的名称加前缀 “I”。
public interface IConvertible
{
byte ToByte();
}
5.自定义的属性以“Attribute”结尾。
public class TableAttribute:Attribute
{
}
6.自定义的异常以Exception结尾。
public class NullEmptyException:Exception
{
}
7.方法的命名。一般将其命名为动宾短语。
public class File
{
public void CreateFile(string filePath)
{
}
public void GetPath(string path)
{
}
}
8.局部变量的名称要有意义。
不要用x,y,z等等,用For循环变量中可使用i, j, k, l, m, n。
public class User
{
public void GetUser()
{
string[] userIds={ "ziv ", "zorywa ", "zlh "};
for(int i=0,k=userIds.Length;i <k;i++)
{
}
}
}
9.所有的成员变量声明在类的顶端,用一个换行把它和方法分开。
public class Product
{
private string _productId;
private string _productName;
public void AddProduct(string productId,string productName)
{
}
}
10.用有意义的名字命名namespace,如:公司名、产品名。
namespace Zivsoft//公司命名
{
}
namespace ERP//产品命名
{
}
11.建议局部变量在最接近使用它时再声明。
12.使用某个控件的值时,尽量命名局部变量。
public string GetTitle()
{
string title=lbl_Title.Text;
return title;
}
14.把引用的系统的namespace和自定义或第三方的用一个换行把它们分开。
using System;
using System.Web.UI;
using System.Windows.Forms;
using CSharpCode;
using CSharpCode.Style;
15.文件名要能反应类的内容,最好是和类同名,一个文件中一个类或一组关连类。
16.目录结构中要反应出namespace的层次。
17.大括号 "{“要新起一行。
public Sample()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
18. 普通get/set属性,建议采用3.0的风格:
public string Name
{
get;
set;
}
19. 局部变量,看情况使用var,尽量不使用var关键字。
20. 对象初始化,能简写最好简写:
ValueText vt=new ValueText{Value=10, Text="Age"};
其实规则很重要,它是一种标准,可有可无,但有总会比无好。
备注:内容借鉴了多篇网上文字整合,都是自己用的,顺便方便大家,有雷同的道友别介意啊