|
1 |
| -# 《Effective Coding 阿里巴巴 Java 开发手册》 |
| 1 | +# 《Effective Coding——阿里巴巴 Java 开发手册》 |
2 | 2 |
|
3 | 3 | ## 第一章 编程规约
|
4 | 4 | ### 命名风格
|
@@ -113,12 +113,55 @@ public class TimeTaskThread extends Thread {
|
113 | 113 | 1. volatile 解决多线程内存不可见问题。对于一写多读,可以解决变量同步问题,但是如果多写,同样无法解决线程安全问题。
|
114 | 114 |
|
115 | 115 | ### 控制语句
|
116 |
| -1. 在一个 switch 快内,每个 case 要么通过 break/return 等来终止,要么注释说明程序将继续执行到哪一个 case 为止;在一个 switch 块内,**都必须**包含一个 default 语句并且放在最后,即使它什么代码都没有。 |
| 116 | +1. 在一个 switch 块内,每个 case 要么通过 break/return 等来终止,要么注释说明程序将继续执行到哪一个 case 为止;在一个 switch 块内,**都必须**包含一个 default 语句并且放在最后,即使它什么代码都没有。 |
117 | 117 | 1. 在高并发场景中,**避免使用**“等于”判断作为中断或退出的条件。<br>**说明**:如果并发控制没有处理好,容易产生等值判断被击穿的情况,应使用大于或小于的区间判断条件来代替。
|
118 | 118 | 1. 不要在条件判断中执行其它复杂的语句,可将复杂逻辑判断的结果赋值给一个**有意义的布尔变量名**,以提高可读性。
|
119 | 119 |
|
120 | 120 | ### 注释规约
|
121 | 121 | 1. 特殊注释标记。TODO 实际上是一个 Javadoc 的标签,虽然目前的 Javadoc 还没有实现,但已经被广泛使用,且**只能应用于类、接口和方法上**。在注释中用 FIXME 标记某代码是错误的,而且不能工作,需要及时纠正。
|
122 | 122 |
|
123 | 123 | ### 其他
|
124 |
| -1. 注意 Math.random() 这个方法返回的是 double 类型,取值范围 x ∈ [0, 1),如果想获得整数类型的随机数,不要将 x 放大 10 的若干倍然后取整,直接使用 Random 对象的 nextInt 或者 nextLong 方法。 |
| 124 | +1. 注意 Math.random() 这个方法返回的是 double 类型,取值范围 x ∈ [0, 1),如果想获得整数类型的随机数,不要将 x 放大 10 的若干倍然后取整,直接使用 Random 对象的 nextInt 或者 nextLong 方法。 |
| 125 | + |
| 126 | +## 第二章 异常日志 |
| 127 | +### 异常处理 |
| 128 | +1. catch 时请分清稳定代码和不稳定代码。稳定代码指的是无论如何都不会出错的代码。对于非稳定代码的 catch,尽可能在进行异常类型的区分后,再做对应的异常处理。 |
| 129 | +1. 不要在 finally 块中使用 return。<br>**说明**:当 finally 块中的 return 返回后方法结束执行,不会再执行 try 块中的 return 语句。 |
| 130 | +1. 定义时区分 unchecked/checked 异常,避免直接抛出 new RuntimeException(),更不允许抛出 Exception 或者 Throwable,应使用有业务含义的自定义异常。推荐业界已定义过的自定义异常,如 DAOException/ServiceException 等。 |
| 131 | + |
| 132 | +### 日志规约 |
| 133 | +1. 应用中不可直接使用日志系统(Log4j、Logback)中的 API,而应依赖使用日志框架 SLF4J 中的 API。使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。 |
| 134 | + |
| 135 | +```java |
| 136 | +import org.slf4j.Logger; |
| 137 | +import org.slf4j.LoggerFactory; |
| 138 | + |
| 139 | +private static final Logger logger = LoggerFactory.getLogger(Abc.class); |
| 140 | +``` |
| 141 | + |
| 142 | +2. 谨慎地记录日志。生产环境禁止输出 debug 日志;有选择地输出 info 日志;如果使用 warn 记录刚上线时的业务行为信息,一定要注意日志输出量的问题,避免把服务器磁盘撑爆,并及时删除这些观察日志。 |
| 143 | + |
| 144 | +## 第三章 单元测试 |
| 145 | +1. 单元测试是可重复执行的,不能受到外界环境的影响。 |
| 146 | +1. 和数据库相关的单元测试,可以设定自动回滚机制,不给数据库造成脏数据。 |
| 147 | +1. 单元测试作为一种质量保障手段,不建议项目发布后补充单元测试用例,建议在项目提测前完成单元测试。 |
| 148 | + |
| 149 | +## 第四章 安全规约 |
| 150 | +1. 针对发帖、评论、发送即时消息等用户生成内容的场景,必须实现防刷、文本内容违禁词过滤等风控策略。 |
| 151 | + |
| 152 | +## 第五章 MySQL 数据库 |
| 153 | +### 建表规约 |
| 154 | +1. 表达是与否概念的字段,必须使用 is_xxx 的方式命名,数据类型为 `unsigned tinyint`。<br> **说明**:任何字段如果为非负数,则必须是 unsigned。 |
| 155 | +1. 字段允许适当冗余,以提高查询性能,但必须考虑数据一致。e.g. 商品类目名称使用频率高,字段长度短,名称基本一成不变,可在相关联的表中冗余存储类目名称,**避免关联查询**。冗余字段遵循: |
| 156 | + - 不是频繁修改的字段; |
| 157 | + - 不是 varchar 超长字段,更不能是 text 字段。 |
| 158 | + |
| 159 | +### 索引规约 |
| 160 | +1. 在 varchar 字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据实际文本区分度决定索引长度即可。 |
| 161 | +1. 页面搜索严禁左模糊或者全模糊,如果需要请通过搜索引擎来解决。<br> **说明**:索引文件具有 B-Tree 的**最左前缀匹配特性**,如果左边的值未确定,那么无法使用此索引。 |
| 162 | +1. 如果有 order by 的场景,请注意利用索引的有序性。order by 最后的字段是组合索引的一部分,并且放在索引组合顺序的最后,避免出现 file_sort 的情况,影响查询性能。 |
| 163 | + - **正例**:where a=? and b=? order by c; 索引: a_b_c。 |
| 164 | + - **反例**:索引中有范围查找,那么索引有序性无法利用,如 WHERE a>10 ORDER BY b; 索引 a_b 无法排序。 |
| 165 | +1. 利用延迟关联或者子查询优化超多分页场景。<br>**说明**:MySQL 并不是跳过 offset 行,而是取 offset+N 行,然后返回放弃前 offset 的行,返回 N 行。当 offset 特别大的时候,效率会非常的低下,要么控制返回的总页数,要么对超过阈值的页数进行 SQL 改写。 |
| 166 | +1. 建组合索引的时候,区分度最高的在最左边。 |
| 167 | +1. SQL 性能优化的目标,至少要达到 range 级别,要求是 ref 级别,最好是 consts。 |
0 commit comments