编程规约(上) -- 阿里巴巴Java开发手册

没有标注 "推荐" 等字样的, 为强制标准.

加粗的为不熟悉的.

一.命名风格

1-1.代码中的命名均不能以下划线或美元符号开始或结束

String _name, $name; // not

1-2.严禁使用拼音和英文混合,不能使用中文, 国际通用的名称,可视同英文

String getPingfenByName; //not

1-3.类名使用驼峰命名,首字母大写,DO / BO / DTO / VO / AO / PO /UID 等除外

1-4.方法名,参数名,变量都采用 lowerCanelCase 风格

1-5.常量命名全部大写,单词间用下划线隔开.不要嫌名字长,语意表达完整

String MAX_STOCK_COUNT;

1-6.抽象类名使用 Abstract 或 Base 开头,异常类名使用 Exception 结尾,测试类名以它要测试的类名开始 ,Test 结尾。

1-7.表示数组, 类型[] 变量名;

int[] arrayDemo;  //yes
int arrayDemo1[]; //not

1-8.POJO类中布尔类型的变量,都不要加 is 前缀,否则部分框架解析会引起序列化错误.

Boolean isDelete; //not

1-9.包名统一使用小写,点分隔符之间有且仅有一个自然语义的单词;包名统一使用单数形式,类名可以使用复数形式。

1-10.杜绝不规范的缩写导致望文不知义 Condition --> condi

 

推荐:

1-11.任何自定义编程元素在命名时尽量使用完整的单词组合来表达, 反例 int a;

1-12.如果模块,接口,类,方法使用了设计模式,在命名时需体现出具体模式。

  例如:OrderFactory,LoginProxy, ResourceObserver

1-13.接口类中的方法和属性不要加任何的修饰符号(public也不加),并加上有效的JavaDoc注释。

  尽量不要在接口里定义变量,如果要,肯定是与接口方法相关,,并且是整个应用的基础常量。

  JDK8 default方法,是对所有实现类都有价值的默认实现

1-14.接口和实现类的命名有两套规则

  1) 对于 Service 和  DAO类, 基于 SOA的理念,暴露出来的服务一定是接口,内部的实现类用 Impl 后缀区分

  2) (推荐) 如果是形容能力的接口名称,取对应的形容词为接口名( -able 形式)

 

参考:

1-15.枚举类建议带上Enum后缀, 枚举成员名称需要全大写,单词间用下划线隔开。

  枚举类就是特殊的类,域成员均为常量,且构造方法被默认强制是私有。

  例如:枚举名为 ProcessStatusEnum , 成员名 SUCCESS / UNKNOWN_REASON

1-16.各层命名规约:

  A)Service/DAO 层方法命名规约

    1) 获取单个对象的方法用 get 做前缀。
    2) 获取多个对象的方法用 list 做前缀,复数形式结尾如:listObjects。
    3) 获取统计值的方法用 count 做前缀。
    4) 插入的方法用 save/insert 做前缀。
    5) 删除的方法用 remove/delete 做前缀。
    6) 修改的方法用 update 做前缀。

  B)领域模型命名规约

    1) 数据对象:xxxDO,xxx 即为数据表名。
    2) 数据传输对象:xxxDTO,xxx 为业务领域相关的名称。
    3) 展示对象:xxxVO,xxx 一般为网页名称。
    4) POJO 是 DO/DTO/BO/VO 的统称,禁止命名成 xxxPOJO。

 

二.常量定义

2-1.不允许使用任何魔法值(即未经预先定义的常量) 直接出现在代码中.

  例如: int priceTable[] = new int[16]; //ERROR:这个16究竟有何含义呢?

2-2.在使用Long或者long赋值时, 数值后使用大写的L


推荐:

2-3.不要使用一个常量类维护所有常量,要按照常量功能进行归类.

2-4.常量的复用层次有五层: 跨应用共享,应用内共享,子工程内共享,包内共享,类内共享

  1) 跨应用: 放置在二方库中,通常是 client.jar 中的 constant 目录下
  2) 应用内: 放置在一方库中,通常是子模块中的 constant 目录下
  3) 子工程内: 即在当前子工程的 constant 目录下
  4) 包内: 即在当前包下单独的constant目录下
  5) 类内: 直接在类内部 private static final 定义.

2-5.如果变量值仅在一个固定范围内变化,用enum类型来定义

 

三.代码格式

3-1.大括号的使用约定,大括号内为空,写成 { } 即可. 非空写成以下格式

public void method() { //1.左大括号前不换行,后换行. 2.左大括号前需要空格

}//右大括号前换行,后还有else则不换行,表示中止的右大括号必须换行

3-2.小括号和字符之间不出现空格

if ( a==b ) //not

3-3.if /for /while /switch /do 等保留字与括号之间都必须加空格

3-4.任何二目,三目运算符的左右两边都需要一个空格.

3-5.采用4个空格缩进,禁止使用tab字符

说明:如果使用 tab 缩进,必须设置 1 个 tab 为 4 个空格。IDEA 设置 tab 为 4 个空格时,
   请勿勾选 Use tab character;而在 eclipse 中,必须勾选 insert spaces for tabs。

//正例 (1-5)
public static void main(String[] args) { 
    // 缩进 4 个空格 
    String say = "hello"; 
    // 运算符的左右必须有一个空格 
    int flag = 0; 
    // 关键词 if 与括号之间必须有一个空格,括号内的 f 与左括号,0 与右括号不需要空格 
    if (flag == 0) {
        System.out.println(say); 
    } 

    // 左大括号前加空格且不换行;左大括号后换行
    if (flag == 1) { 
        System.out.println("world"); 
       // 右大括号前换行,右大括号后有 else,不用换行 
    } else {
        System.out.println("ok"); 
        // 在右大括号后直接结束,则必须换行 
    } 
}

 

3-6.注释的双斜线与注释内容之间有且仅有一个空格

3-7.单行字符数限制不超过120个, 超出换行, 换行原则 :

  1) 第二行相对第一行缩进4空格,第三行开始不再缩进
  2) 运算符与下文一起换行
  3) 方法调用点符号与下文一起换行
  4) 方法调用中的参数需要换行时,在逗号后进行
  5) 在括号前不要换行,逗号前不要换行

3-8.方法参数在定义和传入时,多个参数逗号后必须加空格

3-9.IDE的 test file encoding 设置为 UTF-8; IDE 中文件的换行符使用 Unix格式, 不要使用windows格式.

 

推荐 :

3-10.单个方法的总行数不超过80行,包括注释,大括号,空行等.

代码逻辑分清红花和绿叶,个性和共性,
绿叶逻辑单独出来成为额外方法,使主干代码更加清晰.
共性逻辑抽取成共性方法,便于维护和复用.

3-12.不同逻辑,不同语义,不同业务的代码之间插入一个空行分隔开来以提升可读性. 不必插入多个空行.

 

四.OOP规约

4-1.不要使用一个类的对象引用访问此类的静态变量或静态方法, 无畏增加编译器解析成本.

4-2.所有的覆写方法,必须加@Override 注解

4-3.相同参数类型,业务含义,才可以使用可变参数,避免使用Object. (提倡尽量不使用可变参数编程)

4-4.外部正在调用或者二方库依赖的接口, 不允许修改方法签名.
   接口过时必须加 @Deprecated 注解,并清晰的说明采用的新接口或者新服务是什么

4-5.不能使用过时的类或方法.

4-6.equals方法,应使用常量或确定有值的对象来调用. 推荐使用 java.util.Objects#equals (JDK7引入的工具类)

4-7.所有的相同类型的包装类对象之间值的比较,全部用equals方法比较. 包装类:Integer等

4-8.关于基本数据类型与包装数据类型的使用标准如下:
  1) 所有的POJO类属性必须使用包装数据类型
  2) RPC方法的返回值和参数必须使用包装数据类型
  3) (推荐) 所有的局部变量使用基本数据类型

4-9.定义DO/DTO/VO 等POJO类时, 不要设定任何属性默认值

4-10.序列化类新增属性时,请不要修改 serialVersionUID 字段,避免反序列失败.

4-11.构造方法里面禁止加入任何业务逻辑, 如果有初始化逻辑,请放在 init 方法中.

4-12.POJO类必须写 toString 方法.如果继承了另一个POJO ,注意在前面加一下 super.toString

4-13.禁止在POJO类中,同时存在对应属性的 isXxx() 和 getXxx() 方法.

说明:框架在调用属性Xxx的提取方法时,不确定哪个方法被优先调用到

 

推荐:

4-14.使用索引访问用String split 方法得到的数组时,需做最后一个分隔符后有无内容的检查.    

String str = "a,b,c,,";
String[] ary = str.split(",");
System.out.println(ary.length); //3

4-15.当一个类有多个构造方法,或者多个同名方法,这些方法应该按顺序放置在一起,便于阅读.优先于16条规则.

4-16.类内方法定义的顺序依次是: 公有方法或保护方法 >私有方法 >getter/setter 方法.

4-17.setter方法中,参数名称与类成员变量名称一致,不要在方法中增加业务逻辑,增加排查问题的难度.

4-18.循环体内,字符串的连接方式,使用StringBuilder 的 append 方法进行扩展.

4-19.final 可以声明类,成员变量,方法,以及本地变量.
  1) 不允许被继承的类
  2) 不允许修改引用的域对象
  3) 不允许被重写的方法,例如 setter 方法
  4) 不允许运行过程中重新赋值的局部变量
  5) 避免上下文重复使用一个变量,使用final描述可以强制重新定义一个变量,方便更好的进行重构.  ??

4-20.慎用Object的clone方法来拷贝对象(浅拷贝),若要实现深拷贝需要重写clone方法实现域对象的深度遍历式拷贝

4-21.类成员与方法访问控制从严 :
  1) 如果不允许直接通过new来创建对象, 构造方法必须私有
  2) 工具类不允许有public 或 default构造方法
  3) 类中非static成员变量并且与子类共享,必须是protected
  4) 类中非static成员变量并且仅在本类使用,必须是private
  5) 类中static成员变如果仅在本类使用,必须是private
  6) 若是static成员变量,考虑是否为final
  7) 类成员方法只供内部调用,必须是private
  8) 类成员方法只对继承类公开,那么限制为protected

说明: 任何类、方法、参数、变量,严控访问范围。过于宽泛的访问范围,不利于模块解耦。
思考:如果是一个 private 的方法,想删除就删除,可是一个 public 的 service 成员方法或 成员变量,删除一下,不得手心冒点汗吗? 

 

posted @ 2018-07-09 14:00  污力豆豆  阅读(405)  评论(0编辑  收藏  举报