Table of Content 目錄
1 目的
為了統一公司軟體發展的設計過程中關於代碼編寫時的編寫規範和具體開發工作時的編程規範,保證代碼的一致性,便於交流和維護,特制定此規範。
2 範圍
本規範適用於開發組全體人員,作用於軟體專案開發的代碼編寫階段和後期維護階段。
3 C#編程規范
3.1 命名规则和风格
1. 类和方法名采用Pascal风格
public class SomeClass
{
public SomeMethod(){}
}
2. 局部变量和方法参数采用camel风格
void MyMethod(int someNumber)
{}
3. 接口名采用I作为前缀
interface IMyInterface
{..}
4. 私有成员变量采用m_作为前缀
public class SomeClass
{
private int m_Number;
}
5. 自定义属性类名采用Attribute作为后缀
6. 自定义异常类名采用Exception作为后缀
7. 采用动词-对象对命名方法,例如ShowDialog()
8. 有返回值的方法应该取名表示其返回值,例如GetObjectState()
9. 采用描述性的变量名。
a) 避免采用单字母的变量名,如i或t;而是采用index或temp。
b) 对public和protected成员避免采用匈牙利命名法。
c) 不要采用缩写(例如将number缩写为num)。
10. 总是使用C#预定义的类型,而不是使用System命名空间中的别名。例如:采用object不用Object,采用string不用String,采用int不用Int32。
11. 采用有意义的命名空间名,例如产品名称或公司名称。
12. 避免使用类的全称,而是采用using语句。
13. 避免在命名空间内使用using语句。
14. 将所有framework命名空间名放在一起,后面放自定义或第三方的命名空间名。
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using MyCompany;
using MyControls;
15. 采用委托推断,不要显式实例化委托。
delegate void SomeDelegate();
public void SomeMethod()
{}
SomeDelegate someDelegate = SomeMethod;
16. 严格遵守缩进格式。
a) 缩进采用4个空格。
b) 不用采用tab或非标准的缩进。
17. 注释缩进和其注释的代码在同一层次。
18. 所有注释要经过拼写检查。拼写错误的注释表明开发的草率。
19. 所有成员变量应该定义在前面,和属性或方法间空开一行。
public class MyClass
{
int m_Number;
string m_Name;
public void SomeMethod1()
{}
public void SomeMethod2()
{}
}
20. 局部变量的定义尽可能靠近它的初次使用。
21. 文件名应该体现其包含的类。
22. 当使用partial类型且每部分分配一个文件时,以类型名加P和序数命名每个文件。
//In MyClassP1.cs
public partial class MyClass
{}
//In MyClassP2.cs
public partial class MyClass
{}
23. 左大括号总是放在新行中。
24. 匿名方法模仿普通方法的布局,和匿名委托定义放在一行。
a) 遵守将左大括号放在新行的规则。
delegate void SomeDelegate(string someString);
//正确
public void InvokeMethod()
{
SomeDelegate someDelegate = delegate(string name)
{
MessageBox.Show(name);
};
someDelegate("Juval");
}
//避免采用:
public void InvokeMethod()
{
SomeDelegate someDelegate = delegate(string name){MessageBox.Show(name);};
someDelegate("Juval");
}
25. 没有参数的匿名方法使用空括号。
a) 仅当匿名方法可能被用于任何委托时省略括号。
delegate void SomeDelegate();
//正確
SomeDelegate someDelegate1 = delegate()
{
MessageBox.Show("Hello");
};
//避免
SomeDelegate someDelegate1 = delegate
{
MessageBox.Show("Hello");
};
3.2 编码惯例
1. 避免在一个文件中放多个类。
2. 一个文件应该只对一个命名空间提供类型。避免在同一文件中有多个命名空间。
3. 避免文件长度超过500行(除了机器自动产生的代码)。
4. 避免方法定义超过25行。
5. 避免超过5个参数的方法。使用结构传递多个参数。
6. 每行应该不超过80个字符。
7. 不要手工编辑任何机器生成的代码。
a) 如果修改机器生成的代码,修改代码格式和风格以符合本编码标准。
b) 尽可能采用partial类以分解出需要维护的部分。
8. 避免对显而易见的内容作注释。
a) 代码应该是自解释的。 由可读性强的变量和方法组成的好的代码应该不需要注释。
9. 仅对操作的前提、内在算法等写文档。
10. 避免方法级的文档。
a) 对API文档采用大量的外部文档。
b) 方法级注释仅作为对其他开发人员的提示。
11. 决不要硬编码数值,而总是声明一个常量。
12. 仅对本来就是常量的值使用const修饰符,例如一周的天数。
13. 避免对只读变量使用const修饰符。在此情况下,采用readonly修饰符。
public class MyClass
{
public readonly int Number;
public MyClass(int someValue)
{
Number = someValue;
}
public const int DaysInWeek = 7;
}
14. 对任何假设采用assert。
using System.Diagnostics;
object GetObject()
{…}
object obj = GetObject();
Debug.Assert(obj != null);
15. 每行代码应该经过白盒测试。
16. 仅捕获已经显式处理了的异常。
17. 在抛出异常的catch语句中,总是抛出最初异常以保持最初错误的堆栈位置。
catch(Exception exception)
{
MessageBox.Show(exception.Message);
throw; //Same as throw exception;
}
18. 避免将错误代码作为方法的返回值。
19. 避免定义自定义的异常类。
20. 定义自定义异常时:
a) 从ApplicationException继承
b) 提供自定义的序列化。
21. 避免在一个程序集中有多个Main()方法。
22. 仅对最需要的类型标记为public,其他的标记为internal。
23. 避免采用friend程序集,因为这样增加了程序集间的耦合度。
24. 避免使用依赖于从特定位置运行的程序集的代码。
25. 尽量减少应用程序集(客户端EXE程序集)的代码。采用类库而不要包含业务逻辑层代码。
26. 避免对枚举提供明确的值。
//正確
public enum Color
{
Red,Green,Blue
}
//避免
public enum Color
{
Red = 1,Green = 2,Blue = 3
}
27. 避免对枚举指定类型。
//避免
public enum Color : long
{
Red,Green,Blue
}
28. if语句总是使用括号,即使它包含一句语句。
29. 避免使用?:条件算符。
30. 避免在布尔条件语句中调用函数。赋值到局部变量并检查它们的值。
bool IsEverythingOK()
{...}
//避免:
if(IsEverythingOK())
{...}
//采用:
bool ok = IsEverythingOK();
if(ok)
{...}
31. 总是使用从0开始的数组。
32. 总是使用一个for循环显式地初始化一个引用类型的数组。
public class MyClass
{}
MyClass[] array = new MyClass[100];
for(int index = 0; index < array.Length; index++)
{
array[index] = new MyClass();
}
33. 不用提供public或protected成员变量,而是使用属性。
34. 避免使用new继承修饰符,而是使用override。
35. 对非密封类总是将public和protected方法标记为virtual。
36. 除非涉及到互操作,永远不要用不安全的代码。
37. 避免显式类型转换。使用as算法防护性地转换类型。
Dog dog = new GermanShepherd();
GermanShepherd shepherd = dog as GermanShepherd;
if(shepherd != null)
{...}
38. 类成员有委托时:
a) 使用前将委托复制到局部变量,以避免并发冲突。
b) 调用前始终检查委托是否为空。
public class MySource
{
public event EventHandler MyEvent;
public void FireEvent()
{
EventHandler temp = MyEvent;
if(temp != null)
{
temp(this,EventArgs.Empty);
}
}
}
39. 不要提供public的事件成员变量,而是使用事件访问器。
public class MySource
{
MyDelegate m_SomeEvent;
public event MyDelegate SomeEvent
{
add
{
m_SomeEvent += value;
}
remove
{
m_SomeEvent -= value;
}
}
}
40. 使用Programming .NET Components中定义的EventsHelper类安全地发布事件。
41. 面向接口編程。
42. 避免使用一个成员的接口。
43. 努力使每个接口拥有3-5个成员。
44. 努力每个接口不用超过20个成员。
45. 避免将事件作为接口成员。
46. 避免使用抽象方法,而是使用接口代替。
47. 不要假设一种类型支持某个接口。防护性地检查是否支持该接口。
SomeType obj1;
IMyInterface obj2;
/* Some code to initialize obj1, then: */
obj2 = obj1 as IMyInterface;
if(obj2 != null)
{
obj2.Method1();
}
else
{
//Handle error in expected interface
}
48. 将呈现给用户的字符串永远不用硬编码,而是使用资源。
49. 发布时可能修改的字符串不用硬编码,例如连接字符串。
50. 构建一个长字符串时,使用StringBuilder,不要用string。
51. 避免提供带结构的方法。
a) 参数化的构造函数是鼓励使用的。
b) 可以重载算符。
52. 当提供静态成员变量时,提供一个静态构造函数。
53. 可以用前期绑定就不要用后期绑定。
54. 对应用程序进行日志和跟踪。
55. 除非在switch语句中跳转,不要用goto语句。
56. switch语句中使用default用于加断言。
int number = SomeMethod();
switch(number)
{
case 1:
Trace.WriteLine("Case 1:");
break;
case 2:
Trace.WriteLine("Case 2:");
break;
default:
Debug.Assert(false);
break;
}
57. 除非在构造函数中调用另一个构造函数,否则不用使用this。
//Example of proper use of this
public class MyClass
{
public MyClass(string message)
{}
public MyClass() : this("hello")
{}
}
58. 除非为了解决调用基类构造函数时成员名的冲突,否则不要使用base访问基类的成员。
//Example of proper use of base
public class Dog
{
public Dog(string name)
{}
virtual public void Bark(int howLong)
{}
}
public class GermanShepherd : Dog
{
public GermanShepherd(string name): base(name)
{}
override public void Bark(int howLong)
{
base.Bark(howLong);
}
}
59. 使用泛型的代码中避免与System.Object进行类型转换,而是使用限制或as算符。
class SomeClass
{}
//避免
class MyClass<T>
{
void SomeMethod(T t)
{
object temp = t;
SomeClass obj = (SomeClass)temp;
}
}
//正确
class MyClass<T> where T : SomeClass
{
void SomeMethod(T t)
{
SomeClass obj = t;
}
}
59. 泛型接口不要定义限制。接口层的限制通常能用强类型代替。
public class Customer
{...}
//避免
public interface Ilist<T> where T : Customer
{...}
//正确
public interface ICustomerList : Ilist<Customer>
{...}
60. 不要在接口中定义与方法相关的限制。
61. 使用String.Empty取代””
//避免
string name=” ”;
//正确
string name=String.Empty;
62. 总是在unchecked状态下运行代码(出于性能的原因),但是为了防止溢出或下溢操作,要果断地使用checked模式。
Int CalcPower(int number,int power)
{
int result=1;
for (int count=1;count<=power;count++)
{
checked
{
result*=number;
}
}
return result;
}
63. 使用条件方法来取代显式进行方法调用排除的代码(#if…#endif)
public class MyClass
{
[Conditional("MySpecialCondition")]
public void MyMethod( )
{}
}
4 Asp.Net編程規范
4.1 變量、控件、組件命名
1.页面级变量:级别标识为m (例如:string m_strNewline)
2.页面间变量:采用request传递获取
1.DOM對像命名规范 |
|
|
text | txt | txtFirstName |
button | btn | btnSubmit |
select | sel | selSex |
option | opt | optMale |
form | frm | frmMain |
frame | fra | fraContent |
hidden | hdn | hdnRefresh |
div | div | divMenu |
span | span | spanLogo |
對話框對像 | dlg | dlgAlert |
窗口對像 | win | winDetail |
2.服務器控件命名规范 |
|
|
AdRotator | adrt | adrtTopAd |
Button | btn | btnSubmit |
Calendar | cal | calMettingDates |
CheckBox | chk | chkBlue |
CheckBoxList | chkl | chklFavColors |
CompareValidator | valc | valcValidAge |
CustomValidator | valx | valxDBCheck |
DataGrid | dgrd | dgrdTitles |
DataList | dlst | dlstTitles |
DropDownList | drop | dropCountries |
HyperLink | lnk | lnkDetails |
Image | img | imgAuntBetty |
ImageButton | ibtn | ibtnSubmit |
Label | lbl | lblResults |
LinkButton | lbtn | lbtnSubmit |
ListBox | lst | lstCountries |
Panel | pnl | pnlForm2 |
PlaceHolder | plh | plhFormContents |
RadioButton | rad | radFemale |
RadioButtonList | radl | radlGender |
RangeValidator | valg | valgAge |
RegularExpression | vale | valeEmail_Validator |
Repeater | rpt | rptQueryResults |
RequiredFieldValidator | valr | valrFirstName |
Table | tbl | tblCountryCodes |
TableCell | tblc | tblcGermany |
TableRow | tblr | tblrCountry |
TextBox | txt | txtFirstName |
ValidationSummary | vals | valsFormErrors |
XML | xmlc | xmlcTransformResults |
3.ADO.NET組件命名规范 |
|
|
Connection | con | conNorthwind |
Command | cmd | cmdReturnProducts |
Parameter | parm | parmProductID |
DataAdapter | dad | dadProducts |
DataReader | dtr | dtrProducts |
DataSet | dst | dstNorthWind |
DataTable | dtbl | dtblProduct |
DataRow | drow | drowRow98 |
DataColumn | dcol | dcolProductID |
DataRelation | drel | drelMasterDetail |
DataView | dvw | dvwFilteredProducts |
4.以下是一些常用的C#成员及其推荐命名方法 |
|
|
标志符 | 规则 | 实例与描述 |
类Class | Pascal | Application |
枚举类型Enum | Pascal | 记住,是以Pascal命名,切勿包含Enum,否则FXCop会抛出Issue |
委托Delegate | Pascal | 以Pascal命名,不以任何特殊字符串区别于类名、函数名 |
常量Const | 全部大写 | 全部大写,单词间以下划线隔开 |
接口Interface | Pascal | IDisposable 注:总是以 I 前缀开始,后接Pascal命名 |
方法Function | Pascal | ToString |
命名空间Namespace | Pascal | 以.分隔,当每一个限定词均为Pascal命名方式,比如: |
using ExcelQuicker.Framework | ||
参数 | Camel | 首字母小写 |
局部变量 | Camel | 也可以加入类型标识符,比如对于System.String类型,声明变量是以str开头,string strSQL = string.Empty; |
数据成员 | Camel | 以m开头+Pascal命名规则,如m_ProductType(m意味member) |
属性(Property) | Pascal | BackColor |
受保护的实例字段(Field) | camel | backColor |
注意:很少使用。属性优于使用受保护的实例字段。 | ||
公用实例字段(Field) | Pascal | BackColor |
注意:很少使用。属性优于使用公用实例字段。 | ||
屬性(Attribute) | Pascal | XmlElementAttribute,最后要以Attribute结束 |
事件Event | Pascal | ValueChanged |
異常Exception | Pascal | Exception为后缀 |
4.2 注釋規范
1、文件头部注释
在代码文件的头部进行注释,这样做的好处在于,我们能对代码文件做变更跟踪。在代码头部分标注出创始人、创始时间、修改人、修改时间、代码的功能,这在团队开发中必不可少,它们可以使后来维护/修改的同伴在遇到问题时,在第一时间知道他应该向谁去寻求帮助,并且知道这个文件经历了多少次迭代、经历了多少个程序员的开发和修改。
样本:
/********************************************************************************
** 創建人: Eunge
** 创建时间:2004-6-8
** 修改人:Lucy
** 修改时间:2004-12-9
** 修改人:Lucy
** 修改时间:2005-01-29
** 描述:主要用于产品信息的资料录入
*********************************************************************************/
2、函数、属性、类等注释
请使用///三斜线注释,这种注释是基于XML的,不仅能导出XML制作帮助文档,而且在各个函数、属性、类等的使用中,编辑环境会自动带出注释,方便你的开发。以protected,protected Internal,public声明的定义注释都建议以这样命名方法。
例如:
/// <summary>
///函数、属性、类作用描述
///創建人
///創建時間
///修改人
///修改時間
/// </summary>
/// <param name="參數">參數名</param>
/// <returns>如果有返回值則需填上</returns>
函数、属性、类
{
…
//邏輯點注釋
}
3、逻辑点注释
在我们认为逻辑性较强的地方加入注释,说明这段程序的逻辑是怎样的,以方便我们自己后来的理解以及其他人的理解,并且这样还可以在一定程度上排除BUG。在注释中写明我们的逻辑思想,对照程序,判断程序是否符合我们的初衷,如果不是,则我们应该仔细思考要修改的是注释还是程序了
4、代碼段說明
為了使代碼段結構清晰易讀,必須使用#region和#endregion將相同功能或邏輯的代碼段分組
例如:
#region 代碼段說明文字
代碼段…
#endregion
4.3 文件目錄
App_Code存放WebSite可重用Class
App_GlobalResources存放全球(本地化)資源
Bin存放dll、com+
Script存放JS,VBScript
Image存放圖片
CSS存放樣式
Theme存放主題
Skin 存放皮膚
MasterPage 存放母版
UserControl存放用戶自定義控件(ascx)
Log日志,建議放在db裡,不要使用xml或txt或系統方式記錄
UploadFiles上傳的文件,建議使用CMS內容管理系統
Report存放報表,建議用Reporting Services報表服務器集成管理
WebService存放WebService Class
4.4 分層架構
BLL業務邏輯層
DAL數據訪問層,這層將會用ORM實現
UI 顯示層,主要放Aspx頁面
4.5 頁面佈局
使用MasterPage(Header和Footer建議做成ascx)
HeaderLogo Navigation Menu |
Body(Content) |
Footer(Copy Right,Project Version) |
4.6 控件使用
原则:尽可能使用Html控件,需要提交而又不用在客户端使用Javasrcipt的可以使用Web控件
,如果是唯讀的Web控件必須要禁用ViewState(如GridView)
控件使用约定:
列表用GridView/DataList/Repeater
分頁用一個Pager組件(如AspNetPager)
輸入框用TextBox
下拉框用DropDownList
日期可用一些JS日期控件(如My97 Date Picker)
按鈕用Button
區域用TextArea
多選用CheckBoxList
單選用RadioButtonList
上傳文件用FileUpload或Ajax上傳組件
在線HTML編輯推薦使用FreeTextBox
4.7 CSS
链接类:
a:link {font-size: 12px;line-height: 20px;text-decoration: none; color: #666666}
a:visited {font-size: 12px;line-height: 20px;color: #666666;text-decoration:none;}
a:hover {font-size: 12px;line-height: 20px;color: #ff6600;text-decoration:underline;}
a:active {font-size: 12px;line-height: 20px;color: #666666;text-decoration:underline;}
表格类:
td{font-size: 12px; line-height: 20px; text-decoration: none;}
文本框类:
.input{border-right: #99ccff 1px solid; border-top: #99ccff 1px solid;border-left: #99ccff 1px solid; border-bottom: #99ccff 1px solid;height: 22px}
grid类:
.dg_grid /* grid-总体 */{font-size:12px; border-style:solid; border-width:2px; border-color:white;text-align:center; vertical-align:middle;}
.dg_header /* grid-页眉 */{font-weight :bold ; color:#e7e7ff; background-color :#3366cc; text-align:center;vertical-align:middle; height:25px;}
.dg_alter /* grid-交替行 */{background-color :aliceblue; height:22px;}
.dg_item /* grid-普通行 */{color :black; background-color:whitesmoke; height:22px;}
.dg_page /* grid-页导航 */{color:black; text-align:right; vertical-align:middle; height:22px;}
.dg_select/* grid-选择行 */{font-weight :bold ; color:white; background-color :#9471de;}
4.8 Script
使用jQuery框架能快速完成JavaScript對DOM的選取和操作,內含Ajax框架
4.9 Ajax
推薦使用微軟的ajax庫
4.10 ORM
推薦使用nHibernate
4.11 開發模式
1.基於WebForm+Server Control+CodeBehide的MVP模式
2.基於Model+View(WebForm+Template)+Controler的MVC模式
5 推薦開發環境、工具及組件
5.1 開發環境
基礎環境(所有的開發人員都應該安裝)
winxp/winserver2003+IIS6.0+ie6+IEDevToolbar+FireFox+FireBug+mssql2005 develop edition
開發工具
A、一般開發人員
vs.net2008pro
B、架構師(架構組和SA級別)
VSTE for Architect
C、測試人員
VSTE for Tester
5.2 工具及組件
UML推薦Rose/StartUML, DataBase建模推薦Power Designer
文本編輯工具推薦UltraEdit
開源框架推薦jQuery(js),ExtJs(js),nHbiernate,Spring.net
報表工具推薦Reporting Services
日志組件推薦使用Log4Net
其它推薦工具
Sandcastle:帮助文档生成工具
Reflector for .NET:类浏览器和反编译器
The Regulator:生成和测试正则表达式
代碼生成:A、CodeSmith B、动软.Net代码生成器