开发规范的重要性
定义规范的目的是让项目中所有的文档都看起来像一个人写的,增加可读性,减少出现错误的几率。
减少维护成本;
一个软件的生命周期中,80%的花费在于维护,另一方面,几乎没有任何一个软件,在其整个生命周期中,均由最初的开发人员来维护,规范的编码减少人员变动带来的维护成本。
改善软件的可读性
可以让程序员尽快而彻底地理解新的代码。
程序的坏味道
1.在循环中对字符串操作时用String
在处理String 的时候要尽量使用 StringBuffer 类,StringBuffer 类是构成 String 类的基础。String 类将 StringBuffer 类封装了起来,(以花费更多时间为代价)为开发人员提供了一个安全的接口。当我们在构造字符串的时候,我们应该用 StringBuffer 来实现大部分的工作,当工作完成后将 StringBuffer 对象再转换为需要的 String 对象 。比如:如果有一个字符串必须不断地在其后添加许多字符来完成构造,那么我们应该使用 StringBuffer 对象和她的 append() 方法。如果我们用 String 对象代替StringBuffer对象的话,会花费许多不必要的创建和释放对象的 CPU 时间。
String sentence = "";
for( int i = 0; i < wordArray.length; i++ ) {
sentence += wordArray[ i ];
}
用StringBuffer.append()优化,优化后为:
StringBuffer buffer = new StringBuffer( 500 );
for( int i = 0; i < wordArray.length; i++ ) {
buffer.append( wordArray[ i ] );
}
String sentence = buffer.toString( );
2.考虑Windows与Unix平台的互移植性
换行符
System.out.print("Hello,world!\n");
优化后:
System.out.println("Hello,world!");
或者你构造一个带换行符的字符串:
String newline = System.getProperty("line.separator");
System.out.println("Hello world" + newline);
路径分隔符
在UNIX和Windows环境下,会采用不同的路径分隔符,如Windows中用”\”,而UNIX下一般采用”/”,因此为了保证系统的可移植性,需要分别进行处理。
String file_path = dir + “/” + file_name;
优化后:
String file_path = dir + File.separator + file_name;
3.滥用synchronized 关键字
Synchronized关键字是避免死锁的好方法,但同时会极大地降低性能,避免不必要的使用关键字 synchronized,应该在必要的时候再使用它。
public class LazySingleton { private static LazySingleton m_instance = null ; private LazySingleton(){}; synchronized public static LazySingleton getInstance(){ if(m_instance==null) m_instance=new LazySingleton(); return m_instance; } }
4.在循环中构造和释放对象
for (int i = 0; i < 10000; ++i) {
Object obj = new Object();
System.out.println("obj= " + obj);
}
上面的做法会浪费较大的内存空间。正确的做法如下所示:
优化后:
Object obj = null;
for (int i = 0; i < 10000; ++i) {
obj = new Object();
System.out.println("obj= "+ obj);
}
采用上面的第二种编写方式,仅在内存中保存一份对该对象的引用,而不像上面的第一种编写方式中代码会在内存中产生大量的对象引用,浪费大量的内存空间,而且增大了垃圾回收的负荷。因此在循环体中声明创建对象的编写方式应该尽量避免
5.对文件或者数据库的操作不及时关闭
FileOutputStream fos = new FileOutputStream(projectFile);
project.save(fos, “IDE Project File”);
FileOutputStream fos = new FileOutputStream(projectFile);
project.save(fos, “IDE Project File”);
fos.close();
6.对变量的重复计算
例如:
for(int i=0;i<list.size();i++)
应该改为
for(int i=0,len=list.size();i<len;i++)
并且在循环中应该避免使用复杂的表达式,在循环中,循环条件会被反复计算,如果不使用复
杂表达式,而使循环条件值不变的话,程序将会运行的更快。
7.一个方法的代码过长,超过1000行
应将方法设计成简要的、功能性单元,用它描述和实现一个不连续的类接口部分。理想情况下,方法应简明扼要。若长度很大,可考虑通过某种方式将其分割成较短的几个方法,这样做也便于类内代码的重复使用。
使类尽可能短小精悍,而且只解决一个特定的问题。下面是对类设计的一些建议:
■一个复杂的开关语句:考虑采用"多形"机制
■数量众多的方法涉及到类型差别极大的操作:考虑用几个类来分别实现
■许多成员变量在特征上有很大的差别:考虑使用几个类
8.不写注释,或者注释不清晰
命名不规范
排版格式混乱,不注意缩进与对齐等
9.滥用public公共类定义
让一切东西都尽可能地"私有"--private。可使库的某一部分"公共化"(一个方法、类或者一个字段等等),就永远不能把它拿出。若强行拿出,就可能破坏其他人现有的代码,使他们不得不重新编写和设计。若只公布自己必须公布的,就可放心大胆地改变其他任何东西。在多线程环境中,隐私是特别重要的一个因素--只有private字段才能在非同步使用的情况下受到保护。
10.在程序中使用硬编码
硬编码:
指的是在软件实现上,把输出或输入的相关参数(例如:路径、输出的形式或格式)直接以常量的方
式书写在源代码中,而非在运行时期由外界指定的设置、资源、数据或格式做出适当回应。一般被认
定是种反模式或不完美的实现,因为软件受到输入数据或输出的格式改变就必需修改源代码,对客户
而言,改变源代码之外的小设置也许还比较容易。
11.出现http 404或http 500错误
12.在JSP页面中使用JDBC API,直接写SQL语句以及业务逻辑代码
13.在程序代码中存在垃圾数据文件(例如.bak,keep, cvs文件夹等)
14.变量只有在用到它的时候才定义和实例化。
这是初学者最容易犯的错,合理的使用变量,并且只有在用到它的时候才定义和实例化,能有效的避免内存空间和执行性能上的浪费,从而提高了代码的效率。
例如:
void f(){ int i;
A a = new A();
if(…){
a.showMessage();
}
}
应该改成:
void f(){ int i;
A a = null;
if(…){
//用到时才实例化
a = new A();
a.showMessage();
}
}
15.所有调试信息直接System.out.print打印到控制台
Logger日志工具类
JS中debugger,以及console.log
16.对数组为空、数组越界、页面传递的参数为空等异常情况不做任何处理
for (Map.Entry<String,List<OfflineReportDTO>> entry : allResult.entrySet()) {
offlineCashe = entry.getValue();
String time_cashe = "";//定义临时时间
String way_cashe = ""; //定义临时的登陆方式,记录前一天最后一次的登陆方式
String TimeBegin = timeFormat + TIME_ZERO;//每日初始时间
String TimeEnd = timeFormat + TIME_TWENTYFOUR;//每日终止时间
}
此处entry.getValue()可能为空,如果不做判断就会出现空指针异常
因此应该在取值前做一下判断
if (entry.getValue()!=null)
17.上传附件的代码中,不检查文件名长度以及附件的文件大小不做限制
18.Socket,JDBC资源,File(I/O相关), LDAP连接,JMS连接,EJB,Non-Serialable Object等对象放入Session
19.方法的参数很多,超过5个
定义规范的目的是让项目中所有的文档都看起来像一个人写的,增加可读性,减少出现错误的几率。
减少维护成本;
一个软件的生命周期中,80%的花费在于维护,另一方面,几乎没有任何一个软件,在其整个生命周期中,均由最初的开发人员来维护,规范的编码减少人员变动带来的维护成本。
改善软件的可读性
可以让程序员尽快而彻底地理解新的代码。
程序的坏味道
1.在循环中对字符串操作时用String
在处理String 的时候要尽量使用 StringBuffer 类,StringBuffer 类是构成 String 类的基础。String 类将 StringBuffer 类封装了起来,(以花费更多时间为代价)为开发人员提供了一个安全的接口。当我们在构造字符串的时候,我们应该用 StringBuffer 来实现大部分的工作,当工作完成后将 StringBuffer 对象再转换为需要的 String 对象 。比如:如果有一个字符串必须不断地在其后添加许多字符来完成构造,那么我们应该使用 StringBuffer 对象和她的 append() 方法。如果我们用 String 对象代替StringBuffer对象的话,会花费许多不必要的创建和释放对象的 CPU 时间。
String sentence = "";
for( int i = 0; i < wordArray.length; i++ ) {
sentence += wordArray[ i ];
}
用StringBuffer.append()优化,优化后为:
StringBuffer buffer = new StringBuffer( 500 );
for( int i = 0; i < wordArray.length; i++ ) {
buffer.append( wordArray[ i ] );
}
String sentence = buffer.toString( );
2.考虑Windows与Unix平台的互移植性
换行符
System.out.print("Hello,world!\n");
优化后:
System.out.println("Hello,world!");
或者你构造一个带换行符的字符串:
String newline = System.getProperty("line.separator");
System.out.println("Hello world" + newline);
路径分隔符
在UNIX和Windows环境下,会采用不同的路径分隔符,如Windows中用”\”,而UNIX下一般采用”/”,因此为了保证系统的可移植性,需要分别进行处理。
String file_path = dir + “/” + file_name;
优化后:
String file_path = dir + File.separator + file_name;
3.滥用synchronized 关键字
Synchronized关键字是避免死锁的好方法,但同时会极大地降低性能,避免不必要的使用关键字 synchronized,应该在必要的时候再使用它。
public class LazySingleton { private static LazySingleton m_instance = null ; private LazySingleton(){}; synchronized public static LazySingleton getInstance(){ if(m_instance==null) m_instance=new LazySingleton(); return m_instance; } }
4.在循环中构造和释放对象
for (int i = 0; i < 10000; ++i) {
Object obj = new Object();
System.out.println("obj= " + obj);
}
上面的做法会浪费较大的内存空间。正确的做法如下所示:
优化后:
Object obj = null;
for (int i = 0; i < 10000; ++i) {
obj = new Object();
System.out.println("obj= "+ obj);
}
采用上面的第二种编写方式,仅在内存中保存一份对该对象的引用,而不像上面的第一种编写方式中代码会在内存中产生大量的对象引用,浪费大量的内存空间,而且增大了垃圾回收的负荷。因此在循环体中声明创建对象的编写方式应该尽量避免
5.对文件或者数据库的操作不及时关闭
FileOutputStream fos = new FileOutputStream(projectFile);
project.save(fos, “IDE Project File”);
FileOutputStream fos = new FileOutputStream(projectFile);
project.save(fos, “IDE Project File”);
fos.close();
6.对变量的重复计算
例如:
for(int i=0;i<list.size();i++)
应该改为
for(int i=0,len=list.size();i<len;i++)
并且在循环中应该避免使用复杂的表达式,在循环中,循环条件会被反复计算,如果不使用复
杂表达式,而使循环条件值不变的话,程序将会运行的更快。
7.一个方法的代码过长,超过1000行
应将方法设计成简要的、功能性单元,用它描述和实现一个不连续的类接口部分。理想情况下,方法应简明扼要。若长度很大,可考虑通过某种方式将其分割成较短的几个方法,这样做也便于类内代码的重复使用。
使类尽可能短小精悍,而且只解决一个特定的问题。下面是对类设计的一些建议:
■一个复杂的开关语句:考虑采用"多形"机制
■数量众多的方法涉及到类型差别极大的操作:考虑用几个类来分别实现
■许多成员变量在特征上有很大的差别:考虑使用几个类
8.不写注释,或者注释不清晰
命名不规范
排版格式混乱,不注意缩进与对齐等
9.滥用public公共类定义
让一切东西都尽可能地"私有"--private。可使库的某一部分"公共化"(一个方法、类或者一个字段等等),就永远不能把它拿出。若强行拿出,就可能破坏其他人现有的代码,使他们不得不重新编写和设计。若只公布自己必须公布的,就可放心大胆地改变其他任何东西。在多线程环境中,隐私是特别重要的一个因素--只有private字段才能在非同步使用的情况下受到保护。
10.在程序中使用硬编码
硬编码:
指的是在软件实现上,把输出或输入的相关参数(例如:路径、输出的形式或格式)直接以常量的方
式书写在源代码中,而非在运行时期由外界指定的设置、资源、数据或格式做出适当回应。一般被认
定是种反模式或不完美的实现,因为软件受到输入数据或输出的格式改变就必需修改源代码,对客户
而言,改变源代码之外的小设置也许还比较容易。
11.出现http 404或http 500错误
12.在JSP页面中使用JDBC API,直接写SQL语句以及业务逻辑代码
13.在程序代码中存在垃圾数据文件(例如.bak,keep, cvs文件夹等)
14.变量只有在用到它的时候才定义和实例化。
这是初学者最容易犯的错,合理的使用变量,并且只有在用到它的时候才定义和实例化,能有效的避免内存空间和执行性能上的浪费,从而提高了代码的效率。
例如:
void f(){ int i;
A a = new A();
if(…){
a.showMessage();
}
}
应该改成:
void f(){ int i;
A a = null;
if(…){
//用到时才实例化
a = new A();
a.showMessage();
}
}
15.所有调试信息直接System.out.print打印到控制台
Logger日志工具类
JS中debugger,以及console.log
16.对数组为空、数组越界、页面传递的参数为空等异常情况不做任何处理
for (Map.Entry<String,List<OfflineReportDTO>> entry : allResult.entrySet()) {
offlineCashe = entry.getValue();
String time_cashe = "";//定义临时时间
String way_cashe = ""; //定义临时的登陆方式,记录前一天最后一次的登陆方式
String TimeBegin = timeFormat + TIME_ZERO;//每日初始时间
String TimeEnd = timeFormat + TIME_TWENTYFOUR;//每日终止时间
}
此处entry.getValue()可能为空,如果不做判断就会出现空指针异常
因此应该在取值前做一下判断
if (entry.getValue()!=null)
17.上传附件的代码中,不检查文件名长度以及附件的文件大小不做限制
18.Socket,JDBC资源,File(I/O相关), LDAP连接,JMS连接,EJB,Non-Serialable Object等对象放入Session
19.方法的参数很多,超过5个