源代码编写规范.docx
《源代码编写规范.docx》由会员分享,可在线阅读,更多相关《源代码编写规范.docx(14页珍藏版)》请在冰豆网上搜索。
源代码编写规范
源代码编写规范
版本<1.0>
1简介
1.1目的
本文用于定义本公司程序编码规范。
本文的目的在于规范和指导软件编程活动,作为考核标准。
1.2范围
本文仅用于指导软件编程工作,同时作为其他分析和设计工作的参考资料。
本文的预期读者是:
软件工程师/设计员、程序员。
本公司各项目可以采用不同的编程语言,并参照本规范和各语言的习惯定义各自的编程规范,但是必须经过评审通过。
编程规范一旦通过评审,任何人在编程活动中都必须遵循。
2代码格式规范
【规范1】单行代码不得超过120字符。
【规范2】每行代码最多包含一个独立的语句。
【规范3】代码缩进两个空格。
说明:
两个空格已经足够清晰了,缩进量过大会导致单行代码很长,反而影响阅读。
【规范4】不要使用TAB缩进代替空格缩进。
【规范5】如果单行代码过长,则应该遵循以下规则断行:
♦在逗号的后面。
♦在操作符的前面。
♦断行的起始位置应该对其原行表达式的起始位置,如果无法满足,则缩进2个空格。
【规范6】每一个变量的声明独占一行。
【规范7】将变量的声明置于代码块的开始位置。
【规范8】在java中for、while、do-while循环,if、elseif、else、switch-case分支,try-catch-finally块即使仅包含一个语句,也要用{}包含。
其他语言参照执行。
【规范9】空行的位置:
♦在逻辑代码段之间。
♦for、while、do-while循环,if、elseif、else、switch-case分支,try-catch-finally块的前面。
♦在两个类或接口的定义之间。
♦在两个方法/函数/过程之间。
♦方法/函数/过程内部变量定义行和第一个非变量定义行之间。
♦包含(C++)/引入(Java)完毕之后。
【规范10】空格的位置:
♦在一个关键字和做括号“(”之间。
注意:
不要在方法名和左括号之间加空格。
♦在参数列表的每个逗号“,”之后。
♦一元操作符前后。
注意:
二元操作符前后都不加空格。
例如:
inta=10;a=a+1;a++;
♦for语句的每个表达式之间。
例如:
for(inti=0;i<20;i++)…
♦类型转换语句之后。
例如:
Strings=(String)c;
【建议】空行、空格也是代码。
空行是一个逻辑段起止的标志,它和编程者的思路是一致的。
另外,适当的使用空行和空格可以使你的代码更加清晰。
3代码注释规范
【规范1】代码注释的量应该不少于总代码行数的1/3。
说明:
只有足够的注释才能充分的说明你的代码,没有哪个规范可以规定注释量的上限,但是一般来说1/3应该是下限。
如果你的代码包括注释、空行共90行,那么注释应该不少于30行。
【规范2】在维护代码的同时,维护你的注释。
说明:
我们通常在编写代码的同时都会对代码进行注释,但是往往在维护代码的时候忘记同时维护注释。
所以很多注释在代码反复修改之后,失去了说明代码的作用,这样的注释还不如不写。
【规范3】注释不要重复你的代码。
例如:
Stringstr;//声明一个String对象:
str
上面的代码看上去没有问题,但是注释却是没有用的――只是对代码的简单重复。
要记住,注释是用来说明代码的,而不是重复代码的。
【建议】文件注释。
文件注释用于说明代码文件的一些附加信息,它位于源代码文件的顶部。
文件注释最重要的作用是记录代码维护历史。
例如:
/*
*文件名:
Demo.java
*作者:
SamLee
*完成日期:
2004/02/02
*维护人员:
SamLee
*维护日期:
2004/02/02
*维护原因:
修改了对于图的深度遍历的算法
*当前版本:
1.0
*前继版本:
0.9beta
*/
【规范4】为每一个类编写类注释。
类的注释位于类声明的前面,使用/**/进行注释(对于java,是/***/)。
类的注释应该说明一下几点:
1)完成了哪些工作,即这个类是作什么的。
2)使用的方法和注意事项,如果比较难以表达,那么可以写一些示例代码。
3)作者列表
4)当前版本和完成时间
5)参考类,即这个类与哪些类相关。
注意:
类注释不要写类的实现方法,例如:
“Matrix类采用主选消元法实现矩阵的求逆运算,具体算法是:
…”,这样的注释往往会限制类的扩展,并且加重了类的维护的工作量。
我们来看一个好的类注释:
/**
*TheLong
classwrapsavalueoftheprimitivetype
*long
inanobject.AnobjectoftypeLong
*containsasinglefieldwhosetypeislong
.
*以上是类的作用
*
*
*Inaddition,thisclassprovidesseveralmethodsforconvertinga
*long
toaString
anda
*String
toalong
,aswellasother
*constantsandmethodsusefulwhendealingwithalong
.
*以上是类的使用简介
*@authorLeeBoynton
*@authorArthurvanHoff
*作者列表
*@version1.64,03/21/02
*版本和时间
*/
publicfinalclassLongextendsNumberimplementsComparable{
/**代码省略*/
}
摘自sunJdk1.4源代码,java.lang.Long
【规范5】为每一个方法(函数、过程)编写方法注释。
方法注释位于方法的前面,使用/**/进行注释(对于java,是/***/)。
方法的注释应该说明一下几点:
1)该方法的作用。
2)使用的注意事项(如果需要)。
3)对每一个输入参数进行说明:
作用,取值范围等。
4)对返回值进行说明。
5)对每一个抛出的异常进行说明:
什么情况下出现该异常。
6)方法注释不要写算法。
例如:
/**
*ExecutesthegivenSQLstatement,whichreturnsasingle
*ResultSet
object.
*以上是该方法的作用
*@paramsqlanSQLstatementtobesenttothedatabase,typicallya
*staticSQLSELECT
statement
*以上是参数说明
*@returnaResultSet
objectthatcontainsthedataproduced
*bythegivenquery;nevernull
*以上是返值说明
*@exceptionSQLExceptionifadatabaseaccesserroroccursorthegiven
*SQLstatementproducesanythingotherthanasingleResultSet
object
*以上是异常说明
*/
ResultSetexecuteQuery(Stringsql)throwsSQLException;
摘自sunJdk1.4源代码,java.sql.Statement
【规范6】为每一个属性编写属性注释。
属性是类的状态,应该为每一个属性编写注释:
说明该属性的作用,如果需要,说明其取值范围,以及使用的注意事项。
例如:
/**
*ThesizeoftheArrayList(thenumberofelementsitcontains).
*/
privateintsize;
摘自sunJdk1.4源代码,java.uitl.ArrayList
/**Thevalueisusedforcharacterstorage.*/
privatecharvalue[];
摘自sunJdk1.4源代码,java.lang.String
【规范7】不要编写修饰性的注释。
我们需要的是有用的代码,而不是漂亮的代码。
例如以下的注释是不被推荐的:
/***********************************************************
*ThesizeoftheArrayList(thenumberofelementsitcontains).
***********************************************************/
【规范8】为每一个局部变量编写行末注释。
行末注释的好处是:
具有明显的针对性。
例如:
intlength=0;//thelengthofthearray,initialtozero.
【规范9】在具有复杂算法的代码块前,说明其算法。
例如:
/*
*以下的代码采用二分法对链表进行排序,具体算法是…
*
*/
【规范10】为每一个for、while、do-while循环,if、elseif、else、switch-case分支,try-catch-finally块编写注释。
这样的地方通常体现了代码逻辑。
对于复杂的代码块,可以采用/**/注释,对于简单的代码块,采用行末注释。
【规范11】对于临时代码,编写详细的注释。
临时代码就是目前不使用的,但是也许以后会用到的代码。
对于这样的代码,我们通常使用/**/把它们注释起来:
1)说明注释的原因。
2)说明注释者,和注释时间。
3)说明在什么情况下,可以恢复代码。
4)说明在什么情况下,这些代码需要彻底删除。
5)代码一旦正式发布,必须彻底删除这些注释。
例如:
/*
*有于xxx原因,将以下代码注释。
*注释者:
SamLee,时间2004/03/04
*只有xxx的情况下,才可继续使用下面的代码。
*如果发布之前仍未使用,则删除这些代码
inta=0;
*/
【规范12】尽量使你的注释简单。
例如:
//采用Iterator遍历整个缓冲区,根据对象最后一次使用的时间,删除过期的对象
while(cache.Iterator().hasNext());
//删除缓冲区中过期的对象
while(cache.Iterator().hasNext());
【建议】在编写代码之前,编写你的注释。
编写注释有助于你仔细的思考你的代码。
如果你以前没有这个习惯,请尽量养成它,你会体会到它的好处。
【规范13】对于Java、JavaScript、Object,按照JavaDoc规范编写注释。
请参考【规范4】、【规范5】、【规范6】,这3个规范规定的注释,形成了JavaDoc。
【规范14】对于文档注释(即【规范4】、【规范5】、【规范6】规定的注释),应该只说明“为什么这样做”,而不需要说明“怎样做”。
4命名规范
【规范1】必须慎重的、认真的为你的每一个包、类、方法、变量命名。
说明:
要起一个科学合理的名字,因为名字是理解代码的重要依据。
同时,一旦代码发布,其依赖者、继承者都要永远维持这种命名。
想像一下,如果你和你的同事不得不使用类似tj(统计?
条件?
)这样的名字,而又不能改变现状(会影响其他使用者),那该是一件多么痛苦的事情。
【规范2】遵循技术框架的命名规范。
【规范3】必须采用英文命名。
说明:
英文是全世界软件业通用的交流语言。
【规范4】采用有意义的单词,要求望文知意。
【规范5】可以采用一个单词或多个单词或单词的缩写作为名字,缩写单词的每个字母都要大写。
【规范6】对于难以使用英文的情况,可以参考相关行业标准,比如使用国标。
【规范7】不要使用冠词。
例如:
anUser,thePassword,someEmps,没有必要使用冠词。
但是在命名的时候,要注意名词复数,例如:
users、actions。
【规范8】采用约定俗成的习惯用法。
例如:
getUsername比receiveUsername好,虽然它们表达的意思相同。
常见的习惯用法:
♦循环变量:
i、j、k、m、n
♦临时变量:
tmp、temp
♦数据库:
conn、stmt、pstmt、rs、rowSet
♦长度:
length
♦数量:
count
♦位置:
pos或position
♦下标或索引:
index
♦设置/获取:
set/get
♦布耳变量的命名:
isXXX,例如:
isEmptySet
♦大小:
size
♦工具类所在的包:
util
【规范9】属性、变量、方法参数的命名规范(适用于Java、JavaScript、ObjectC)。
♦首字母小写,其他单词首字母大写。
例如:
userPrivilege
♦采用名词。
例如:
connection(而不是Connect)
♦关于缩写,必须符合【规范3】
【规范10】类、接口命名规范:
♦首字母大写,其他单词首字母大写。
例如:
BufferedStreamReader
♦采用名词。
♦采用单数形式,因为类或者接口代表了“一类”事物,因此通常采用单数形式。
♦关于缩写,必须符合【规范3】
【规范11】包的命名规范:
♦包名所有字母都要小写。
♦顶级包名采用开发者所在机构的域名的逆序。
例如:
org.honqun、org.jboss
♦非顶级包名采用名词,或名词的缩写。
♦如果不在本机构外部发布,可以直接使用项目、产品名称作为顶级包。
【规范12】方法(函数)的命名规范:
♦首字母小写,其他单词首字母大写(java专用)。
例如:
buildXML
♦采用强动词。
例如:
createJSPPage
♦关于缩写,必须符合【规范3】
♦构造方法的名字与类名相同――语法的要求。
【规范13】常量的命名规范:
常量的每一个字母大写,单词之间用下划线分隔。
常量的名字必须涵盖该常量的准确意义。
例如:
privatestaticfinalintMAX_PATH=255;
【规范14】数组的命名规范:
数组应该总是用下面的方式来命名:
byte[]buffer;
而不是:
bytebuffer[];
【规范15】存取器(accesser)方法的命名规范:
♦存取器方法用于获取类的一个属性或设置类的一个属性。
♦存取器后的单词与对应的属性名称相同,但是首字母大写(符合【规范10】)。
存取器方法的参数与对应的属性名称尽量相同。
【规范16】禁止使用“magicvalue”
不可为变量直接赋予非零数字或者表现为数字的字符串,请将这些数值定义为常量,大量的常量可以单独提取为常量类。
不可重复的使用一个字符串,请将经常使用的字符串定义为常量。
以下是使用magicvalue的例子:
IntegerlastIndex=18;//错误!
IntegerfirstIndex=0;//0值是可以使用的。
Stringstate="1";//将"1"定义为常量
Stringname="somename";
Stringdesc="somename";//定义为常量
5异常处理规范
【规范1】如果需要自定义异常(Exception),那么请使用“非可检查”异常,“非可检查”异常不会强制使用者处理异常,极大的简化了代码的复杂程度,提高了代码的可读性。
【规范2】如果所使用的API抛出了“可检查”异常,那么在处理异常的时候可以将多个不同的异常同时处理。
【规范3】尽量使用系统提供的异常。
例如:
如果方法参数验证失败,则抛出thrownewIllegalArgumentException。
【规范4】处理异常,至少做以下工作:
1)输出异常栈。
2)用warning或者error记录日志。
3)如果需要,重新抛出异常,抛出的异常必须是一个“非可检查”异常。
例如:
catch(Exceptione){
e.printStackTrace();
logger.error(e.getMessage());
thrownewApplicationException(e);
}
【规范5】不要用异常代替逻辑。
“异常”代表了不可预测的情况,而逻辑一定是可以预测的,因此,不要用异常代替逻辑。
简单的说,在catch代码中只能有处理异常的代码,不能加入逻辑代码。
6其他规范
【规范1】禁止拷贝粘贴代码。
当你Copy-Paste代码的时候,说明代码中存在重复,重复的代码往往导致代码难以维护和阅读。
一旦那些保存在剪切板中的代码中存在错误,编写者甚至不知道到哪里修改这些错误。
每当你Copy-Paste代码的时候,请停下来,考虑将这些代码提取为方法、类或者组件。
【规范2】对于暂时无法实现的代码,使用//TODO:
进行注释。
下面的代码,用于处理日期类型,但是,在可以预期的需求中,还要处理时间类型:
if(StringUtils.equalsIgnoreCase(field.getDataType(),AnyDataModelConstants.DATA_TYPE_DATE)){//TODO:
转换日期类型(目前不支持时间类型)
row.put(key,newDateTime((Date)value).toString(Constants.DATE_PATTERN));
}
【规范3】禁止使用FIXME注释,与其将BUG留给别人处理,不如现在就解决它。
【规范4】对于不被推荐使用的API方法,如果为了兼容性不能删除这个方法,那么请用文档注释和注解进行标注,并说明不推荐使用的原因和替换方案,以及在哪个版本中删除这个方法。
/**
@deprecatedOnlyreturnthelengthoftheindentstring.
@see{@link#taskUnassigned}*/
@Deprecated
TaskQuerytaskUnnassigned();