最近在几个不同的团队中发现他们的编码规范中对空格的用法大不相同。这激起了我的好奇心,因为我一直觉得,对于代码格式中的空格的使用,应该有一个大家都公认的最好的习惯。但是在现实开发中,似乎没有出现这样的统一。
现状
首先,我们看看在大多数JavaIDE中Java代码的风格习惯。
下面是一个例子:
publicclassExample{
publicstaticvoidmain(String[]args){
intanswer=2+4*6;
for(inti=0;i<5;i++){ doSomething(); } System.out.println("Theansweris"+answer); } privatestaticvoiddoSomething(){ //something } } 请注意,这是Java编程者中和其它类似C语言的语言中最常见的一种风格 在括号内部两边没有留空格。只有当括号前面有关键字for或while等时,空格才会出现在它们之间,但在方法名和其之后的括号间没有空格。然而,在左大括号前总会有空格(这个左大括号一般会出现在一行的最后)。数学操作符总有空格包围。而分号前不会有空格。 如果你经常阅读代码,也许认为这是很自然的安排,但如果你不是一个程序员,可能会认为这些规则太随意,有很多不统一、特例、有待讨论的地方。
请给你的代码留下多一些空间
在我当前的开发项目中,公司里有两个主要的开发团队,一个是LoadTestProducts(LTP)团队,另一个是FunctionalTestProducts(FTP)团队。两个团队里遵守了一些编码风格习惯,其中对空格的使用都是特别慷慨,就像下面这个代码片段的例子:
publicclassExample
{
publicstaticvoidmain(String[]args)
{
intanswer=2+4*6;
for(inti=0;i<5;i++) { doSomething(); } System.out.println("Theansweris"+answer); } privatestaticvoiddoSomething() { //something } } 这种风格看起来代码的密度更小,而且更有统一性(例如,在左括号前都没有空格,在所有的括号、花括号、中括号的左右内边都有空格)!我并不是说这样比之前的风格更好或更差….只是这样更容易区别单词。代价就是一个屏幕里只能显示更少的代码。 虽然每种编码风格都有各自的优势和缺点,但让我吃惊的是,FTP开发团队最终决定转向使用之前提到的最常见的那种编码风格。他们认为这种转变是值得的,他们甚至还进行过讨论,所以,我相信他们认为这种转变是重要的。他们判断的依据并不是这种比那种好…我认为这主要着眼于什么人习惯这种风格,因为我们的大部分产品都是开源的,这是重要原因,更容易让社群内的程序员捐赠代码。 在我的团队里,LTP团队,我们仍然坚持我们的风格,不打算做任何改变。至少对于我来说,这是一种基于技术考虑的决定:如果另一种编码风格没有体现出任何的优势(我们的这个项目对开源捐赠的需求很少),为什么要转向另一种风格?
规则需要统一
我一直在给开源项目捐赠代码,比如Ceylon编程语言,让我非常吃惊的是,他们完全没有遵守任何的编码风格。你可以用任何你喜欢的风格来写代码。
也许某些被一些公司里大量的编码规范惊吓住的程序员会喜欢这样,但我相信,如果没一套编码规范,你的项目的代码很可能在格式上出现混乱。每个代码捐赠者都会在提交的代码里带入他特有的代码风格,这不奇怪,结果就是所有的代码各式各样,你从下面几行代码里就能看到多种不同的风格:
while(existscell=iter){
if(existselem=cell.element,
elem==element){
last=cell;
}
iter=cell.rest;
}
}
if(existscell=last){
cell.element=replacement;
returntrue;
}
assert(0<=index
我认为,这个问题非常容易回答!当然会影响。用眼睛逐行扫描一下下面两段代码(从Ceylon项目中选出的),你会很容易感觉到哪个更易读。–CeylonCreate)?
functionvalidModuleNameChar(Characterc)=>c.letter||c.digit||cin['_','.'];
if(!trimmedName.empty,
validModuleNameFirstChar(trimmedName.firstelse'X'),
trimmedName.every(validModuleNameChar),
!(trimmedName.split('.'.equals,true,false)).containsAny(ceylonKeywords.chain{""})){
returntrimmedName;
}
functionvalidModuleNameChar(Characterc)=>c.letter||c.digit||cin['_','.'];
if(!trimmedName.empty,
validModuleNameFirstChar(trimmedName.firstelse'X'),
trimmedName.every(validModuleNameChar),
!(trimmedName.split('.'.equals,true,false)).containsAny(ceylonKeywords.chain{""}))
{
returntrimmedName;
}
它们的区别也许很小,但如果你整天花大量的时间读大量的代码,这区别就大了。