Java项目组开发规范33页.docx
《Java项目组开发规范33页.docx》由会员分享,可在线阅读,更多相关《Java项目组开发规范33页.docx(18页珍藏版)》请在冰豆网上搜索。
Java项目组开发规范33页
概述
一.1编写目的
为规范FSOP项目的开发实施工作,特制定本规范。
为了提高软件开发质量,降低开发周期,增强代码的可重用性和易读性,使软件便于维护,开发人员间便于交流和协作,特总结出开发规范,以为参考。
一.2面向读者
从事FSOP项目的开发、实施工作的相关人员。
一.3名词解释
本节对手册中涉及到的术语进行简单描述。
程序结构
一.4包结构
项目中的所有代码,必须符合如下的结构:
1、各子系统的模块:
com.icss.fsop.{subsys}.{module}.servlet.[xxServlet]
com.icss.fsop.{subsys}mon.util.[xxUtil]
com.icss.fsop.{subsys}mon.hander.[xxHander]
com.icss.fsop.{subsys}mon.sql.[xxSql]
com.icss.fsop.{subsys}mon.entity.[xxxx]
其中subsys是子系统的名称,module是模块的名称,xxServlet和xxHandler是模块下面的Servlet和Handler,允许有多个Servlet和Handler同时存在,建议同一个模块下,用多套Servlet和Handler处理不同的业务对象;util存放该模块专用的类;package/class可以任意级别的包或者类;
2、子系统之外的模块:
com.icss.fsop.sm.{module}.servlet.[xxServlet]
com.icss.fsop.smmon.util.[xxUtil]
com.icss.fsop.smmon.hander.[xxHander]
com.icss.fsop.smmon.sql.[xxSql]
com.icss.fsop.smmon.entity.[xxxx]
其中sm是systemmanage的简写,其他同上;
3、公共的类:
com.icss.fsopmon.[package/class]
含义同上。
一.5相关类
1、对于Servlet,必须继承ServletBase,必须在Servlet中处理与request和response相关的操作,一般是取参数和设置属性等操作;
2、对于Handler,必须继承HandlerBase,该类的方法中,不能用request和response作为参数,更不能用Servlet作为参数;
3、程序中使用到的SQL,一律在XXXSQLBuilder中进行拼写,该类属于util包,需要继承SQLBuilderBase,其构造函数为私有类型,并且要实现静态方法getSQLBuilder(conn),根据不用的数据库类型,返回不同的实例。
JAVA规范
一.6核心原则
1.软件工程化
2.面向对象
3.能简单不复杂
4.强调团队协作
一.7命名规范
程序内的所有标识符(包括包名、类名、接口名、方法名、变量名)都应由字母、数字和下划线组成,并以字母开头;统一采用英文命名,用词应当准确,禁止使用中英文混合的方式命名,如果可能的话,尽量使用有意义的英文单词或多个单词的缩写命名(缩写应该是被广泛使用的缩写),做到见名知意;标识符的长度应当符合“min-length && max-information”原则;程序中不要出现仅靠大小写区分的相似的标识符;在使用英文字母起标识作用时要注意,尽量不使用“O”,“Z”,“I”等单个字符,以避免与数字“0”,“2”,“1”混淆。
一.7.1包、类和接口
1、所有包名全部小写,只能使用英文字母,不得使用数字和其他符号;
2、类名使用有意义的英文单词或单词的组合,每个单词的首字母大写,如果是实现接口的类,可酌情使用Imp结尾,英文单词一般为名词。
3、接口名使用有意义的名词和形容词的组合,每个单词的首字母大写,名称前不需要添加前缀“I”,英文字母i的大写。
一.7.2方法
方法命名使用动词或“动词+名词”的组合,名称的首字母小写,名称中其他词的首字母大写。
对于取值的方法(gettermethod),加“get”作前缀;对于设置的方法(settermethod),加“set”作前缀;对于布尔型的方法(booleanmethod),加“is”作前缀;用正确的反义词组命名具有互斥意义或相反动作的函数,例如getValue(),setValue()。
一.7.3变量
变量命名使用名词或名词“形容词+名词”的组合,名称的首字母小写,名称中其他词的首字母大写。
尽量避免单个字符的变量名,除非是一次性的临时变量。
临时变量通常被取名为i,j,k,m和n,它们一般用于整型;c,d,e,它们一般用于字符型。
用正确的反义词组命名具有互斥意义的变量,例如:
intminValue和intmaxValue。
尽量避免名字中出现数字编号,如Value1,Value2等,除非逻辑上的确需要编号。
命名应尽量使用匈牙利命名法,成员变量用长名字,参数和局部变量用短名字,一般由小写字母开头的单词组合而成。
类成员变量前一般应加上m_,静态变量应加上s_,紧接着是变量的类型(只限于JDK内置类型)。
临时变量应参照如下类似的格式书写,如ltmp,tmpStr,tempStr等。
例如:
m_nTotalNum,m_strPath,s_bRcving
类型
前缀
整型
n,i
长整型
l
无符号整型
u
字符
ch
布尔量
b
浮点数
f
双精度浮点
d
字符串
str,sz
一.7.4常量
常量(staticfinal变量)名字的每个字母都大写,并且指出完整含义,词与词之间用下划线分隔。
一.8代码结构
代码组织要清晰,严格控制函数的长度和每行代码的长度,{,},(,),if,else,do,while,for,case等要对应整齐,缩进全部用Tab键(4个空格)。
变量的定义要集中,函数间要有空行分开,一个程序中的空行数目最好占8%-16%。
多态函数和功能相近的函数集中放在一起。
代码应该简洁、清楚并讲述了所发生的一切,我们的目标应该是写出最清晰的代码,而不是最巧妙的代码。
有些不易理解的变量或函数应作注释,难懂的代码要有注解,在文件的开始处有该文件的用途描述。
一定要保持注释的一致性。
代码的重用要仔细,删掉从来没有用过的函数或变量,大篇幅注释掉的代码行也应删除,以免使程序混乱难读。
工程中不起作用的文件或类应删除,工程目录下的非工程文件也应该移走,保持工程的清洁,避免混淆难于管理。
一.8.1缩进
代码缩进是指通过在每行代码前键入空格或制表符的方式,表示每行代码之间的层次关系。
任何编程语言都需要代码缩进规范程序的结构,采用代码缩进的编程风格有利于代码的阅读和理解。
在本项目的开发中,统一采用TAB(4个空格)进行代码缩进。
在遇到有关类、结构、函数或过程、以及枚举等等复杂程序结构的定义的时候,我们通常需要将它的内容缩进一层。
在C/C++/C#/Java语言中,大括号是一个非常明显的标志,凡是遇到大括号,都应该直接联想到缩进。
一.8.2行宽
当一条语句太长而超出一定的宽度时,应该折行书写,尽量避免一行的长度超过80个字符。
一.8.3换行
需要折行时,从第二行起到该语句结束之间的各行应该缩进一层,至下一条语句时再恢复原来的缩进位置。
这一点我相信大家都能理解并愿意遵循,然而问题的焦点并不在于要不要换行,而在于在什么位置换行。
当一个表达式不能在一行内写完,参照下面的标准换行:
逗号后换行,操作符后换行,,换行时保证代码意义的连贯性。
在换行时,我们通常在一个变量或者常量之前换行,把逗号之类的分隔符、运算符留在前一行的行尾。
函数调用时,如果参数个数很多,或者要传递的表达式写起来很长,那么也会涉及到长语句换行问题;在一些必要的情况下,我们为了清晰地列出函数的每一个参数,可以每行只书写一个参数,原则是:
尽可能地在参数与参数之间换行,并将逗号保留在上一行行末。
下面是经常使用的一些换行的示例代码:
代码示例1:
由于代码过长而进行断行
bitmap=newBitmap(size.Width,size.Height,
System.Drawing.Imaging.PixelFormat.Format32bppArgb);
代码示例2:
对于一个超长表达式,我们可以在某两个表达式项之间断开:
if(f==ImageFormat.Jpeg.Guid||
f==ImageFormat.Tiff.Guid||
f==ImageFormat.Png.Guid||
f==ImageFormat.Exif.Guid)
supportsPropertyItems=true;
else
supportsPropertyItems=false;
原本一个很长的条件表达式,通过在“||”运算符处换行,显得更加地清晰。
有一点需要我们注意的是,当我们进行折行时,要将折行位置处的分隔符(如前一例中的逗号,这一例中的“||”运算符等)留在上一行的行末,给人以“此行并未结束”的直观印象。
代码示例13:
寻找最佳的断行位置
doublecontainerAspectRatio=
(double)container.ClientWidth/container.ClientHeight;
如此一来,这个除法算术表达式就显得较为完整,相比前一种写法而言更能体现其内在的逻辑关系。
通常我们会选择整个表达式中最高的关系层次进行断行,例如上述代码中的“赋值号”和“除号”都是可以考虑的断行点,但相比较而言,除号连接的这个算术表达式只是整个赋值表达式的右半部分,如果在除号处断行,那么不但整个表达式会被截断,连局部的这个除法表达式也会被截断;反之,我们选择在赋值号处换行,可以保持除法表达式的完整,最大限度地减少换行对语句整体结构的破坏,能够更加清楚地表达出原来的逻辑。
代码示例14:
将函数调用中的每一个参数都分行书写
RectangleimageBounds=newRectangle(
itemBounds.X+padding,
itemBounds.Y+padding,
itemBounds.Width-padding*2,
itemBounds.Height-padding*2
当参数数量较多,参数较长或者包含表达式的时候,这种排版比起单独写成一行更为直观醒目。
一.8.4长度
每个函数主要逻辑语句的长度以30个自然行以下为宜,建议不要超过50行,如果超过80行就应该重新组织。
如果{}单独成行,则其所在的行不在计算的范围内,catch/finally语句块中的语句不计算在内。
一.8.5括号
在大括号语法中,缩进时大括号的写法有不同的几种,个人认为,前面所用的那种左右括号单独一行的写法最为清晰,因为可以最好地反映出括号的配对情况。
具体使用何种方式并不重要,重要的是,要保持方式风格的统一,不能在同一个项目中出现不同的风格。
风格1看起来紧凑些,可以减少代码的行数,但是在其他代码存在换行的情况下,不容易发现配对的括号,必须要借助IDE提供的功能才可以,建议使用风格2,这样的代码看起来更清晰一些,这点比较重要;
//风格1
if(condition){
doSomethingIf();
}else{
doSomethingElse();
}
//风格2
if(condition)
{
doSomethingIf();
}
else
{
doSomethingElse();
}
一.8.6注释
注释是用来解释程序做什么(What),为什么这样做(Why),以及要特别注意的地方的,而不是注释程序是怎么工作的(How),你的程序本身就应该能说明这一问题,如果程序的逻辑过于复杂,添加一些注释也是有必要的。
例如:
下面的注释是必须的:
//gothruthearray,notethelastelementisat[len-1]
for(i=0;i{
DoSomeThing();
}
下面的注释是多余的
//thisloopstartstheifrom0tolen,ineachstep,it
//doesSomeThing
for(i=0;i{
DoSomeThing();
}
Java程序有两类注释:
实现注释(implementationcomments)和文档注释(documentcomments)。
实现注释使用/*...*/和//界定的注释。
文档注释是Java独有的,并由/**...*/界定。
切记,注释要随着程序的修改而不断更新,一个误导的(Misleading)注释往往比没有注释更糟糕。
另外,注释(包括所有源代码)建议只用ASCII字符,不要用中文或其他特殊字符,它们会极大地影响程序的可移植性。
一.8.6.1单行注释
短注释可以显示在一行内,并与其后的代码具有一样的缩进层级。
如果一个注释不能在一行内写完,就该采用多行注释(参见"多行注释")。
单行注释之前应该有一个空行。
例如:
if(condition){
/*Handlethecondition.*/
...
}
或者
if(condition){
//Handlethecondition.
...
}
一.8.6.2多行注释
多行注释通常用于提供对方法,数据结构和算法的描述。
多行注释常被置于每个类和方法开始处,或者用于需要对某一实现细节做详细说明时。
例如:
/*
*Hereisablockcomment.
*/
一.8.6.3行末注释
极短的注释与它们所要描述的代码位于同一行,注释界定符是"//"或者/**/,可以注释掉整行或者一行中的一部分。
例如:
if(a==2)
{
returntrue;//specialcase
}
else
{
returnfalse;/*specialcase*/
}
一.8.6.4文档注释
文档注释描述Java的类、接口、构造器,方法,以及字段(field)。
每个文档注释都会被置于注释定界符/**...*/之中,一个注释对应一个类、接口或成员。
该注释应位于声明之前,文档注释的第一行(/**)不需缩进,随后的文档注释每行都缩进1格(使星号纵向对齐)。
例如:
/**
*TheExampleclassprovides...
*/
publicclassExample
{
/**
*thefielddescription...
*/
privateintiCount=0;
/**
*themethoddescription...
*@param
*@return
*@throws
*/
publicvoiddoSomething()
{
}
}
若你想给出有关类、接口、变量或方法的信息,而这些信息又不适合写在文档中,则可使用实现块注释或紧跟在声明后面的单行注释。
例如,有关一个类实现的细节,应放入紧跟在类声明后面的实现块注释中,而不是放在文档注释中。
文档注释不能放在一个语句块内使用。
一.8.7声明
变量的声明:
推荐一行声明一个变量,因为这样以利于写注释;尽量在声明变量的同时进行初始化,唯一不这么做的理由是变量的初始值依赖于某些先前发生的计算;避免声明的局部变量覆盖上一级声明的变量。
例如,不要在内部代码块中声明相同的变量名;只在代码块的开始处声明变量,不要在首次用到该变量时才声明。
定义类的成员变量时,总的定义顺序是先定义静态变量后定义实例变量,在每种类型的变量中,变量顺序依次为:
公共(public)变量,受保护(protected)变量,私有(private)变量。
一.8.8语句
if、for、do、while、case、switch、default等语句自占一行,且if、for、do、while等语句的执行语句部分无论多少都要加括号{}。
尽量减少嵌套语句的层数,最好不好超过4层,如果多于4层,则应该对函数进行重构。
一.8.8.1if-else
只有if的语句:
if(condition)
//dosomething
含有else的语句:
if(condition)
//dosomething
else
//dosomething
含有else-if的语句:
if(condition)
//dosomething
elseif(condition2)
//dosomething
一.8.8.2for语句
一个for语句应该具有如下格式:
for(initialization;condition;update)
statements;
一个空的for语句(所有工作都在初始化,条件判断,更新子句中完成)应该具有如下格式:
for(initialization;condition;update){}
当在for语句的初始化或更新子句中使用逗号时,避免因使用三个以上变量,而导致复杂度提高。
若需要,可以在for循环之前(为初始化子句)或for循环末尾(为更新子句)使用单独的语句。
一.8.8.3while语句
一个while语句应该具有如下格式
while(condition)
statements;
一个空的while语句应该具有如下格式:
while(condition){}
一.8.8.4do-while语句
一个do-while语句应该具有如下格式:
do
statements;
}while(condition);
一.8.8.5switch语句
对于有多个分支的代码,每个分支一行,且必须包含默认(default)分支。
一个switch语句应该具有如下格式:
switch(condition)
caseABC:
statements;
break;
caseXYZ:
statements;
break;
default:
statements;
break;
一.8.8.6try语句
一个try-catch语句应该具有如下格式:
try
statements;
catch(ExceptionClasse)
statements;
finally
statements;
其中finally语句块是可选的。
一.8.8.7空语句
空行将逻辑相关的代码段分隔开,以提高可读性。
下列情况应该总是使用两个空行:
1、多个类(接口)声明之间
下列情况应该总是使用一个空行:
1、两个方法之间
2、语句块内的局部变量和方法的第一条语句之间
3、注释之前
4、一个方法内的两个逻辑段之间
一.8.8.8空格
下列情况应该使用空格:
1、一个紧跟着括号的关键字应该被空格分开,例如:
while(true)
2、空白应该位于参数列表中逗号的后面;
obj.doSomething(arg1,arg2,arg3);
3、所有的二元运算符,除了".",应该使用空格将之与操作数分开。
一元操作符和操作数之间不因该加空格,比如:
负号("-")、自增("++")和自减("--")。
例如:
a+=c+d;
a=(a+b)/(c*d);
n++;
printSize("sizeis"+foo+"\n");
4、for语句中的表达式应该被空格分开,例如:
for(expr1;expr2;expr3)
5、强制转型后应该跟一个空格,例如:
myMethod((byte)aNum,(Object)x);
myMethod((int)(cp+5),((int)(i+3))+1);
一.9异常处理
系统中捕获的异常,在无法采取补救措施或补救措施失败后,一律不允许单独处理异常,全部要向上级代码抛出,由系统统一处理。
系统提供了通用的异常封装类BaseException和在代码中程序员需把捕获到的具体异常和相应的异常描述代码一同封装入BaseException中,“向外”抛出,最终由系统统一处理。
当在业务层代码(handler)中有异常发生时,需在异常try/catch的catch块中创建BaseException,将捕获到的具体异常封装入BaseException,并将BaseException向外抛出至servlet中,交由上级代码统一处理,并记录详细的日志信息。
例如:
try{
}catch(IOExceptione){
log.error("系统发生异常:
无法进行XXX操作",e);
throw(newBaseException(IErrorCode.IO_Exception,e));
当在逻辑控制层代码(servlet)中有异常发生,或有异常被抛出至servlet中时,不允许在servlet中出现try/catch块对产生的异常进行处理。
servlet中的方法一律将异常“向外”抛出,由系统级代码统一处理。
例如:
protectedvoidperformTask()throwsNumberFormatException{
一.10其他规范
1、限制外部包的使用
如果需要使用一个外部包需要听取项目经理的意见。
在项目经理批准以前,严禁擅自使用一个外部的包;
2、对于只有一行的方法体,可以和方法声明写在一行上;
3、在类内部尽量不要定义main方法,请使用TestMain运行待测试的类,如果已经定义了,那么它应该写在类的底部;
4、程序中用到的资源,比如文件流、数据库连接等,要遵循哪里获取哪里释放的原则;
5、PrintStream已经被不赞成(deprecated)使用,用PrintWrite来代替她。
JSP规范
一.11JSP文件名命名规则
以功能名称+操作名称作为JSP文件名称,例如用户管理的用户维护的功能名称为USER_MANAGE_MAINTAIN,当前操作名称为增加,则该JSP的名称为userManageMaintainAdd.jsp
操作名称一览表:
操作名称
代码
增加
Add
修改
Modify
明细
Detail
删除
Delete
查询
Search
审核操作
Audit
列表
List
一.12JSP头格式
JSP头部一般需要遵循以下格式:
<%@pagelanguage="java"pageEncoding="GBK"%>
<%@pageimport="java.util.*"%>
<%@pageimport="java.io.File"%>//jdk标准包
<%@pageimport="javax.mail.Transport"%>//java扩展包
<%@pageimport="org.apache.xml.serialize"%>//使用的