代码规范最佳实践

文/ BlackSwift(简书作者)

原文链接:http://www.jianshu.com/p/8cad7cb9d6ef 

代码规范是一个老生常谈的问题,涉及到一个码农的软技能。网上有很多类似的文章,但是有些文章比较落后了,因此需要补充新鲜的文章

主要参考如下

  1. 《编写可读代码的艺术》

  2. 《编程的智慧》

  3. 个人平时积累

我个人对代码规范的要求,主要就是一点:避免自己几个月后看着代码愤而打开提交记录看谁写的渣代码

下面的内容还是比较新的,从逻辑判断、注释规范等方面进行了思考。

1. 代码编写

1.1. 关于if的使用场景

1.1.1. 不要省略if中的其它条件

if是很容易犯错的地方,因此不要省略if中的其它条件,就算它什么也不做也要写出来,否则以后将是一个定时炸弹

if(a < 2){
  if(b > 3){
    //do sth.
  } else{
    //do nothing
  }
} else{
  //do nothing
}
1.1.2. 不要使用反义词

在使用boolean时,不要使用反义词,减少大脑Parser时间

//bad
boolean isNotExistInTable;
if(!isNotExistInTable){
  //到底判断条件是啥?负负得正?
}
//good
boolean isEmptyInTable;
if(!isEmptyInTable){
  //明白了,这里是Table中元素不为空的场景
}
1.1.3. 法示表达尤用使要不

尤达表示法曾经在C中非常流行,不过它的时代已经过去了

//bad, 多此一举
if(null == str){
}
//good, 因为编译器或者IDE均会进行校验,写成\`str=null\`会被检查出来了
if(str == null){
}
1.1.4. 按照“电路”逻辑进行编写

不要把判断全部写到if括号里

//bad
if(!(age > 18)&&!(today - startday > 30)){
  //wtf,大脑分析到一半忘记前面的变量了
}

下面就是按照“电路”逻辑进行编写的,每行一个比较,就算使用了b1,b2这样的命名,也能够看得懂。

//good
//必须18以上才能购买
boolean b1 = age > 18;
//如果小于等于30天,那么将没有优惠
boolean b2 = today - startday > 30;
if(!(b1&&b2)){
  //
}

1.1.5. 不要使用Lambda表达式

虽然Java8提供了此方法,但是它与JS、Ruby的风格完全不同。在Java中通过接口实现,而在动态语言中通过block或者函数对象实现,信息量也完全不同,除非全部成员都是大神。

不信的话,你写完代码后一个星期后看看是否还看得懂吧。

1.2. 关于流程处理

流程在业务代码中广泛出现,建议除了面试,不要在业务中使用goto、doWhile、contine、break,甚至for/while/iterator代码,它们可以被如下替换

  • try/finally

  • 函数式编程: Java8stream, RxJava, Guava, CommonCollection4, 特别推荐stream,它内部与Haskell一样支持惰性求值,效率肯定比自己写的轮子更优秀。

我个人推荐使用函数式表达式,也就是类似于脚本语言的写法来写Java,看黑板:

idea_2016_3_streams_intentions_7.gif

1.3. 注释中加入自己的判断与想法

1.3.1. 使用大家都认可的行话

比如FIXME,TODO等,这个在Intellij中有快捷键

//FIXME: 在某场景下调用时出现一个异常没有复现,详见xxx工单
private doWork(){
}
1.3.2. 警告他人调用的陷阱
//警告,内部使用了for循环查表,可能导致阻塞而变慢
public list<String> querybyId(List<Node> nodes,long id){
}
1.3.3. 注释中描述修改的原因
private doWork(){
  //根据工单xxx进行修改,处理了某场景问题
  sth.doAnother();
  //虽然看似没用,这样写的原因是....
  sth2.doAnother();
}

无论何时,只要是你心里所想,只要不是用来粉饰烂代码,就可以写出来,以后代码更新时,可以快速进入状态,避免再次读码而浪费时间

1.3.4. 对重要的对象提供一个例子

在构造变量时,可以通过注释例子帮助理解。不要吝啬代码在VCS中所占用的空间,以免后期查阅文档浪费更多的时间

/**
* the id of employee, \[a-zA-Z0-9/s\]{0,12}
* eg: xyz223344
**/
String id;
/**
* the blur redis, must be power of 2
* eg: 2, 4, 8
**/
int BLUR_RADIS = 8;
/**
* return the person whoes age > ${age}
* eg: (18,\[14,46,18,50\]) -> \[46,50\]
**/
private List<Person> filterByAge(int age, List<Person> person){
}
/**
* valid by regex defined in file: xxx.ccc.bbb.xml
**/
private boolean doVaild(String s){
}

1.4. 使用注解

添加注解,让你的IDE更加智能地进行静态检测

  1. Android: Improve Code Inspection with Annotations,注意可以将注解设置为provided模式

  2. Java: 使用JavaX自带包,注意这个包里面老是在变,我个人日常也是只用Null判断

1.5. 建立自己的Util

除了Apache等出名的工具类外,也可以将自己的通用代码放入Utils中,好处如下

  1. 降低代码量

  2. 对Apache等工具类不完善的地方进行再包装

  3. 写完了可以骗Star(当然我个人不赞同,也不敢用)

  4. 熟悉常用的库,减少自己造轮子

2. 编码完成后,使用CodeFormatter

代码格式化(CodeFormatter)工具涉及到审美、对齐、缩进、左括号之争。统一的格式能减少代码阅读时的误判。

我个人推荐用Square的格式,倒入格式后cmd +alt + L即可

https://github.com/square/java-code-styles

如果你所在公司有自己的格式要求,就算你认为“不合理”,也要按照公司大流来

3. 使用静态分析工具检查源码

静态分析工具通过对Java文件的AST进行分析,找出潜在的问题,通过自动化工具节约时间。

1. Intellij

使用Intellij的代码检查功能,平时尽量处理掉IDE右边的黄色警告(比如未使用的变量、错误的拼写),写完代码后,尽量用Inspect去跑一遍整个代码

2. FindBugs/PMD

这个同上,许多公司都用它作为VCS门禁,没跑通不能上库。在本地环境它可以作为Intellij的插件引入,它是根据class文件进行静态分析的,功能如其名。建议将设置中的报警级别调为最敏感。

4. SUM

总的来说,代码还是需要积累,建议多看源码,不管是我的文章,还是教你写代码的书籍,都不如直接看现成的代码,各位可以mark下面几个项目,纯函数,没有复杂逻辑