为Java,我们要做点什么? ——提高代码质量

原创 2007年09月26日 16:38:00

Java,我们要做点什么?

——提高代码质量

前言:

       代码作为一个软件的核心内容,其品质的优劣直接决定了一个软件项目或产品最终的成败,正因为这样,在软件开发过程中,代码质量的管理就应该提升到一个集规范化、艺术化的角度去研究。规范化大多数开发过软件的人都能够理解是怎么一回事,即保证整个系统在代码风格上的统一,以便于管理,这样的统一其实囊括了多方面的因素,例如变量的定义规范,注释的书写原则等等,作为Java,这样的规则其实早就形成了一套业内墨守成规的定义,这样的定义其实都是遵循了一些高效开发的原则,同时凝聚了诸多软件设计界大师优秀编程习惯的精髓而成的。至于艺术性,我想在本文的最后,各位是应该能得到属于自己的答案的。现代编程,我们可以寻找到非常多的非常优秀的学习资料,因此,可以不夸张的说,站在巨人的肩膀上,我们在开发过程中,碰多的许多问题都是能得到比较完美的解答的,但是这样的答案要我们去不断的总结,不断的扩充,才能找到正解。下面我本人通过自身的实践,并在互联网上搜集的一些关于在代码管理上的一些同行的见解,希望能给各位带来一些帮助。

 

第一篇:你准备好了吗?

       Java,一种极具表现力的编程语言,在现代软件发展的舞台上占据了一席不可替代的位置,为什么这么说,我想任何一位曾经接触过它,异或是正在使用它的人都是会有这种体会的,其实更加准确的说,使用过它的人才能从真正意义上去理解这一层概念,因为它的设计者们已经赋予了它生命和灵魂,我是这样认为的,曾经我写过这样的一篇文章,有兴趣的可以在我Blog里看到http://blog.csdn.net/lzq3180/archive/2007/01/01/1471871.aspx,作为任何一位准备使用Java或是正在使用Java的人,我想每个人都应该问一下自己,“我准备好了吗?”,我不是危言耸听,一个只对Java基本语法了解的开发人员真的能胜任一个真正意义上的企业级Java项目吗?是的,系统架构师已经为你设计出了轮廓,是的,技术总监们已经随时准备着为你处理技术难题了,看似我们能做的就是按照他们的意图去实现吧,“实现”,一个我经常听到的名词,一个看似简单的工作,其实对一个软件产品是否稳定,是否健壮起到了决定性的因素,但是,这一步在很多的公司却总是不会被提升到一个很高的层次去研究。在我看来,一个成熟的团队,至少他的每一位开发人员都能熟练的、巧妙的运用他手中的那把“枪”,那才能称之为一个具有战斗力的团队。奉上程序般的一句话,“if (Are you ready?==’yes’ ) let’s go; else return;

 

第二篇:修炼之道

       在前言里,我说过,“代码质量的管理应该提升到一个集规范化、艺术化的角度去研究”,这里,我就谈谈,如何让代码规范,如何让代码赋予艺术。

       规范,一个在开发中不会不提的一个话题,有的落实的很好,有的呢,很不乐观,一方面也许是项目管理者自身出现的问题,这里我们就不做探讨,另一方面,很有可能就是这个规范在实践中本身就很难去规范,慢慢的,就没有人去遵守。

       下来,我就在Java项目开发中,总结了一些简约的规范,仅供参考;

(1)Java代码书写规范(技巧)

1)  所有文件的开头都要有Java文档的注释。

2)  文件里的代码的首行是所在包的说明,接下来是引入类的说明。

3)  包名以一个小写的顶层域名开始(例如,com.edu.)

4)   类和接口名应该是名词,而且组成它的每个单词的首字母必须大写(例如,EmployeeHours)

6) 所有的类文件应该包含以下部分:

该类的Java文档;
变量列表:静态变量、实例变量(publicprotectedno access specifiedprivate)
方法列表:构造体和方法(方法应该按照功能分组)

7)  方法名应该是动词,第一个单词的首字母小写,接下来的单词的首字母大写(例如:getHoursWorked)

8)   变量应该以字母打头,只有一个字母的变量(例如,ijk)应该避免出现,除非是一个暂时变量(例如,在一个for语句中)

9)   尽量使类中所有的变量都是私有的,只能通过方法来访问它们。

10)   常量应该全部大写,单词之间由下划线分隔(例如,MAX_WORK_HOURS)

11)   用常量来定义具体数值(例如,int MAX_WORK_HOURS=24)

12)   内部变量声明时应该对它进行初始化。

13)   一行应该包含一个语句。        

14)  在使用if-elseforwhiledoswitch语句时应该使用大括号。

(注:对于注释的详细介绍,可以介绍一片文章,将的比较详细,http://www.iplab.cs.tsukuba.ac.jp/~liuxj/jdk1.2/zh/docs/tooldocs/win32/javadoc.html#documentingpackages)

 

(2)Java代码书写规范(细节)

1) 可读性:避免使用不易理解的数字,用有意义的标识来替代。不要使用难懂的技巧性很高的语句;源程序中关系较为紧密的代码应尽可能相邻。

2) 美观方面:

2.2.1 关键词和操作符之间加适当的空格。

2.2.2 相对独立的程序块与块之间加空行。

2.2.3 较长的语句、表达式等要分成多行书写。

2.2.4 划分出的新行要进行适应的缩进,使排版整齐,语句可读。

2.2.5 长表达式要在低优先级操作符处划分新行,操作符放在新行之首。

2.2.6 循环、判断等语句中若有较长的表达式或语句,则要进行适应的划分。

2.2.7 若函数或过程中的参数较长,则要进行适当的划分。

2.2.8 不允许把多个短语句写在一行中,即一行只写一条语句。

2.2.9 函数或过程的开始、结构的定义及循环、判断等语句中的代码都要采用缩进风格。

2.2.10 编写程序块时‘{’‘}’应各独占一行并且位于同一列,同时与引用它们的语句左对齐。在函数体的开始、类的定义、结构的定义、枚举的定义以及iffordowhileswitchcase语句中的程序都要采用如上的缩进方式。

(注:某些IDE已经为你完成了代码的这些格式化工作了,例如EclipseJBuilder等都提供这些功能)

 

       (3) 代码性能提高

1)   避免一行中超过80个字符。

2)  数组标识:要用"int[] packets",而不是"int packets[]",后一种永远也不要用。

3)  不要在循环中构造和释放对象。

4)   如何使用Exception
Exception
降低性能。一个异常抛出首先需要创建一个新的对象。Throwable接口中的构造器调用名为fillInStackTrace()的本地方法。这个方法负责巡检栈的整个框架来收集跟踪信息。这样无论何时有异常抛出,它要求虚拟机装载调用栈,因为一个新的对象在中部被创建。异常应当仅用于有错误发生时,而不要控制流。

5) 
不要两次初始化变量,Java通过调用独特的类构造器默认地初始化变量为一个已知的值。所有的对象被设置成nullintegers (byte, short, int, long)被设置成0floatdouble设置成0.0Boolean变量设置成false。这对那些扩展自其它类的类尤其重要,这跟使用一个新的关键词创建一个对象时所有一连串的构造器被自动调用一样。
6)  
在任何可能的地方让类为Final,标记为final的类不能被扩展。在《核心Java API》中有大量这个技术的例子,诸如java.lang.String。将String类标记为final阻止了开发者创建他们自己实现的长度方法。更深入点说,如果类是final的,所有类的方法也是final的。Java编译器可能会内联所有的方法(这依赖于编译器的实现)。在我的测试里,我已经看到性能平均增加了50%
7) 
在任何可能的地方使用局部变量,属于方法调用部分的自变量和声明为此调用一部分的临时变量存储在栈中,这比较快。诸如static,实例(instance)变量和新的对象创建在堆中,这比较慢。局部变量的更深入优化依赖于你正在使用的编译器或虚拟机。
8) 
很多开发人员在脑子中编写可复用和灵活的代码,而有时候在他们的程序中就产生额外的开销。曾经或者另外的时候他们编写了类似这样的代码:

public void doSomething(File file) {
FileInputStream fileIn = new FileInputStream(file);
// do something

他够灵活,但是同时他们也产生了更多的开销。这个主意背后做的事情是操纵一个InputStream,而不是一个文件,因此它应该重写如下:
public void doSomething(InputStream inputStream){
// do something

9)  乘法和除法,摩尔法则——它声明CPU功率每年成倍增长。"摩尔法则"表明每年由开发者所写的差劲的代码数量三倍增加,划去了摩尔法则的任何好处。
考虑下面的代码:
for (val = 0; val < 100000; val +=5) { shiftX = val * 8; myRaise = val * 2; }

如果我们狡猾的利用位移(bit),性能将会六倍增加。这是重写的代码:
for (val = 0; val < 100000; val += 5) { shiftX = val << 3; myRaise = val << 1; }


代替了乘以8,我们使用同等效果的左移3位。每一个移动相当于乘以2,变量myRaise对此做了证明。同样向右移位相当于除以2,当然这会使执行速度加快,但可能会使你的程序以后难于理解;所以这只是个建议
10) 
用代码有效处理内存溢出
OutOfMemoryError
是由于内存不够后普遍会遇到的问题,下面一段代码能有效判断内存溢出错误,并在内存溢出发生时有效回收内存
通过该方法可以联想到有效管理连接池溢出,道理等同。
import java.util.*;
public class DataServer
{
private Hashtable data = new Hashtable();
public Object get (String key)
{
Object obj = data.get (key);
if (obj == null)
{
System.out.print (key + “ ”);
try
{
// simulate getting lots of data
obj = new Double[1000000];
data.put (key, obj);
}
catch (OutOfMemoryError e)
{
System.out.print (“/No Memory! ”);
flushCache();
obj = get (key);// try again
}
}
return (obj);
}
public void flushCache()
{
System.out.println (“Clearing cache”);
data.clear();
}
public static void main (String[] args)
{
DataServer ds = new DataServer();
int count = 0;
while (true) // infinite loop for test
ds.get (“” + count++);
}
}


11)  Lazy Loading Lazy evaluation)在需要装入的时候才装入
static public long
factorial( int n) throws IllegalArgumentException
{
IllegalArgumentException illegalArgumentException = 
new IllegalArgumentException( “must be >= 0”);
if( n < 0) {
throw illegalArgumentException ;
} else if( ( n == 0) || ( n == 1)) {
return( 1);
} else (
return( n * factorial( n - 1)) ;
}


优化后代码
static public long
factorial( int n) throws IllegalArgumentException
{
if( n < 0) {
throw new IllegalArgumentException( “must be >= 0”);
} else if( ( n == 0) || ( n == 1)) {
return( 1);
} else (
return( n * factorial( n - 1)) ;
}


12)  异常在需要抛出的地方抛出,try catch能整合就整合

已下代码 更容易被编译器优化
try {
some.method1(); // Easier to optimize
some.method2();
some.method3();
} catch( method1Exception e) {
// Handle exception 1
} catch( method2Exception e) {
// Handle exception 2
} catch( method3Exception e) {
// Handle exception 3
}


13)  For循环的优化
Replace...
for( int i = 0; i < collection.size(); i++) {
...
}
with...
for( int i = 0, n = collection.size(); i < n; i++) {
...
}


14)  字符串操作优化
在对字符串实行+操作时,最好用一条语句
// Your source code looks like...
String str = "profit = revenue( “ + revenue +
”) - cost( “ + cost + ”)";



// 编译方法
String str = new StringBuffer().append( "profit = revenue( “).
append( revenue).append( “) - cost( “).
append( cost).append( “)“).toString();


在循环中对字符串操作时改用StringBuffer.append()方法
String sentence = "";
for( int i = 0; i < wordArray.length; i++) {
sentence += wordArray[ i ];
}


优化为
StringBuffer buffer = new StringBuffer( 500);
for( int i = 0; i < wordArray.length; i++) {
buffer.append( wordArray[ i ] );
}
String sentence = buffer.toString();


15)  对象重用(特别对于大对象来说)
public
class Point
{
public int x;
public int y;
public Point()
{
this( 0, 0);
}
}


优化为:
public class Component
{
private int x;
private int y;
public Point getPosition()
{
Point rv = new Point(); // Create a new Point
rv.x = x; // Update its state 
rv.y = y;
return rv;
}
}
// Process an array of Component positions...
for( int i = 0; i < componentArray.length; i++ ){
Point position = componentArray[i].getPosition();
// Process position value...
// Note: A Point object is created for *each* iteration
// of the loop...
}


可再次优化,仅使用一个类对象:)
public
class Component
{
private int x;
private int y;
public Point getPosition( Point rv)
{
if( rv == null) rv = new Point();
rv.x = x; // Update its state 
rv.y = y;
return rv;
}
// Create a single point object and reuse it...
Point p = new Point( );
for( int i = 0; i < componentArray.length; i++ ){
Point position = componentArray[i].getPosition( p );
// Process position value...
// Note: Only *one* Point object is ever created.
}


15)   j2ee相关
a) 
尽量不要将大对象放到HttpSession或其他须序列化的对象中,并注意及时清空Session
b) 
使用预编译语句prepareStatement代替
createStatement
c) 
尽可能使用连接池

 

       (4) 代码测试与维护

代码测试和维护是保证代码质量一个很关键的工序,由于本人水平有限,这里就不做介绍了。

 

“剑道于身,剑道亦离身”,练剑者当他脱离剑的束缚,达到人剑合一的时候,就达到“手中无剑,心中有剑”了。

 

第三篇:“手中无剑,心中有剑”

       当你对习惯于一些优秀的规范的时候,那也就不是什么规范了,他就成为了你的一部分了,因为这个时候,你的“剑”已然不再是那把“剑”,他已经成为了你的灵魂了。我想,程序在那个时候不再只运行于那冰冷的机器上,而在你那火热热的心中,那样的程序不只是产品,更是一件活生生的艺术品,这就是我理解的艺术化,希望能与你产生共鸣。

 

鸣谢:

       伟大的祖国,伟大的民族!

 

      

                                                                                                         作者:Aaron(打水人)

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Bootstrap学习心得

这句话是说明让当前的视图等于当前物理折别的大小 Bootstrap是移动设备优先的。 Bootstrap所有的js插件都依赖jquery css文件放在head中js文件放在body的最下面 ...

HttpClient学习笔记

HttpClient简介HttpClient 是 Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HT...

Java项目源码为什么要做代码混淆(解释的很好)

代码混淆,是将计算机程序的代码转换成一种功能上等价,但是难于阅读和理解的形式的行为。代码混淆可以用于程序源代码,也可以用于程序编译而成的中间代码。执行代码混淆的程序被称作代码混淆器。目前已经存在许多种...

最近一段时间要做的事情就是它了——Java服务器端的相关技术

原文链接 http://www.jianshu.com/p/814d05ddb54a 应届毕业生如何成为一名服务器端开发工程师(一) 字数1298 阅读1860 评论1...

菜鸟要做架构师(二)——java性能优化之for循环

完成同样的功能,用不同的代码来实现,性能上可能会有比较大的差别,所以对于一些性能敏感的模块来说,对代码进行一定的优化还是很有必要的。今天就来说一下java代码优化的事情,今天主要聊一下对于for(wh...

记互助网成立互有会的美丽缘由——人生的意义:平凡人要做点不平凡的事情

【1】人生的意义:平凡人要做点不平凡的事情 去过婺源的人都知道,婺源有一座特别的桥,叫做彩虹桥,这是中国最美的廊桥。 很多人知道这个桥,却不知道这座廊桥是由两个异想天开的年轻人建造的。 ...

IT面试经验——提高面试代码质量的三要素

代码的规范性     面试官是根据应聘者写出的代码来决定是否录用一个应聘者的。应聘者首先要把代码写得规范,才可以避免很多低级错误。如果代码写得不够规范,会影响面试官阅读代码的兴致,至少印象分会打...

实习日常(1)——提高代码质量:过度保护以及TDD,BDD

Beginning TDD,BDD:在刚到公司的时候,重构java旧项目,花了漫长时间,写了与原代码运行路径一致,但很繁复的代码,导致在一天之后难以阐述逻辑。被质疑逻辑错误,当时委屈。最后修改抽出了...
  • V_code
  • V_code
  • 2017年01月02日 21:16
  • 220

重构——提高现有代码的质量

  • 2007年10月20日 13:21
  • 2.02MB
  • 下载

提高你的Java代码质量吧:使用valueof前必须进行校验

一、分析  每个枚举都是java.lang.Enum的子类,都可以访问Enum类提供的方法,比如hashCode、name、valueOf等,其中valueOf方法会把一个String类型的名称...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:为Java,我们要做点什么? ——提高代码质量
举报原因:
原因补充:

(最多只允许输入30个字)