本文主要讲解阿里JAVA开发手册中比较重要的设计规范,这些重要的设计规范有助于我们改进自己的代码,提升系统的系统的性能。
曾经与一位从阿里出来的Java工程师一起工作过一段时间,他的技术说不上非常厉害,但是,他的代码写的的非常好,凡是他做的功能很少出现Bug。我就很好奇,于是经常向他请教一些代码设计的原则,然后他告诉了我阿里Java手册。并且,他将这个手册进行了修改,也成为了我司Java程序员的开发手册。这篇文章就让我们看一看这个手册中比较重要的原则。
代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束。
反例:_name/__name/$name/name_/name$/name__
类型与中括号紧挨相连来表示数组。
正例:定义整形数组int[]arrayDemo;反例:在main参数中,使用Stringargs[]来定义。
POJO类中布尔类型变量都不要加is前缀,否则部分框架解析会引起序列化错误。
说明:表达是与否的值采用is_xxx的命名方式,所以,需要在设置从is_xxx到xxx的映射关系。
反例:定义为基本数据类型BooleanisDeleted的属性,它的方法也是isDeleted(),RPC框架在反向解析的时候,“误以为”对应的属性名称是deleted,导致属性获取不到,进而抛出异常。
在常量与变量的命名时,表示类型的名词放在词尾,以提升辨识度。
正例:startTime/workQueue/nameList/TERMINATED_THREAD_COUNT
反例:startedAt/QueueOfWork/listName/COUNT_TERMINATED_THREAD
接口类中的方法和属性不要加任何修饰符号(public也不要加),保持代码的简洁性,并加上有效的Javadoc注释。尽量不要在接口里定义变量,假如一定要定义变量,肯定是与接口方法相关,并且是整个应用的基础常量。
正例:接口方法签名voidcommit();
接口基础常量StringCOMPANY="alibaba";
反例:接口方法定义publicabstractvoidf();
说明:JDK8中接口答应有默认实现,那么这个default方法,是对所有实现类都有价值的默认实现。
枚举类名带上Enum后缀,枚举成员名称需要全大写,单词间用下划线隔开。
说明:枚举其实就是尤其的类,域成员均为常量,且构造方法被默认强制是私有。
正例:枚举名字为ProcessStatusEnum的成员名称:SUCCESS/UNKNOWN_REASON。
各层命名规约:
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。
不答应任何魔法值(即未经预先定义的常量)直接出现在代码中。
反例:Stringkey="Id#taobao_"+tradeId;
cache.put(key,value);
cache.put(key,value);
避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可。
相同参数类型,相同业务含义,才可以使用Java的可变参数,避免使用Object。
说明:可变参数必须放置在参数列表的很后。(提倡同学们尽量不用可变参数编程)
正例:publicListlistUsers(Stringtype,Long...ids){...}
所有整型包装类对象之间值的比较,全部使用equals方法比较。
说明:对于Integervar=?在-128至127范围内的赋值,Integer对象是在IntegerCache.cache产生,会复用已有对象,这个区间内的Integer值可以直接使用==进行判定,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用equals方法进行判定。
关于基本数据类型与包装数据类型的使用标准如下:
1)【强制】所有的POJO类属性必须使用包装数据类型。
2)【强制】RPC方法的返回值和参数必须使用包装数据类型。3)【推荐】所有的局部变量使用基本数据类型。
说明:POJO类属性没有初值是提醒使用者在需要使用时,必须自己显式地进行赋值,任何NPE问题,或者入库检查,都由使用者来保证。
正例:数据库的查询结果可能是null,因为自动拆箱,用基本数据类型接收有NPE风险。
反例:比如显示成交总额涨跌情况,即正负x%,x为基本数据类型,调用的RPC服务,调用不成功时,返回的是默认值,页面显示为0%,这是不合理的,应该显示成中划线。所以包装数据类型的null值,能够表示额外的信息,如:远程调用失败,异常退出。
POJO类必须写toString方法。
使用IDE中的工具:source>generatetoString时,假如继续了另一个POJO类,注重在前面加一下super.toString。
说明:在方法执行抛出异常时,可以直接调用POJO的toString()方法打印其属性值,便于排查问题。
关于hashCode和equals的处理,遵循如下规则:
1)只要覆写equals,就必须覆写hashCode。
2)因为Set存储的是不重复的对象,依据hashCode和equals进行判定,所以Set存储的对象必须覆写这两个方法。
3)假如自定义对象作为Map的键,那么必须覆写hashCode和equals。
说明:String已覆写hashCode和equals方法,所以我们可以愉快地使用String对象作为key来使用。
线程资源必须通过线程池提供,不答应在应用中自行显式创建线程。
说明:线程池的好处是减少在创建和销毁线程上所消耗的时间以及系统资源的开销,解决资源不足的问题。假如不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者“过度切换”的问题。
线程池不答应使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
以上规范在设计代码中,是比较重要的原则。假如编写代码的过程中,可以依照以上原则,那代码的可读性和可维护性将大大提升
下一篇:淘宝直播吸引粉丝的途径
文章地址:https://www.tianxianmao.com/article/online/6557.html