返回首页
当前位置: 主页 > 编程语言 > JAVA教程 >

Java开发规范

时间:2018-01-09 23:51来源:电脑教程学习网 www.etwiki.cn 编辑:admin

编码规范就如同协议,有了Http、TCP等各种协议,计算机之间才能有效地通信,同样的,有了一致的编码规范,程序员之间才能有效地合作。道理大家都懂,可现实中的我们,经常一边吐槽别人的代码,一边写着被吐槽的代码,究其根本,就是缺乏遵从编码规范的意识!多年前,Google发布Google Java Style来定义Java编码时应遵循的规范;今年年初阿里则发布阿里巴巴Java 开发手册,并随后迭代了多个版本,直至9月份又发布了pdf终极版。这两大互联网巨头的初衷,都是希望能够统一标准,使业界编码达到一致性,提升沟通和研发效率,这对于我们码农无疑是很赞的一笔福利呀。笔者将两份规范都通读了一遍,其中列举的不少细则跟平时的编码习惯基本是符合的,不过还是有不少新奇的收获,忍不住记录在此,供日后念念不忘~

Java开发规范总览

一、Google Java Style

Google的java开发规范主要分为6大部分:源文件基本规范、源文件结构、代码格式、命名、编程实践和Javadoc,各部分概要如下:


1、源文件基本规范(source file basics):文件名、文件编码、特殊字符的规范要求
2、源文件结构(source file structure):版权许可信息、package、import、类申明的规约
3、代码格式(formatting):大括号、缩进、换行、列长限制、空格、括号、枚举、数组、switch语句、注4、解、注释、和修饰符等格式要求
5、命名(Naming):标识符、包名、类名、方法名、常量名、非常量成员名、参数名、局部变量的命名规范
6、编程实践(Programming Practices):@override、异常捕获、静态成员、Finalizers等用法规约

二、阿里巴巴Java开发手册

阿里的Java开发手册相对于前者更上一层楼,它除了基本的编程风格的规约外,还给出了日志、单元测试、安全、MySQL、工程结构等代码之外的规约,据说是阿里近万名开发同学集体智慧的结晶,相当了得,还是挺值得借鉴一下的。各部分概要如下:


1、编程规约:命名风格、常量、代码格式、OOP、集合处理、并发、控制语句、注释等
2、异常日志:异常处理、日志的命名、保留时间、输出级别、记录信息等
3、单元测试:AIR原则(Automatic,Independent,Repeatable)、单侧的代码目录、目标,单侧的写法,即BCDE原则(Border,Correct,Design,Error)
4、安全规约:权限校验、数据脱敏、参数有效校验、CSRF安全过滤、防重放限制、风控策略等
5、MySQL数据库:建表、索引、SQL语句、ORM映射等
6、工程结构:应用分层、二方库依赖(坐标命名、接口约定、pom配置)、服务器端各项配置(TCP超时、句柄数、JVM参数等)

熟知的规范

对于大家已经烂熟于心并已习惯遵守的一些编码规范,比如类名、常量的命名、数组的定义、Long类型的字面等,就不在此一一列出了,只想就一些平时编码中较容易个性化,并可能会存在争议的规范进行一番探讨。为了便于说明,用G表示规范出自于Google Java Style,A表示规范出自于阿里巴巴Java开发手册。


[A]IDE的text file encoding设置为UTF-8;IDE中文件的换行符使用Unix格式,不要使用Windows格式([G]文件编码:UTF-8)

看似简单的一个编码约定,在实际开发过程中却经常出现不一致,由于我们是中文操作系统,系统编码是GBK。当两个协作的开发人员IDE,一个采用系统默认编码,一个设置为UTF-8,那么二人看对方写的中文注释就各自都是乱码了,很尴尬。对于“换行符使用Unix格式”,这个在编写shell和hive脚本时踩过好几次坑,而且错误提示很隐晦,一时半会还真察觉不出来,只能说这个规范请务必遵守!


[A]代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。

大多数程序员还是都会遵从英文的命名方式,但在实际工作中还真有遇到过拼音与英文混用的命名,比如创建报文的函数命名为createBaowen,看起来怪怪的,有点不伦不类。


[A]抽象类命名使用Abstract或Base开头;异常类使用Exception结尾;测试类以它要测试的类的名称开始,以Test结尾

以spring源码为例,其抽象类都是以Abstract开头,异常类以Exception结尾,测试类则是以Tests结尾。


[A]POJO类中布尔类型的变量,都不要加is,否则部分框架解析会引起序列化错误。

这个问题一说大家都知道,但实际却是很容易被忽视!因为Boolean通常表达“是”或“否”的意思,可能一遇到布尔变量,大家会习惯性地将它与is关联起来,“很自然”地就会以is开头定义变量。但笔者想说的是,这其实反应了至少两个问题:1、对JavaBean属性命名规范不熟;2、对框架解析POJO的原理不熟,如RPC反向解析、spring MVC参数绑定、MyBatis处理映射等。
private boolean isActive;
//lombok、Eclipse生成getter、setter的结果如下,框架会误把变量解析成active
public boolean isActive() {
return isActive;
}
public void setActive(boolean isActive) {
this.isActive = isActive;
}

在搞清这两个问题前,还是建议老老实实按规范来吧。


包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用单数形式,类名若有复数含义,则可使用复数形式。

实际工作中看到过包名包含下划线的,如org.sherlockyb.user_manage.dao,还是有必要统一一下。


[A]不允许任何魔法值(即未经定义的常量)直接出现在代码中。
反例:String key = “Id#taobao_” + tradeId;
​ cache.put(key, value);

避免硬编码问题是每个程序员都应该具备的基本素养,硬编码所带来的可读性差、维护困难等问题,众所周知。


[A,G]采用空格缩进,禁止使用tab字符。

这是Google和ali一致的规约,只不过前者是一个tab对应2个空格,后者则是4个空格。之所以不提倡tab键,是因为不同的IDE对tab键的“翻译”默认有所差异,容易因不同程序员的个性化而导致同一份代码的格式混乱。


[A,G]单行字符数限制不超过120/100个字符,超出需要换行,换行时遵循如下规则:
1)[A,G]第二行相对于第一行缩进4个空格,从第三行开始,不再继续缩进。
2)[A]运算符或方法调用的点符号与下文一起换行([G]若是非赋值运算符,则在该符号前断开;若是赋值运算符或foreach中的分号,则在该符号后断开)。
4)[A]方法调用时,多个参数,需要换行时,在逗号后进行([G]逗号与前面的内容留在同一行)。
5)在括号前不要换行。

对于单行字符限制,阿里的是120,Google的是100。个人觉得120略长,特别是当用笔记本码代码时,对于超限的代码行,经常要用横向滚动条,不太友好,个人推荐100的限制。


没有必要增加若干空格来使某一行的字符与上一行对应位置的字符对齐。

在变量较多时,这种对齐是一种累赘。虽说有IDE的自动格式化功能,但多人协作时,难保各自的格式化没有差异,会因格式变化而造成不必要的代码行改动,无疑会给你的代码合并徒增困扰。


方法体内的执行语句组、变量的定义语句组、不同的业务逻辑之间或者不同的语义之间插入一个空行。相同业务逻辑和语义之间不需要插入空行。

代码分块就如同文章分段,整洁的代码具有更强的自解释性。


外部正在调用或者二方库依赖的接口,不允许修改方法签名,避免对接口调用方产生影响。作为提供方,接口过时必须加@Deprecated注解,并清晰地说明采用的新接口或者新服务是什么;作为调用方,有义务去考证过时方法的新实现是什么。

接口契约,是使用方和调用方良好协作的有效保障,请务必遵守。


所有的相同类型的包装类对象之间值的比较,全部用equals方法比较。
说明:对于Integer var = ?在-128至127范围内的赋值,Integer对象是在IntegerCache.cache产生,会复用已有对象,这个区间内的Integer值可以直接使用==进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是个大坑,推荐使用equals方法进行判断。

这里补充几点,除了Integer,其他包装类型如Long、Byte等都有各自的cache。这里只提到了等值比较,对于>,<等非等值比较,没必要手动拆箱去比较,包装类型之间直接可以比较大小,亲测有效。例如:

------分隔线----------------------------
标签(Tag):java Java开发规范
------分隔线----------------------------
推荐内容
猜你感兴趣