最近换了新的工作,在阅读前辈写的代码过程中(历史原因),真的是各种吐槽,加上自己阅读的一些编码书籍,结合自己积累的一些编码习惯,总结了一下,方便自己回顾。
参考资料:
编写可读代码的艺术(非常不错的书,告诉你如何判断代码的好坏)
Robust Java 中文版(java异常和测试)
58同城Java编码规范
阿里巴巴Java开发手册
代码规范需要从读者的角度去考虑。
常用格式
适当换行,一行代码在当前屏幕下不用左右滚动,考虑到不同屏幕的分辨率,尽量控制每一行不要超过120个字符。
方法不要超过100行,尽量控制在一屏以内。
全局变量声明尽量放在代码块开始处,内层尽量不要过多声明变量
字符串比较时,将常量置于equals之前str != null && str.equals(“”) è (“”).equals(str)
操作符前后加空格a == b
If/for/while等保留字和后面的括号之间需要空格,括号内左右不需要空格,多个参数,后面必须空格
定义javabean时,属性统一放一起,写在开头,方法统一一起,放在属性后,属性和方法不要交叉。
为防止出现NULL转基本类型错误,属性建议全部用封装类型。
缩小变量的作用域,尽量减少全局变量,全局变量定义放在一起,不要哪里第一次用,定义在哪里。
以前不推荐定义变量前移,是因为无法确定该变量是否未使用,可以移除,但在新的IDE下,未使用的变量会有提示。
命名
接口类实例等是表示是什么,需要名词或名词短语,传统的模式中,方法表示do something,是基于业务的,所以需要时动词或者表示动作含义的短语。rest是基于资源的,和传统的模式有一些区别,所以rest下的命名有一些不一样,rest的方法表示对资源的操作。
可以使用2表示to,4表示for,用来连接命名
注释
注释需要站在读者的角度,考虑读者需要得到的信息
注释的作用是为了让读代码的人,能够尽快的了解代码在干些什么。所以,在写代码的时候,不仅需要用代码将脑海中的想法写出来,还需要在较为复杂的地方,用简单易理解的文字,记录想法,表述思路。
布局
关系较为紧密的代码应尽可能相邻,让相关的代码组成代码块,代码块之间用1-2个换行来区分
使用一致的布局,让读者能够快速习惯代码风格
不完全相信外部输入,进行合理验证,XSS攻击
最小量使用外部输入参数(方法形参最小化)
异常
尽量不要使用Java异常机制进行业务逻辑的判断
尽量输出异常的堆栈,以方便问题及Bug的查找。
避免异常信息直接展现给用户,对用户不友好
如何选择try catch去处理异常,还是throws抛出到上层
基本原则是尽可能的去处理异常,当没有能力或条件处理时,需要抛出异常。
处理异常的常用方式
记录异常相关信息:单纯的记录异常信息,在调用链的底层,没有必要的意义,同时,上层调用方还需要额外的操作来判断执行结果,建议抛出异常到上层。
返回明确友好的信息:比较友好的交互,一般用在最接近客户的应用层,如果在底层使用这种方式,需要将返回信息包装对象层层传递,直到和客户直接交互的最上层,不建议。
返回修改后的数据或默认值:当出现异常时,返回指定的数据,比如默认值等,可以考虑这种方式,上层不需要再处理异常,一般也不需要判空等额外的操作来判断执行结果。
转到其他部分处理:将是否存在异常当做逻辑判断,不推荐使用
忽略异常,不进行任何操作,仅仅只是捕获,应尽量避免此类操作:这种情况,建议使用抛出的方式,给上层处理
重试恢复或者停止应用等明确的处理方式:建议使用捕获处理的方式
常量
尽量少的在代码中直接使用字面量,不得已必须使用时,一定要加上字面量含义的注释。
接口
接口时,尽量减少对外部参数的依赖,能够自己获取的,尽量自己获取,方便调用方,同时,也符合不完全相信外部输入的原则。
返回数据时,返回的数据大而全,会加大IO消耗,从而影响响应时间,但同时会减少访问次数,增加可用性;返回的数据刚好满足目前需要,不会影响响应时间,但会造成可用性不高,修改任何上层调用方,都可能需要修改返回值。
工程学(拆分)
工程学就是把大问题拆分成小问题,找出解决小问题的方案,然后把这些解决方案拼装在一起,软件开发既然被归纳成工程学,自然也需要拆分。
一段代码块只处理一件事,按照事件拆分
多个地方需要,拆分公共部分
和当前业务无关,可拆分成工具
…
表达式
太长的表达式,拆分成多个表达式
If(表达式1 || 表达式2 || 表达式3 || 表达式4)è 单独封装一个方法 if(表达式1) return
多次使用的表达式,引入额外变量代替
If(表达式 == obj1 || 表达式 || 表达式) è Obj obj = 表达式
分支嵌套
循环分支等会使代码变得混乱,
多层嵌套会使代码看起来很复杂,尽量减少代码的嵌套层次,必要的时候,借助return,breake,continue等等反向考虑可能会简单很多
调整以后的代码
条件顺序
If (a > 10 ) || If (10 > a )
If(null == obj),历史原因,以前IDE工具没有现在智能化,当出现If(obj = null)的情况下,不会提示异常,而If(null = obj)无法编译通过,会提示异常,为了减少If(obj = null),建议使用If(null == obj),现代IDE非常智能,所以不需要刻意的写出、成If(null == obj),但建议项目中保持一致,要么全写成If(null == obj),要么全写成If(obj == null)。
是否需要单一出口(尽量只有一个return)
单一出口的目的是为了保证在函数结尾的清理工作,但是java中提供了更好的方式,try finally,而且提前返回可以减少代码的执行时间等优势,所以,可以使用提前return
善用API
最好读的代码就是没有代码
开源API是大家都接受,能快速理解的代码,善用开源API,能减少开发时间,保证代码简洁可读。
适时的对代码重构
添加一个新功能点,感觉会影响代码的可读性,加大代码复杂度的时候,可能需要考虑,重构这部分代码
代码没有层次感,严重影响阅读,需要考虑重构
一个代码块长度过长,一般超过100行,就需要考虑重构
发现存在大量重复使用代码时
…