重读阿里巴巴java开发手册——记录与自我理解

前言

博主本周花了三天的时间,重读了阿里巴巴的java开发手册,里面遗漏的一些点,以及一些自我解读,现在在此进行记录。

内容

一、编程规约

(四)OOP规约

13.【强制】禁止在POJO类中,同时存在对应属性xxx的isXxx()和getXxx()方法。
14.【推荐】使用索引访问用String的split方法得到的数组时,需做最后一个分隔符后有无内容的检查,否则会有抛IndexOutOfBoundsException的风险。
17.【推荐】setter方法中,参数名称与类成员变量名称一致,this.成员名=参数名。在getter/setter方法中,不要增加业务逻辑,增加排查问题的难度

(五)集合处理

2.【强制】ArrayList的subList结果不可强转成ArrayList,否则会抛出ClassCastException异常,即java.util.RandomAccessSubListcannotbecasttojava.util.ArrayList。说明:subList返回的是ArrayList的内部类SubList,并不是ArrayList而是ArrayList的一个视图,对于SubList子列表的所有操作最终会反映到原列表上。
3.【强制】在subList场景中,高度注意对原集合元素的增加或删除,均会导致子列表的遍历、增加、删除产生ConcurrentModificationException异常
7.【强制】不要在foreach循环里进行元素的remove/add操作。remove元素请使用Iterator方式,如果并发操作,需要对Iterator对象加锁。
11.【推荐】使用entrySet遍历Map类集合KV,而不是keySet方式进行遍历。说明:keySet其实是遍历了2次,一次是转为Iterator对象,另一次是从hashMap中取出key所对应的value。而entrySet只是遍历了一次就把key和value都放到了entry中,效率更高。如果是JDK8,使用Map.foreach方法。正例:values()返回的是V值集合,是一个list集合对象;keySet()返回的是K值集合,是一个Set集合对象;entrySet()返回的是K-V值组合集合。

Map tt = new HashMap<>();
        tt.put("1","t1");
        tt.put("2","t2");
        tt.forEach((k,v)->System.out.println("key:"+k+",value:"+v));
(六)集合处理

5.【强制】
如果是JDK8的应用,可以使用instant代替Date,Localdatetime代替Calendar,Datetimeformatter代替Simpledateformatter,官方给出的解释:simple beautiful strong immutable thread-safe

它使用的是datetime,不知道为什么不使用timestamp,二者的异同点,参考网址:
https://blog.csdn.net/qq_28483283/article/details/81873054

二、异常日志

(一)异常处理

2.【强制】异常不要用来做流程控制,条件控制。说明:异常设计的初衷是解决程序运行中的各种意外情况,且异常的处理效率比条件判断方式要低很多。
7.【强制】不要在finally块中使用return。说明:finally块中的return返回后方法结束执行,不会再执行try块中的return语句。

五、MySQL数据库

(一)建表规约

1.【强制】表达是与否概念的字段,必须使用is_xxx的方式命名,数据类型是unsigned tinyint(1表示是,0表示否)。说明:任何字段如果为非负数,必须是unsigned。
5.【强制】主键索引名为pk_字段名;唯一索引名为uk_字段名;普通索引名则为idx_字段名。说明:pk_ 即primary key;uk_ 即uniquekey;idx_ 即index的简称。
6.【强制】小数类型为decimal,禁止使用float和double。说明:float和double在存储的时候,存在精度损失的问题,很可能在值的比较时,得到不正确的结果。如果存储的数据范围超过decimal的范围,建议将数据拆成整数和小数分开存储。
9.【强制】表必备三字段:id, gmt_create, gmt_modified。说明:其中id必为主键,类型为bigintunsigned、单表时自增、步长为1。gmt_create, gmt_modified的类型均为datetime类型,前者现在时表示主动创建,后者过去分词表示被动更新。

(三)SQL语句

1.【强制】不要使用count(列名)或count(常量)来替代count(),count()是SQL92定义的标准统计行数的语法,跟数据库无关,跟NULL和非NULL无关。说明:count(*)会统计值为NULL的行,而count(列名)不会统计此列为NULL值的行。
3.【强制】当某一列的值全是NULL时,count(col)的返回结果为0,但sum(col)的返回结果为NULL,因此使用sum()时需注意NPE问题。正例:可以使用如下方式来避免sum的NPE问题:SELECTIF(ISNULL(SUM(g)),0,SUM(g))FROMtable;
4.【强制】使用ISNULL()来判断是否为NULL值。
说明:NULL与任何值的直接比较都为NULL。

  • 1)NULL<>NULL的返回结果是NULL,而不是false。
  • 2)NULL=NULL的返回结果是NULL,而不是true。
  • 3)NULL<>1的返回结果是NULL,而不是true。

7.【强制】禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。
9.【推荐】in操作能避免则避免,若实在避免不了,需要仔细评估in后边的集合元素数量,控制在1000个之内。
10.【参考】如果有国际化需要,所有的字符存储与表示,均以utf-8编码,注意字符统计函数的区别。
说明:

  • SELECTLENGTH("轻松工作"); 返回为12
  • SELECTCHARACTER_LENGTH("轻松工作"); 返回为4
  • 如果需要存储表情,那么选择utf8mb4来进行存储,注意它与utf-8编码的区别。
(四)ORM映射

1.【强制】在表查询中,一律不要使用* 作为查询的字段列表,需要哪些字段必须明确写明。说明:1)增加查询分析器解析成本。2)增减字段容易与resultMap配置不一致。3)无用字段增加网络消耗,尤其是text类型的字段
2.【强制】POJO类的布尔属性不能加is,而数据库字段必须加is_,要求在resultMap中进行字段与属性之间的映射。
4.【强制】sql.xml配置参数使用:#{},#param# 不要使用 ${} 此种方式容易出现SQL注入。
5.【强制】iBATIS自带的queryForList(StringstatementName,intstart,intsize)不推荐使用。
6.【强制】不允许直接拿HashMap与Hashtable作为查询结果集的输出。
9.【参考】@Transactional事务不要滥用。事务会影响数据库的QPS,另外使用事务的地方需要考虑各方面的回滚方案,包括缓存回滚、搜索引擎回滚、消息补偿、统计修正等

六、工程结构

(二)二方库依赖

1.【强制】定义GAV遵从以下规则:

  • 1)GroupID格式:com.{公司/BU}.业务线[.子业务线],最多4级。
    说明:{公司/BU} 例如:alibaba/taobao/tmall/aliexpress等BU一级;子业务线可选。
    正例:com.taobao.jstorm或com.alibaba.dubbo.register
  • 2)ArtifactID格式:产品线名-模块名。语义不重复不遗漏,先到中央仓库去查证一下。
    正例:dubbo-client/ fastjson-api/ jstorm-tool
  • 3)Version:详细规定参考下方。

2.【强制】二方库版本号命名方式:主版本号.次版本号.修订号

  • 1)主版本号:产品方向改变,或者大规模API不兼容,或者架构不兼容升级。
  • 2)次版本号:保持相对兼容性,增加主要功能特性,影响范围极小的API不兼容修改。
  • 3)修订号:保持完全兼容性,修复BUG、新增次要功能特性等。
    说明:注意起始版本号必须为:1.0.0,而不是0.0.1正式发布的类库必须先去中央仓库进行查证,使版本号有延续性,正式版本号不允许覆盖升级。如当前版本:1.3.3,那么下一个合理的版本号:1.3.4 或1.4.0 或2.0.0

3.【强制】线上应用不要依赖SNAPSHOT版本(安全包除外)。说明:不依赖SNAPSHOT版本是保证应用发布的幂等性。另外,也可以加快编译时的打包构建
6.【强制】依赖于一个二方库群时,必须定义一个统一的版本变量,避免版本号不一致。说明:依赖springframework-core,-context,-beans,它们都是同一个版本,可以定义一个变量来保存版本:${spring.version},定义依赖的时候,引用该版本。
8.【推荐】所有pom文件中的依赖声明放在语句块中,所有版本仲裁放在语句块中。说明:里只是声明版本,并不实现引入,因此子项目需要显式的声明依赖,version和scope都读取自父pom。而所有声明在主pom的里的依赖都会自动引入,并默认被所有的子项目继承

你可能感兴趣的:(重读阿里巴巴java开发手册——记录与自我理解)