阿里开发手册摘要
阿里作为全世界Java开发规模最大和应用水平最高的地方之一,三十几页的规范,从编程、异常日志、SQL、工程、安全五块形成的规约总结,根据约束力,分强制、推荐、参考三大类,可以作为优秀技术团队的重要利器。
官方文档地址:https://yq.aliyun.com/articles/69327?utm_content=m_10088
以下是阅读阿里开发手册中,记录的一些重要摘要信息。
编程规范
命名
- 尽量语义清晰、望名知义
- 遵从驼峰形式
- 如果使用到了设计模式,类名体现具体模式
常量定义
- 值定义不要出现未定义的常量
- 常量类推荐也分类定义常量类,不要大而全的一个常量类
- 变量值在一定范围,使用Enum类
格式规约
- 单行限制不超过120个字符
看注释内容,示例代码:
1 | public static void main(String[] args) { |
OOP规约
- overwrite方法,必须有@overwrite注解
- 静态方法和变量,直接通过类名访问,禁止对象访问,增加无谓的编译器解释成本
- 不能使用过时的类或方法
- 包装类之间的值比较,使用equals方法
- 构造方法禁止加入任何业务逻辑,请放在init方法中
- String的split方法,做分隔符后无内容的检测
- 类方法定义的顺序,公有方法或保护方法 > 私有方法 > getter/setter方法
- getter/setter方法尽量不要加入任何业务逻辑,增加排查问题的难度
- 推荐使用StringBuilder的append方法替换string拼接
集合处理
并发处理
- 线程定义名称
- 使用线程池,使用ThreadPoolExecutor
- 高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁。
- 使用CountDownLatch进行异步转同步操作,每个线程退出前必须调用countDown方法,线程执行代码注意catch异常,确保countDown方法可以执行,避免主线程无法执行至await方法,直到超时才返回结果。
控制语句
1.推荐尽量少用else, if-else的方式可以改写成:
1 | if (condition) { |
- a
注释
- 类、属性、方法,使用/*内容/定义注释,不得使用//注释
- 抽象方法、枚举,详细注释
- 注释掉的代码,配合说明
异常日志
异常处理
- RuntimeException预先检查进行规避,避免IndexOutofBoundsException/NullPointerException
- 异常不能用来做流程控制、条件控制,比条件判断效率低
- finally需要关闭资源、流、连接等
- 避免出现重复代码
日志
- 使用SLF4J日志框架的API,不直接使用log4j/logback
- 日志文件命名,含义清晰
- 异常信息,包含现场信息和堆栈信息
1
logger.error(各类参数或者对象toString + "_" + e.getMessage(), e);
- 使用条件输出或占位输出
1
2
3
4
5
6正例:(条件)
if (logger.isDebugEnabled()) {
logger.debug("Processing trade with id: " + id + " symbol: " + symbol);
}
正例:(占位符)
logger.debug("Processing trade with id: {} symbol : {} ", id, symbol);
MySQL
MySQL规约中,MySQL使用方法都是比较有用的经验之选,推荐都仔细研读。
建表
- 使用小写字母,数字,下划线命名
- 尽量不修改表名、字段名
- 主键pk_ ,索引 idx_ ,唯一 uk_
- 小数类型为decimal,禁止使用float和double。
- 如果存储的字符串长度几乎相等,使用char定长字符串类型
索引
- join字段类型一致、禁止超过3表join
- 在varchar字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据实际文本区分度决定索引长度即可。 说明:索引的长度与区分度是一对矛盾体,一般对字符串类型数据,长度为20的索引,区分度会高达90%以上,可以使用count(distinct left(列名, 索引长度))/count(*)的区分度来确定。
- 页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。右模糊可以利用b+树最左前缀匹配
- 利用延迟关联或者子查询优化超多分页场景。 说明:MySQL并不是跳过offset行,而是取offset+N行,然后返回放弃前offset行,返回N行,那当offset特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过特定阈值的页数进行SQL改写。 正例:先快速定位需要获取的id段,然后再关联: SELECT a.* FROM 表1 a, (select id from 表1 where 条件 LIMIT 100000,20 ) b where a.id=b.id
SQL规约
- 【强制】不要使用count(列名)或count(常量)来替代count(),count()是SQL92定义的标准统计行数的语法,跟数据库无关,跟NULL和非NULL无关。 说明:count(*)会统计值为NULL的行,而count(列名)不会统计此列为NULL值的行。
- 【强制】count(distinct col) 计算该列除NULL之外的不重复行数,注意 count(distinct col1, col2) 如果其中一列全为NULL,那么即使另一列有不同的值,也返回为0。
- 【强制】当某一列的值全是NULL时,count(col)的返回结果为0,但sum(col)的返回结果为NULL,因此使用sum()时需注意NPE问题。
ORM规约
- 在表查询中,一律不要使用 * 作为查询的字段列表,需要哪些字段必须明确写明。
- @Transactional事务不要滥用。事务会影响数据库的QPS,另外使用事务的地方需要考虑各方面的回滚方案,包括缓存回滚、搜索引擎回滚、消息补偿、统计修正等。
工程规约
应用分层
图中默认上层依赖于下层,箭头关系表示可直接依赖,如:开放接口层可以依赖于Web层,也可以直接依赖于Service层,依此类推:
- 开放接口层:可直接封装Service方法暴露成RPC接口;通过Web封装成http接口;进行网关安全控制、流量控制等。
- 终端显示层:各个端的模板渲染并执行显示的层。当前主要是velocity渲染,JS渲染,JSP渲染,移动端展示等。
- Web层:主要是对访问控制进行转发,各类基本参数校验,或者不复用的业务简单处理等。
- Service层:相对具体的业务逻辑服务层。
- Manager层:通用业务处理层,它有如下特征: 1) 对第三方平台封装的层,预处理返回结果及转化异常信息; 2) 对Service层通用能力的下沉,如缓存方案、中间件通用处理; 3) 与DAO层交互,对多个DAO的组合复用。
- DAO层:数据访问层,与底层MySQL、Oracle、Hbase进行数据交互。
- 外部接口或第三方平台:包括其它部门RPC开放接口,基础平台,其它公司的HTTP接口。
服务器规约
- 给JVM设置-XX:+HeapDumpOnOutOfMemoryError参数,让JVM碰到OOM场景时输出dump信息。
- 高并发服务器建议调小TCP协议的time_wait超时时间。
安全规约
用户请求传入的任何参数必须做有效性验证。 说明:忽略参数校验可能导致:
- page size过大导致内存溢出
- 恶意order by导致数据库慢查询
- 任意重定向
- SQL注入
- 反序列化注入
- 正则输入源串拒绝服务ReDoS
附录
分层领域模型规约
- DO(Data Object):与数据库表结构一一对应,通过DAO层向上传输数据源对象。
- DTO(Data Transfer Object):数据传输对象,Service和Manager向外传输的对象。
- BO(Business Object):业务对象。可以由Service层输出的封装业务逻辑的对象。
- QUERY:数据查询对象,各层接收上层的查询请求。注:超过2个参数的查询封装,禁止使用Map类来传输。
- VO(View Object):显示层对象,通常是Web向模板渲染引擎层传输的对象。
专有名词
- POJO(Plain Ordinary Java Object):在本规约中,POJO专指只有setter/getter/toString的简单类,包括DO/DTO/BO/VO等。
- DO(Data Object):本手册指数据库表一一对应的POJO类。
- GAV(GroupId、ArtifactctId、Version):Maven坐标,是用来唯一标识jar包。
- OOP(Object Oriented Programming): 本手册泛指类、对象的编程处理方式。
- ORM(Object Relation Mapping): 对象关系映射,对象领域模型与底层数据之间的转换,本文泛指iBATIS, mybatis等框架。
- NPE(java.lang.NullPointerException): 空指针异常。
- 一方库:本工程内部子项目模块依赖的库(jar包)。
- 二方库:公司内部发布到中央仓库,可供公司内部依赖的库(jar包)。
- 三方库:公司之外的开源的依赖库(jar包)
官方文档地址:https://yq.aliyun.com/articles/69327?utm_content=m_10088