1、 命名规范(Naming Convention)
总则:
1、标识符的命名要清晰、明了,有明确含义,同时使用完整的单词或大家基本可以理解的缩写,避免使人产生误解。
说明:较短的单词可通过去掉“元音”形成缩写;较长的单词可取单词的头几个字母形成缩写;一些单词有大家公认的缩写。
示例:如下单词的缩写能够被大家基本认可。
temp可缩写为 tmp ;
flag可缩写为 flg ;
statistic可缩写为 stat ;
increment可缩写为 inc ;
message可缩写为 msg ;
2、对于变量命名,禁止取单个字符(如i、j、k...),但i、j、k作局部循环变量是允许的。
3、除非必要,不要用数字或较奇怪的字符来定义标识符。
4、用正确的反义词组命名具有互斥意义的变量或相反动作的函数等。
说明:下面是一些在软件中常用的反义词组。
add/ remove begin / end create / destroy
insert/ delete first / last get / release
increment/ decrement put / get
add/ delete lock / unlock open / close
min/ max old / new start / stop
next/ previous source / target show / hide
send/ receive source / destination
cut/ paste up / down
示例:
int min_sum;
int max_sum;
int add_user( BYTE *user_name );
int delete_user( BYTE *user_name );
1.1、包(Packages)
包名全部用小写的ASCI字母,顶级包名通常是com,gov,edu,mil,net,org,或1981年ISO3166标准所指定的标识的国家的英文双字符代码。包名的后续部分根据不同机构各自内部的命名规范而不尽相同。这类命名规范可能以特定目录名的组成来区分部门(department),项目(project),机器(machine),或注册名(login names)。
例如:
com.sun.eng
com.apple.quicktime.v2
edu.cmu.cs.bovik.cheese
1.2、类(Classes)
类名是一个名词,采用大小写混合方式,每个单词的首字母大写(帕斯卡命名法)。尽量使你的类名简洁而富于描述。使用完整单词,避免缩写词(除非该缩写词被广泛的使用,如URL,HTML,在命名过程中如采用缩写则缩写字母全部大写)。
例如:
classRaster
classImageSprite
1.3、接口(Interfaces)
同类名规范。
interfaceRasterDelegate
interfaceStoring
1.4、方法(Methods)
方法名使用动词或动宾词组,应准确描述函数的功能,避免使用无意义或含义不清的动词为函数命名(如process、handle),采用大小写混合方式,第一个单词的首字母小写,其后单词的首字母大写(骆驼命名法)。
例如:
run()
runFase()
getBackground()
1.5、变量(Variables)
变量名均采用大小写混合的方式,应简短且富于描述,易于记忆,即,能够指出其用途。第一个单词的首字母小写,其后单词的首字母大写(骆驼命名法)。变量名非特殊情况不应以下划线或美元符号开头,尽管这在语法上是允许的。
例如:
charc
inti
floatmyWidth
1.6、常量(Constants)
staticfinal变量的名字应该都大写,并且指出完整含义,单词间用下划线分隔。
例如:
staticfinal int MIN_WIDTH = 4
staticfinal int MAX_WIDTH = 999
staticfinal int GET_THE_CPU = 1
2、 排版
2.1、
程序块要采用缩进风格编写,缩进的空格数为4个。对齐只使用空格键,不使用TAB键。
说明:以免用不同的编辑器阅读程序时,因TAB键所设置的空格数目不同而造成程序布局不整齐
2.2、
相对独立的程序块之间、变量说明之后必须加空行。源程序中关系较为紧密的代码应尽可能相邻。
空行将逻辑相关的代码段分隔开,以提高可读性。
下列情况应总是使用两个空行:
◆一个源文件的两个片段(section)之间。
◆类声明和接口声明之间。
下列情况应该总是使用一个空行:
◆两个方法之间。
◆方法内的局部变量和方法的第一条语句之间。
◆块注释或单行注释之前。
◆一个方法内的两个逻辑段之间,用以提高可读性。
2.3、
空格(Blank Spaces)
示例:
(1) 逗号、分号只在后面加空格。
int a, b, c;
(2)比较操作符, 赋值操作符"="、"+=",算术操作符"+"、"%",逻辑操作符"&&"、"&",位域操作符"<<"、"^"等双目操作符的前后加空格。
if (current_time >= MAX_TIME_VALUE)
a = b + c;
a *= 2;
a = b ^ 2;
(3)"!"、"~"、"++"、"--"、"&"(地址运算符)等单目操作符前后不加空格。
*p = 'a'; // 内容操作"*"与内容之间
flag = !isEmpty; // 非操作"!"与内容之间
p = &mem; // 地址操作"&" 与内容之间
i++; // "++","--"与内容之间
(4)"->"、"."前后不加空格。
p->id = pid; // "->"指针前后不加空格
(5) if、for、while、switch等与后面的括号间应加空格,使if等关键字更为突出、明显。
if (a >= b && c > d)
2.4、
一行程序以小于80字符为宜,不要写得过长。较长的语句(>80字符)要分成多行书写,长表达式要在低优先级操作符处划分新行,操作符放在新行之首,划分出的新行要进行适当的缩进,使排版整齐,语句可读。
示例:
permCountMsg.head.len = NO7_TO_STAT_PERM_COUNT_LEN
+ STAT_SIZE_PER_FRAM * sizeOf(_UL );
actTaskTable[frameId * STAT_TASK_CHECK_NUMBER +index].occupied
=statPoi[index].occupied;
actTaskTable [taskNo].durationTrueOrFalse
= getSccpStatisticState(statItem);
reportOrNotFlag = ((taskNo < MAX_ACT_TASK_NUMBER)
&& (n7statStatItemValid(statItem))
&& (actTaskTable[taskNo].resultData != 0));
2.5、
循环、判断等语句中若有较长的表达式或语句,则要进行适应的划分,长表达式要在低优先级操作符处划分新行,操作符放在新行之首。
示例:
if ((taskNo< maxActTaskNumber)
&&(n7statStatItemValid(stat_item)))
{
... // program code
}
for (i =0, j = 0; (i < bufferKeyword[word_index].wordLength)
&&(j < newKeyword.wordLength); i++, j++)
{
... // program code
}
for (i =0, j = 0;
(i < firstWordLength) && (j< secondWordLength);
i++, j++)
{
... // program code
}
2.6、
若函数或过程中的参数较长,则要进行适当的划分。
示例:
n7statStrCompare((BYTE *) & statObject,
(BYTE *) & (actTaskTable[taskNo].statObject),
sizeof (_STAT_OBJECT));
n7statFlashActDuration(statItem, frameId*STAT_TASK_CHECK_NUMBER
+ index,statObject);
2.7、
不允许把多个短语句写在一行中,即一行只写一条语句。
示例:如下例子不符合规范。
rect.length= 0; rect.width = 0;
应如下书写
rect.length= 0;
rect.width = 0;
2.8、
if、for、do、while、case、switch、default等语句自占一行,且if、for、do、while等语句的执行语句部分无论多少都要加括号{}。
示例:如下例子不符合规范。
if(pUserCR == NULL) return;
应如下书写:
if(pUserCR == NULL)
{
return;
}
2.9、
程序块的分界符(如C/C++语言的大括号‘{’和‘}’)应各独占一行并且位于同一列,同时与引用它们的语句左对齐。在函数体的开始、类的定义、结构的定义、枚举的定义以及if、for、do、while、switch、case语句中的程序都要采用如上的缩进方式。考虑到实际的java程序开发中经常有如下示例的缩进格式,故如下所示格式也符合本文档规范,
for (...){
... // program code
}
但仅限于在java程序书写中。其它语言开发过程中还保持原有规定。在java代码书写中,采用了某一种格式后,应保持风格统一。
示例:如下例子不符合规范。
for (...){
... // program code
}
(上面例子尽在java代码中符合本规范约定)
if (...)
{
... // program code
}
voidexampleFun(void)
{
... // program code
}
应如下书写。
for (...)
{
... // program code
}
if (...)
{
... // program code
}
voidexampleFun(void)
{
... // program code
}
3、 注释
3.1、
源文件头部应进行注释,列出:版权说明、版本号、生成日期、作者、模块目的/功能、主要函数及其功能、修改日志等。
示例:下面这段源文件的头注释比较标准,当然,并不局限于此格式,但上述信息建议要包含在内。
/************************************************************
Copyright (C), 1988-1999, Huawei Tech. Co.,Ltd.
FileName: test.cpp
Author: Version : Date:
Description: // 模块描述
Version: // 版本信息
Function List: // 主要函数及其功能
1. -------
History: // 历史修改记录
<author><time><version><desc>
David 96/10/12 1.0 build this moudle
***********************************************************/
说明:Description一项描述本文件的内容、功能、内部各部分之间的关系及本文件与其它文件关系等。History是修改历史记录列表,每条修改记录应包括修改日期、修改者及修改内容简述。
3.2、
函数头部应进行注释,列出:函数的目的/功能、输入参数、输出参数、返回值、调用关系(函数、表)等。
示例:下面这段函数的注释比较标准,当然,并不局限于此格式,但上述信息建议要包含在内。
/*************************************************
Function: // 函数名称
Description: // 函数功能、性能等的描述
Calls: // 被本函数调用的函数清单
Called By: // 调用本函数的函数清单
Table Accessed: // 被访问的表(此项仅对于牵扯到数据库操作的程序)
Table Updated: // 被修改的表(此项仅对于牵扯到数据库操作的程序)
Input: // 输入参数说明,包括每个参数的作
// 用、取值说明及参数间关系。
Output: // 对输出参数的说明。
Return: // 函数返回值的说明
Others: // 其它说明
*************************************************/
3.3、
边写代码边注释,修改代码同时修改相应的注释,以保证注释与代码的一致性。不再有用的注释要删除。
3.4、
注释的内容要清楚、明了,含义准确,防止注释二义性。
说明:错误的注释不但无益反而有害。
3.5、
避免在注释中使用缩写,特别是非常用缩写。
说明:在使用缩写时或之前,应对缩写进行必要的说明。
3.6、
注释应与其描述的代码相近,对代码的注释应放在其上方或右方(对单条语句的注释)相邻位置,不可放在下面,如放于上方则需与其上面的代码用空行隔开。
示例:如下例子不符合规范。
例1:
/* getreplicate sub system index and net indicator */
repssnInd= ssnData[index].repssnIndex;
repssnNi =ssnData[index].ni;
例2:
repssnInd= ssnData[index].repssnIndex;
repssnNi =ssnData[index].ni;
/* getreplicate sub system index and net indicator */
应如下书写
/* getreplicate sub system index and net indicator */
repssnInd= ssnData[index].repssnIndex;
repssnNi =ssnData[index].ni;
3.7、
对于所有有物理含义的变量、常量,如果其命名不是充分自注释的,在声明时都必须加以注释,说明其物理含义。变量、常量、宏的注释应放在其上方相邻位置或右方。
3.8、
数据结构声明(包括数组、结构、类、枚举等),如果其命名不是充分自注释的,必须加以注释。对数据结构的注释应放在其上方相邻位置,不可放在下面;对结构中的每个域的注释放在此域的右方。
示例:可按如下形式说明枚举/数据/联合结构。
/* sccpinterface with sccp user primitive message name */
enum SCCP_USER_PRIMITIVE
{
N_UNITDATA_IND, /* sccp notify sccp userunit data come */
N_NOTICE_IND, /* sccp notify user the No.7 network can not*/
/* transmission thismessage */
N_UNITDATA_REQ, /* sccp user's unit datatransmission request*/
};
3.9、
全局变量要有较详细的注释,包括对其功能、取值范围、哪些函数或过程存取它以及存取时注意事项等的说明。
3.10、
注释与所描述内容进行同样的缩排。
说明:可使程序排版整齐,并方便注释的阅读与理解。
示例:如下例子,排版不整齐,阅读稍感不方便。
voidexample_fun( void )
{
/* codeone comments */
CodeBlock One
/* code two comments */
CodeBlock Two
}
应改为如下布局。
voidexample_fun( void )
{
/* code one comments */
CodeBlock One
/* code two comments */
CodeBlock Two
}
3.11、
将注释与其上面的代码用空行隔开。
示例:如下例子,显得代码过于紧凑。
/* codeone comments */
programcode one
/* codetwo comments */
programcode two
应如下书写
/* codeone comments */
programcode one
/* codetwo comments */
programcode two
3.12、
对变量的定义和分支语句(条件分支、循环语句等)必须编写注释。
说明:这些语句往往是程序实现某一特定功能的关键,对于维护人员来说,良好的注释帮助更好的理解程序,有时甚至优于看设计文档。
3.13、
对于switch语句下的case语句,如果因为特殊情况需要处理完一个case后进入下一个case处理,必须在该case语句处理完、下一个case语句前加上明确的注释。
说明:这样比较清楚程序编写者的意图,有效防止无故遗漏break语句。
示例(注意斜体加粗部分):
caseCMD_UP:
ProcessUp();
break;
caseCMD_DOWN:
ProcessDown();
break;
caseCMD_FWD:
ProcessFwd();
if (...)
{
...
break;
}
else
{
ProcessCFW_B(); // now jumpinto case CMD_A
}
caseCMD_A:
ProcessA();
break;
case CMD_B:
ProcessB();
break;
caseCMD_C:
ProcessC();
break;
caseCMD_D:
ProcessD();
break;
...
3.14、
避免在一行代码或表达式的中间插入注释。
说明:除非必要,不应在代码或表达中间插入注释,否则容易使代码可理解性变差。
3.15、
通过对函数或过程、变量、结构等正确的命名以及合理地组织代码的结构,使代码成为自注释的。
说明:清晰准确的函数、变量等的命名,可增加代码可读性,并减少不必要的注释。
3.16、
在代码的功能、意图层次上进行注释,提供有用、额外的信息。
说明:注释的目的是解释代码的目的、功能和采用的方法,提供代码以外的信息,帮助读者理解代码,防止没必要的重复注释信息。
示例:如下注释意义不大。
/* ifreceive_flag is TRUE */
if(receive_flag)
而如下的注释则给出了额外有用的信息。
/* if mtpreceive a message from links */
if (receive_flag)