《阿里巴巴 Java 开发手册》是阿里巴巴集团技术团队的集体智慧结晶和经验总结,经历了多次大规模一线实战的检验及不断完善,系统化地整理成册,回馈给广大开发者。
本手册的旨在码出高效,码出质量。现代软件架构的复杂性需要协同开发完成,如何高效地协同呢?无规矩不成方圆,无规范难以协同代码的字里行间流淌的是软件系统的血液,质量的提升是尽可能少踩坑,杜绝踩重复的坑,切实提升系统稳定性,码出质量。
阿里巴巴编码规范基础认证的考试要点90%来源于这本开发手册中的内容,目前此手册的最新版本为1.4.0的PDF(详尽版),此版本已为非常详尽的版本,在上一个版本的基础上新增了设计规约大章节,并增加了若干条目。根据手册规约中的内容阿里在2017杭州云栖大会上发布了Java开发规约插件,插件同时支持Intelli IDEA和Eclipse,文后我会简单介绍下这个插件的安装及使用。
我在2018-08-21的晚上通过阿里云大学在线考试通过了这个认证,考试包含50道选择题,分为多选和单选,每次考试题目内容是随机生成的,主要是多选题居多,每次考试单选题目数量也是随机的,但不会超过10道单选,考试时间90分钟,说来惭愧,我第一次考试的时候没有通过,做的比较快,45分钟我就做完了,也没检查直接交卷了,结果考了78分,差2分。。。
如果你关注阿里云在招的Java工程师职位,你会发现岗位说明中有这样的字样“通过阿里巴巴编码规范认证的同学优先录取”,足以看出这份认证考试还是有些许价值的。
那么接下来我将聊聊《阿里巴巴Java开发手册》(文后简称“手册”)读后感以及认证考试的主要考试要点,最后再简单写下插件的安装和使用。
手册读后感
正如阿里官方说明的一样,这是一本由阿里近万名Java开发精英工程师通过大规模一线实战的经验总结而来的,读后确实觉得写的很实用,有些地方可以说是闭坑指南,从书的首屏图样来说这本书是要做领头雁的意思。
本手册以 Java 开发者为中心视角,划分为编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约七个维度,再根据内容特征,细分成若干二级子目录。根据约束力强弱及故障 敏感性,规约依次分为强制、推荐、参考三大类。对于规约条目的延伸信息中,“说明”对规约做了适当扩展和解释;“正例”提倡什么样的编码和实现方式;“反例” 说明需要提防的雷区,以及真实的错误案例。
这是一本关于Java开发规范方面的中文原版说明书,当然有些内容它也遵循了Oracle Sun规范,如编程规约中类名使用UpperCamelCase风格。方法名、参数名、成员变量、局部变量都统一使用lowerCamelCase风格,必须遵从驼峰形式。
讲编码规范的说明书并不是要求我们程序员去死记硬背这些条条框框,我们应该去发掘在这些条条框框之后隐藏的真理是什么?如“为什么我们要去遵循这些规范,为什么要制定这样的规则,使用这样的规则有什么好处,它会限制我们代码内容的创造性吗?”。我觉得带着这些问题去阅读本书,理解这些规范和标准才是正确的打开方式。为了不让本章节拖的太长,我将挑选手册中重要的几个规范点来说下我个人的见解和补充。
(1)编程规约中POJO概念
POJO(Plain Ordinary Java Object): 在本手册中,POJO 专指只有 setter / getter / toString的简单类,包括DO/DTO/BO/VO等。
- DO(Data Object):此对象与数据库表结构一一对应,通过 DAO 层向上传输数据源对象。
- DTO(Data Transfer Object):数据传输对象,Service 或 Manager 向外传输的对象。
- BO(Business Object):业务对象,由 Service 层输出的封装业务逻辑的对象。
- AO(ApplicationObject):应用对象,在Web层与Service层之间抽象的复用对象模型, 极为贴近展示层,复用度不高。
- VO(View Object):显示层对象,通常是 Web 向模板渲染引擎层传输的对象。
我们在实际简单的项目中,可能不会将实体像上面分的那么细,多数命名会直接末尾加POJO或Entity或Model,这对于软件架构不是很复杂,对性能要求也不高的小型后台管理类系统来说,确实已经够了。但对于复杂的,且对性能要求高的项目,就有必要分这么细了,举个例子,一般复杂的项目,开发团队都是10人以上,团队按组划分,各组负责软件架构中不同的应用层级,各层级之间肯定要定义接口,那么数据传输的实体就不能一概而就了,必须分层规范定义;再举个例子,很多时候一个DO实体对应在数据库中表的字段有10多个,但是在页面中需要显示的只需要3-5个,多余的数据会导致传输速度下降,所以需要新建VO对象去进行页面显示,只取需要展示的数据;还有诸如一个用户实体,密码不应该在查询的时候返回给用户,用户编号也不是用户想看到的,用户想看到的只是用户昵称,这时我们必然需要通过BO或者DTO层进行过滤和转义,最终新建Vo对象用于界面展示。
【强制】POJO类中布尔类型的变量,都不要加 is 前缀,否则部分框架解析会引起序列化错误
这一条我也是感触挺深的,这个是真细节,在我还是个菜鸟的时候,我也遇到过 boolean isSuccess的错误,debug调试的时候明明这个值是有值的且为true,怎么传递到前台来了之后就变成了无值默认false呢,千万千万不要这样命名。
(2)格式规范
这里我主要讲一点,代码缩进的时候到底是敲空格键还是tab键,我习惯敲tab,所以我在IDE中设置了一个tab使用4个空格来代替,因为敲空格容易敲错。
(3)集合处理
- foreach中不要进行remove和add操作,remove元素请使用 Iterator方式,如果并发操作,需要对 Iterator 对象加锁。
-
下面这张表格是重点(考试必考,敲黑板,可以记一下)
(4)并发处理
【强制】线程池不允许使用 Executors 去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
说明:Executors 返回的线程池对象的弊端如下:
1)FixedThreadPool 和 SingleThreadPool:
允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
2)CachedThreadPool 和 ScheduledThreadPool:
允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。
对于FixedThreadPool这个线程池,我也是掉过坑里,由于系统在一个特殊时期内业务请求量翻了好几番,当前线程池设定的最大线程数不足,工作线程处理任务的速度大大低于请求任务的新增速度,这会导致请求队列深度无限扩大,内存使用量直线攀升,最终造成频繁FullGC,这样又导致工作线程处理任务的速度进一步变慢,形成死链,最后OOM服务端进程崩溃了。。。
(5)索引规约
【强制】业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。
说明:不要以为唯一索引影响了 insert 速度,这个速度损耗可以忽略,但提高查找速度是明 显的;另外,即使在应用层做了非常完善的校验控制,只要没有唯一索引,根据墨菲定律,必然有脏数据产生。
这一点我也是非常赞同,在生产项目实际运行过程中见到太多这样的脏数据导致被业务或者客户投诉吐槽(怎么我只操作了一次,你们系统记录了2遍,系这也太坑了吧。。。)所以这条规范排在了NO.1。
还有很多痛点和闭坑指南,这里就不一一举例了,我相信每个有经验的Java开发人员看完这本手册都会在其中找到自己曾经的痛点影子,这是一本可以给自己查漏补缺的好书。
认证考试要点
绝大部分的考题涉及到的知识点都能在《阿里巴巴JAVA开发手册》上找到,这些都是比较基础的考点,这里就不说明了,我主要讲一些只在书上稍微提及却又在考试中扩展延伸的考点。
JAVA:
1.考点:集合处理这个章节,特别是数组与集合相互转换,涉及考题较多。
subList 返回的是 ArrayList 的内部类 SubList,并不是 ArrayList ,而是 ArrayList 的一个视图,对于SubList子列表的所有操作最终会反映到原列表上(在sublist中添加/删除元素,不只影响sublist本身,同时会影响原ArrayList)。
在subList场景中,高度注意对原集合元素个数的修改,会导致子列表的遍历、增加、删除均会产生ConcurrentModificationException 异常(切记,这个场景是不被允许的,不要和上一点记混淆)
sublist没有实现序列化,查看源码就可以发现其没有实现Serializable接口,这点必须注意,在大多数写入缓存容器、RPC调用等场景需要做一些调整。
特别是最后一条,手册中并未提及,但是我遇到的多选题,其中有一个选项就是:subList不能作为RPC接口方法的返回结果,因为其没有实现序列化,第一次考试的时候我没有选这个选项,要是选了就一次过了(苦笑)
2.考点:所有的相同类型的包装类对象之间值的比较,全部使用equals方法比较。
对于Integer var = ? 在-128至127范围内的赋值,Integer对象是在IntegerCache.cache产生,会复用已有对象,这个区间内的Integer值可以直接使用==进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用equals方法进行判断
这点在很多书上都有提及,特别重要,这里说下我遇到的题目
代码:
Integer var1 = 20;
Integer var2 = 20;
Integer var3 = 259;
Integer var4 = 259;
题目选项是让你选择 var1 == var2 的值为true还是false,var3 == var4的值为true还是false。
数据库考点:
数据库题目考试的比重还是比较大的,最主要的是sql索引规范,然后就是SQL语句,ORM规范。
1.考点:NULL与任何值比较的结果都为NULL。~记住这点很重要。
2.考点:Mysql涉及的索引从数据结构角度来看涉及到 B-Tree、Hash、R-Tree、Full-text,从物理存储角度,聚集索引(clustered)、非聚集索引(non-clustered)。
在MySQL中,InnoDB引擎表是(聚集)索引组织表(clustered index organize table),而MyISAM引擎表则是堆组织表(heap organize table)。
InnoDB的数据文件本身就是索引文件,B+Tree的叶子节点上的data就是数据本身,key为主键,这是聚簇索引。非聚簇索引,叶子节点上的data是主键(所以聚簇索引的key,不能过长)。为什么存放的主键,而不是记录所在地址呢,理由相当简单,因为记录所在地址并不能保证一定不会变,但主键可以保证。
3.考点:索引规约中相关的点,考到的题比较多,比如索引中有范围查找,那么索引有序性无法利用,如:WHERE a>10 ORDER BY b; 索引a_b无法排序。又比如页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决索引文件具有 B-Tree 的最左前缀匹配特性,如果左边的值未确定,那么无法使用此索引。
4.考点:iBATIS自带的queryForList(String statementName,int start,int size)不推荐使用,存在性能风险。
说明:其实现方式是在数据库取到 statementName 对应的 SQL 语句的所有记录,再通过 subList 取 start,size 的子集合
5.考点:利用延迟关联或者子查询优化超多分页场景
说明:MySQL 并不是跳过 offset 行,而是取 offset+N 行,然后返回放弃前 offset 行,返回 N 行,那当 offset 特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过 特定阈值的页数进行 SQL 改写。
6.考点:在代码中写分页查询逻辑时,若 count 为 0 应直接返回,避免执行后面的分页语句
日志:
1.考点:应用中不可直接使用日志系统(Log4j、Logback)中的API,而应依赖使用日志框架SLF4J中的API,使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。
平时常用的日志适配框架是SLF4J,这里重点提一下JCL(Jakarta Commons Logging),题目中出现的,后来查询了资源它也是一种日志适配框架,考试的时候猜测应该是类似于SLF4J的东西,也选了这个,蒙对了。。。用这些日志框架的好处是降低与具体日志框架的耦合,可以灵活改变使用的具体日志框架。
单元测试:
1.考点:编写单元测试代码遵守 BCDE 原则,以保证被测试模块的交付质量。
B:Border,边界值测试,包括循环边界、特殊取值、特殊时间点、数据顺序等。
C:Correct,正确的输入,并得到预期的结果。
D:Design,与设计文档相结合,来编写单元测试。
E:Error,强制错误信息输入(如:非法数据、异常流程、非业务允许输入等),并得 到预期的结果。
这里考试的时候我遇到的是BCDE解释故意混淆,如E:Equal,保证单元测试的运行生产环境和测试环境完全一样(这怎么可能呢,完全一样了还有测试环境这个称呼吗,呵呵。。。)
2.考点:白盒测试中的代码覆盖率相关概念,语句覆盖、分支覆盖(判定覆盖)、条件覆盖、路径覆盖。
语句覆盖是最弱的一种度量方式,即使是路径覆盖也不能保证程序完全没问题。这些相关概念还是看下专业的书籍或者博客等资料,在这里就不多描述了。
网络:
1.考点:高并发服务器建议调小TCP协议的time_wait超时时间。
重点需要理解tcp协议,三次握手、四次挥手相关概念及状态转换。
阿里巴巴Java开发规约插件安装及使用
因为我目前使用IDEA开发,这里只简单介绍下在IntelliJ IDEA下的安装及使用,Eclipse的同学可以通过GitHub链接传送门了解:
ailibaba/p3c/Eclipse-plugin
IDEA插件安装
从插件资源库中安装
1.Settings >> Plugins >> Browse repositories...
-
通过关键字'alibaba'搜索插件,然后安装'Alibaba Java Coding Guidelines' plugin
- 重启IDEA即可生效
当然也可以下载插件的zip file 通过本地导入的方式安装,这里就不说了。
使用
1.语言切换,支持中文和英文两种语言可选
2.自定义检查设定,可以根据自己公司,自身项目团队的实际情况自定义勾选插件需要检查的规约内容
3.项目代码分析 Code Analyze
我的一个项目使用标准的检查定义分析之后:
这个插件做的非常简单,也很轻量,设计者秉承的是开箱即用的设计理念。
写在最后
最后我给大家总结一下以上你将会用到的资源吧,方便大家今后进入。
点击下载《阿里巴巴Java开发手册》v1.4.0(最新详尽版):
https://yq.aliyun.com/attachment/download/?id=5585
编码规范考试认证:
https://edu.aliyun.com/certification/cldt02
IDE插件下载:
https://github.com/alibaba/p3c
完