一、为何要注重编程格式
今天,Java已成为软件开发的主流用语,笔者近来看到这样一个统计结果:在商业软件产品中,软件产品的后续成本中约80%用于维护开销。而软件维护往往很少由原创者担任,良好的源码编写风格有益于日后软件维护已成为诸软件商公认的事实。
当今,软件产品早己步入团队协作式开发模式,要成为一支优秀开发组的关键因素之一就是组员之间的密切交流,它体现在整个开发周期,从需求、计划、测试案例、设计,到算法、实现方式等软件工程各阶段当中。具体到每一个实现模块的源代码亦不例外。简言之,就是你在编写这段代码时应当让其他人清晰的了解这段代码“是什么”,当程序出错时,其他人能够从程序逻辑上迅速分析找到错误出处。
二、讲究细节
就程序应具有的“透明性”而言,开发小组应当采用一种共同的编写格式。比如Java,大家应当采用同一种IDEs (Integrated Developer Environments)。自2000年以来,Java开发所用IDE发展基本成型,开发人员一致采用的平台通常都是可免费下载的Sun公司的Netbeans IDE和Eclipse IDE,这两种工具都是优秀的“格式化”工具,有助于开发组形成良好的编程风格。如果有人至今还固执地采用那种原始的文本编辑器输入Java代码,未免显得愚钝。
在我们输入源代码时,一个容易忽略的问题是代码显示。传统的代码行通常限制的字符数是80,这主要是考虑到最低廉的文本终端80x25显示模式,这种思维在21世纪宽屏时代早已过时。今天的每行代码字符默认值达120。在输入代码时我们遇到的一个心理活动就是用空格还是制表符Tab,一个Tab等于几个空格,现在的答案是4个空格。
在Java中,从基本语法(比如while, do, for 等循环语句和类定义)开始就涉及到大括号,那么这些括号的摆放位置即便是专业程序也具有不同风格,这里例举如下:
// K&R风格
if (condition) {
statement;
statement;
}
//Allman风格
if (condition)
{
statement;
statement;
}
//Whitesmiths Style风格
if (condition)
{
statement;
statement;
}
//GNU风格
if (condition)
{
statement;
statement;
}
究竟哪种格式好?维基百科论坛对此曾有过较长时间的讨论,结果多数人倾向于前两种格式。如果留心的话,你会看到在Sun公司网站和手册中的代码都采用了K&R风格。一次在做项目时,多数同事都采用了Allman风格,当我发现这点时编写的代码总量已达数千行,此时如果为此而逐行修改不是怕耗时而是进度不允许,此时幸好我采用的Eclipse提供了格式配置工具遂即刻搞掂。流行的Java编辑器在输入左括号时都会自动出现对应的右括号。
在代码的控制结构中,假如只有一行执行语句,从语法上讲,此时的大括号可以省略,但依笔者的经验,此举其实不明智,试想假如在后续编程时需在控制结构中新增加语句时,对控制结构的界限即便是作者本人有时也会混淆,所以,更为稳妥的编写风格是即便是只有单行语句的控制结构也应当写入一对并不多余的大括号,样例如下:
... 不好的习惯 ...
if (condition)
statement;
... 它可能造成的后果是...
if (condition)
statement;
statement;
尽管从语法上讲,将多条语句放在同一行上不会出错,但这亦属不良习惯,因为当他人对该语句进行复制/粘帖等编辑时容易搞错。另一方面,对于一行容不下的超长语句,那么续行应当有明显的凹进,并保证词组的完整性,其形式如下:
if (some really long condition that you need
to continue here)
{
statement;
statement;
}
再如:
...
com.acme.foo.project.data.YourObjectFactory objFactory =
new com.acme.foo.project.data.YourObjectFactory();
...
当用到超长的条件表达式,有时为了逻辑清晰起见,我们应善于对其进行必要的分解,将一行分解为多行短句,例如:
... 原来的代码语句是...
if (value != null && value.length() > 0 && (errCount = 0 ||
isIgnorable(currentError)))
{
... statements ...
}
... 将其分解为...
boolean valueIsGood = (value != null && value.length() > 0);
boolean noErrors = (errCount = 0 || isIgnorable(currentError));
if (valueIsGood && noErrors)
{
... statements ...
}
Java代码中的注释语句分为线型和块状,虽然笔者习惯使用前者,常用于描述一个变量的作用,但这种方式在网站论坛交流时会产生一种不良副作用,在网站上传代码时容易出现不连贯现象。防止出错的方法是,在上传代码时之前一定要预览显示结果。
在Java的声明机制中,应注意变量的声明位置,对于静态变量或常量,应当置于源码文件的顶部,这种风格来源于C语言。但Java对传统C的一种明显突破是,方法级变量是在需要时即时声明和初始化,其合理性在于我们不必劳神声明太多的类变量。
Java对类和变量的命名其实现在已形成了约定俗成:Types (类, 接口等)应当多用小写字母,单词间无空格,但每个单词首字母要大写,形如:SomethingLikeThis;非常量型变量的声明则多用小写字母,而且首字母要小写,单词间无隙,但从第二个单词起则冠以大写字母,形如somethingLikeThis。对于常量(Java中常用的对应关键字是final,也即'static')在命名时通常皆由大写字母组成,形如:SOMETHING_LIKE_THIS。所以,一段成熟的Java代码在命名和拼写时应当犹如以下样码:
class MyNeatClass
{
private int currentValue;
public static final String SOME_STRING_CONSTANT = "Blah blah";
...
public void doSomething()
{
...other statements...
...
int count=0;
for (loop condition)
{
if (branch condition)
{
count++;
}
}
...
}
}
新版Java出现的enum(“枚举”)类型,看起来很象是特殊的class, 它也可以有自己的变量,可以定义自己的方法,可以实现一个或者多个接口。 当我们声明一个enum类型时,定义通常是具有直观意义的字符串,比如:
enum MyFirstEnum
{
ALPHA,
BETA,
GAMMA,
DELTA;
}
此外,Java编译器对于源文件的调用具有优先级标准,我们在编写代码时须遵循这一规则,具体次序为:项目所需的头文件,包声明语句,引入语句,type声明以及"extends"项及"implements",类变量,类方法,内部类声明。
三、小结
本文从Java基本语法入手,列举了Java良好编程风格所应体现的各种规范和规则细节。也许有人会有小题大做之感,但笔者积多年的编码体会是,编写代码越多固然有利于编程技艺的提高,但规范的编程习惯将使写出的代码更便于分析和调试,这对于代码的优质运行将善莫大焉;一个软件项目的成功需要每个开发成员从自己做起,从每一行Coding开始。