所有的程序开发手册都包含了各种规则。一些习惯自由程序人员可能对这些规则很不适应,但是在多个开发人员共同写作的情况下,这些规则是必需的。这不仅仅是为了开发效率来考虑,而且也是为了后期维护考虑。
定义这个规范的目的是让项目中所有的文档都看起来像一个人写的,增加可读性,减少项目组中因为换人而带来的损失。
这是一个强制执行的标准,而不是一个指南。当我们的标准不适应的时候,我们可以讨论、修改标准。但是已经制定的标准一定要得到执行。
当你违背标准时,将其注释出来。如果违背了,你必须说明为什么你要违背这个标准,违背这个标准可能产生的影响,以及标准被应用于这个场合之前可能/必须出现的任何条件。
随着此标准发下的还有一份指南,是rational公司推荐的编程指南。希望大家认真学习,你将受益匪浅。
1. 命名规范
? 一般命名约定
除以下特别规定之外,所有名称遵从本规定。
使用可以准确说明变量/字段/类的完整的英文描述符,并且尽可能采用相关领域内已有的术语。采用大小写混合,提高名字的可读性。一般应该采用小写字母,但是下面规定名称的首字母,以及任何中间单词的首字母应该大写。不要使用相似或者仅在大小写上有区别的名字,也不要使用下划线作为名字的首末字母。
? package 的命名
package 的名字应该都是由一个小写单词组成。
? class/interface 的命名
class与interface的名字必须由大写字母开头。后面的单词也用大写字母开头。
? 普通成员的命名
变量的名字必须用一个小写字母开头。后面的单词用大写字母开头。
? static final 变量的命名
static final 变量的名字应该都大写,并且指出完整含义。
? 数组的命名
数组应该总是用下面的方式来命名:
byte[] buffer;
而不是:
byte buffer[];
2. 文件样式
所有的 ) 文件都必须遵守如下的样式规则
? 版权信息
版权信息必须在 文件的开头,比如:
/**
* copyright ? 2000 shanghai xxx co. ltd.
* all right reserved.
*/
? 其他不需要出现在 doc 的信息也可以包含在这里。
? package/imports
package 行要在 import 行之前,import 中标准的包名要在本地的包名之前,而且按照字母顺序排列。
? class/interface
接下来的是类的注释,一般是用来解释类的。
/**
* a class representing a set of packet and byte counters
* it is observable to allow it to be watched, but only
* reports changes when the current set is complete
*/
? 接下来是类定义,extends和implements要放在不同的行上。
public class counterset
extends observable
implements cloneable
? 构造函数
接下来是构造函数,它应该用递增的方式写(比如:参数多的写在后面)。
访问类型 ("public", "private" 等.) 和 任何 "static", "final" 或 "synchronized" 应该在一行中,方法名和参数另写一行,这样可以使方法和参数更易读。
public
counterset(int size){
this.size = size;
}
? finalize()
如果需要的话,接下来定义finalize()。这是在一个对象从内存里删除之前的“垃圾收集”过程中被自动调用的成员函数。注意程序员是不能控制何时调用此函数的,甚至你都不能肯定此函数会被调用,所以,只有在必要的时候定义这个函数,要慎重使用此函数。
? 克隆方法
如果这个类是可以被克隆的,那么下一步就是 clone 方法:
public
object clone() {
try {
counterset obj = (counterset)super.clone();
obj.packets = (int[])packets.clone();
obj.size = size;
return obj;
}catch(clonenotsupportedexception e) {
throw new internalerror("unexpected clonenotsupportedexception: " + e.getmessage());
}
}
? 类方法
下面开始写类的方法,请按照public, protected, private的顺序排列类方法:
/**
* set the packet counters
* (such as when restoring from a database)
*/
protected final
void setarray(int[] r1, int[] r2, int[] r3, int[] r4)
throws illegalargumentexception
{
//
// ensure the arrays are of equal size
//
if (r1.length != r2.length || r1.length != r3.length || r1.length != r4.length)
throw new illegalargumentexception("arrays must be of the same size");
system.arraycopy(r1, 0, r3, 0, r1.length);
system.arraycopy(r2, 0, r4, 0, r1.length);
}
public和protected方法必须有doc文档。
? 存取方法
类变量的存取的方法书写在其它方法的后面。注意,所以私有的方法要排列在最后(包括公有存取方法的后面)。如果存取方法只是简单的用来将类的变量赋值获取值的话,可以简单的写在一行上:
/**
* get the counters
* @return an array containing the statistical data. this array has been
* freshly allocated and can be modified by the caller.
*/
public int[] getpackets() { return copyarray(packets, offset); }
public int[] getbytes() { return copyarray(bytes, offset); }
public int[] getpackets() { return packets; }
public void setpackets(int[] packets) { this.packets = packets; }
注意其它的方法不要写在一行上。
? 成员变量
接下来是类的成员变量:
/**
* packet counters
*/
protected int[] packets;
? 强烈建议不要定义公有(public)的成员变量,请代之以存取方法。注意public和protected的成员变量必须生成文档(ckage 定义的成员变量如果名字含义明确的话,可以没有注释。
? main 方法
如果定义了main(string[]) 方法, 那么应该把它写在类的底部。
3. 代码编写格式
? 文档化
必须用 doc 来为类生成文档。不仅因为它是标准,这也是被各种 编译器都认可的方法。
? 缩进
如果使用空格缩进的话,缩进应该是每行4个空格。如果在源文件中保存tab字符的话,所有的缩进都应该使用tab字符。不能混合使用空格与tab字符,因为使用不同的源代码管理工具时tab字符将因为用户设置的不同而扩展为不同的宽度。
? 页宽
页宽应该设置为80字符,源代码一般不要超过这个宽度。超长的语句应该在一个逗号或者一个操作符后折行。一条语句折行后,应该比原来的语句再增加一个缩进。
? {}对
如果{}中的语句非常短,{和}可以(和其中的语句)写在一行上。否则,}应该单独在一行上,并且缩进到与相应的{那一行对齐的位置上。
if (i>0) { i ++; }
if (i>0){
i ++ ;
}
? 括号
左括号和后一个字符之间、右括号和前一个字符之间,不应该出现多于一个的空格。不要在语句中使用无意义的括号
4. 程序编写规范
? exit()
永远不要调用exit()。因为这样做不给任何代码代码机会来截获退出。一个类似后台服务地程序不应该因为某一个库模块决定了要退出就退出。
在n中绝对禁止调用exit()。
? 异常
在n或者jsp中,不要试图截获任何实际上并不处理的异常。仅仅是一个e.printstacktrace(); 语句这样的处理没有任何意义。如果需要的话,使用一个finally子句就可以保证某些操作在任何情况下都得到执行。
? final 类
绝对不要因为性能的原因将类定义为 final 的(除非程序的框架要求)
如果一个类还没有准备好被继承,最好在类文档中注明,而不要将她定义为 final 的。这是因为没有人可以保证会不会由于什么原因需要继承她。
? 访问类的成员变量
大部分的类成员变量应该定义为 protected或者private 的来防止随意使用他们。提倡使用存取成员函数,可能的话,不要定义任何public的成员变量。
? jsp
jsp中应该只保留跟表现(显示)直接相关的代码。一切包含程序逻辑、对资源(比如数据库)进行访问的代码,都应该在n中实现。
jsp中的代码应该集中在文件的头部,只有显示输出内容可以嵌入。鼓励使用getproperty和setproperty进行操作,可以简化对null值得处理。
? ns
对servlet/jsp中参数的获取应该写成专门的存取成员函数(setxxx/getxxx),对字符集的转换应该在存取函数中完成。这样在各个功能中可以共用这些部分。
? sql
在所有可能的情况下,应该使用preparedstatement和动态sql,即用?符号代表参数,通过preparedstatement的setxxx(如setint, setstring等)方法设置参数,然后执行sql语句。
不要养成在每次语句执行前根据参数拼sql语句的习惯。
? 类(功能)和程序文件的对应关系
开发jsp过程中可能涉及很多类,在jsp页面中除了要说明这个页面完成的功能之外,还要说明用到的类名称以及类存放的位置、所在文件名等信息,在说明中应着重指出该 jsp使用了类的哪些成员函数。例如:
-- 该jsp程序的功能- ->
—作者的名称,日期,修改记录-- >
? 类的组织方式
鉴于在编译过程中会将所有的类分别编译成独立的class,所以在编写类的过程中尽量将完成一个完整功能的类放在一个文件中,该文件中不要包含完成其它功能的类,这些类可以用package组装和安排。
? 变量的定义和初始化
在程序设计过程中不可避免要定义多个变量并初始化,原则上要求将所有的变量放在一起定义并初始化,虽然对于静态变量系统赋予变量默认值,但为了清晰起见,请大家将初始化代码写在程序中。变量命名的规则见上面的叙述。
? 合成和继承的合理使用
程序中强调继承,但并不表示程序设计中处处用继承,合成和继承作为重新生成类的两个方法,请大家在具体使用之前要慎重。为判断自己到底应当使用哪种方法生成新的类,一个较好的方法是考虑是否需要从新类上溯造型回基础类。若必须上溯,就需要继承;否则,就要慎重考虑,防止自己对继承的滥用。
? 程序的修改和功能变更
程序开发过程中会不断对程序进行修改,对于那些由于功能的改变而引起的修改,在程序文件的头部要以文档的形式记录下来;如果是为了调试bug而进行的程序调整可以不记录在文件中。程序中比较复杂的算法要做出详细的解释。
5. 性能
? 在写代码的时候,从头至尾都应该考虑性能问题。这不是说时间都应该浪费在优化代码上,而是我们时刻应该提醒自己要注意代码的效率。比如:如果没有时间来实现一个高效的算法,那么我们应该在文档中记录下来,以便在以后有空的时候再来实现她。
? 不必要的对象构造,构造对象的代价是很高的
o 不要在循环中构造和释放对象
o 不要构造没有用的对象
如下面例子中,第一行构造的vector对象,根本没有使用,在第二行中就释放掉了。
vector newvector=new vector();
newvector=string2vector.run(str);
o
o 使用 stringbuffer 对象
在处理 string 的时候要尽量使用 stringbuffer 类,stringbuffer 类是构成 string 类的基础。string 类将 stringbuffer 类封装了起来,(以花费更多时间为代价)为开发人员提供了一个安全的接口。当我们在构造字符串的时候,我们应该用 stringbuffer 来实现大部分的工作,当工作完成后将 stringbuffer 对象再转换为需要的 string 对象。比如:如果有一个字符串必须不断地在其后添加许多字符来完成构造,那么我们应该使用 stringbuffer 对象和她的 append() 方法。如果我们用 string 对象代替 stringbuffer 对象的话,会花费许多不必要的创建和释放对象的 cpu 时间。
? 避免不必要的使用 synchronized 关键字
避免的使用关键字 synchronized,应该在必要的时候再使用她,这是一个避免死锁的好方法。