【笔记】阿里开发手册

  2017-03-10  Linux运维编程技术   12 分钟

概述

阿里作为全世界Java开发规模最大和应用水平最高的地方之一,三十几页的规范,从编程、异常日志、SQL、工程、安全五块形成的规约总结,根据约束力,分强制、推荐、参考三大类,可以作为优秀技术团队的重要利器。

官方文档地址:https://yq.aliyun.com/articles/69327?utm_content=m_10088

以下是阅读阿里开发手册中,记录的一些重要摘要信息。

编程规范

命名

  1. 尽量语义清晰、望名知义
  2. 遵从驼峰形式
  3. 如果使用到了设计模式,类名体现具体模式

常量定义

  1. 值定义不要出现未定义的常量
  2. 常量类推荐也分类定义常量类,不要大而全的一个常量类
  3. 变量值在一定范围,使用Enum类

格式规约

  1. 单行限制不超过120个字符

看注释内容,示例代码:

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");
        // 在右大括号后直接结束,则必须换行
    }
}

OOP规约

  1. overwrite方法,必须有@overwrite注解
  2. 静态方法和变量,直接通过类名访问,禁止对象访问,增加无谓的编译器解释成本
  3. 不能使用过时的类或方法
  4. 包装类之间的值比较,使用equals方法
  5. 构造方法禁止加入任何业务逻辑,请放在init方法中
  6. String的split方法,做分隔符后无内容的检测
  7. 类方法定义的顺序,公有方法或保护方法 > 私有方法 > getter/setter方法
  8. getter/setter方法尽量不要加入任何业务逻辑,增加排查问题的难度
  9. 推荐使用StringBuilder的append方法替换string拼接

集合处理

并发处理

  1. 线程定义名称
  2. 使用线程池,使用ThreadPoolExecutor
  3. 高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁。
  4. 使用CountDownLatch进行异步转同步操作,每个线程退出前必须调用countDown方法,线程执行代码注意catch异常,确保countDown方法可以执行,避免主线程无法执行至await方法,直到超时才返回结果。

控制语句

1.推荐尽量少用else, if-else的方式可以改写成:

if (condition) {
    ...
    return obj;
}
// 接着写else的业务逻辑代码;
  1. a

注释

  1. 类、属性、方法,使用/**内容*/定义注释,不得使用//注释
  2. 抽象方法、枚举,详细注释
  3. 注释掉的代码,配合说明

异常日志

异常处理

  1. RuntimeException预先检查进行规避,避免IndexOutofBoundsException/NullPointerException
  2. 异常不能用来做流程控制、条件控制,比条件判断效率低
  3. finally需要关闭资源、流、连接等
  4. 避免出现重复代码

日志

  1. 使用SLF4J日志框架的API,不直接使用log4j/logback
  2. 日志文件命名,含义清晰
  3. 异常信息,包含现场信息和堆栈信息
logger.error(各类参数或者对象toString + "_" + e.getMessage(), e);
  1. 使用条件输出或占位输出
正例:(条件)
if (logger.isDebugEnabled()) {
    logger.debug("Processing trade with id: " + id + " symbol: " + symbol);
}
正例:(占位符)
logger.debug("Processing trade with id: {} symbol : {} ", id, symbol);

MySQL

MySQL规约中,MySQL使用方法都是比较有用的经验之选,推荐都仔细研读。

 建表

  1. 使用小写字母,数字,下划线命名
  2. 尽量不修改表名、字段名
  3. 主键pk_ ,索引 idx_ ,唯一 uk_
  4. 小数类型为decimal,禁止使用float和double。
  5. 如果存储的字符串长度几乎相等,使用char定长字符串类型

索引

  1. join字段类型一致、禁止超过3表join
  2. 在varchar字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据实际文本区分度决定索引长度即可。 说明:索引的长度与区分度是一对矛盾体,一般对字符串类型数据,长度为20的索引,区分度会高达90%以上,可以使用count(distinct left(列名, 索引长度))/count(*)的区分度来确定。
  3. 页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。右模糊可以利用b+树最左前缀匹配
  4. 利用延迟关联或者子查询优化超多分页场景。 说明: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规约

  1. 【强制】不要使用count(列名)或count(常量)来替代count(),count()是SQL92定义的标准统计行数的语法,跟数据库无关,跟NULL和非NULL无关。 说明:count(*)会统计值为NULL的行,而count(列名)不会统计此列为NULL值的行。
  2. 【强制】count(distinct col) 计算该列除NULL之外的不重复行数,注意 count(distinct col1, col2) 如果其中一列全为NULL,那么即使另一列有不同的值,也返回为0。
  3. 【强制】当某一列的值全是NULL时,count(col)的返回结果为0,但sum(col)的返回结果为NULL,因此使用sum()时需注意NPE问题。

ORM规约

  1. 在表查询中,一律不要使用 * 作为查询的字段列表,需要哪些字段必须明确写明。
  2. @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接口。

服务器规约

  1. 给JVM设置-XX:+HeapDumpOnOutOfMemoryError参数,让JVM碰到OOM场景时输出dump信息。
  2. 高并发服务器建议调小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向模板渲染引擎层传输的对象。

专有名词

  1. POJO(Plain Ordinary Java Object):在本规约中,POJO专指只有setter/getter/toString的简单类,包括DO/DTO/BO/VO等。
  2. DO(Data Object):本手册指数据库表一一对应的POJO类。
  3. GAV(GroupId、ArtifactctId、Version):Maven坐标,是用来唯一标识jar包。
  4. OOP(Object Oriented Programming): 本手册泛指类、对象的编程处理方式。
  5. ORM(Object Relation Mapping): 对象关系映射,对象领域模型与底层数据之间的转换,本文泛指iBATIS, mybatis等框架。
  6. NPE(java.lang.NullPointerException): 空指针异常。
  7. 一方库:本工程内部子项目模块依赖的库(jar包)。
  8. 二方库:公司内部发布到中央仓库,可供公司内部依赖的库(jar包)。
  9. 三方库:公司之外的开源的依赖库(jar包)

官方文档地址:https://yq.aliyun.com/articles/69327?utm_content=m_10088

— 转载本站文章请注明作者和出处全栈记 ,请勿用于任何商业用途

— 于 2017年03月10日 ,共写了 4058 字;

— 本文共有 1 个标签:

5条回应:“【笔记】阿里开发手册”

  1. 山野愚人居说道:

    不做开发的路过!

发表评论

电子邮件地址不会被公开。 必填项已用*标注