1.命名
【强制】类名使用 UpperCamelCase 风格,必须遵从驼峰形式,但以下情形例外:DO / BO / DTO / VO / AO
- 正例:MarcoPolo / UserDO / XmlService / TcpUdpDeal / TaPromotion
- 反例:macroPolo / UserDo / XMLService / TCPUDPDeal / TAPromotion
【强制】方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格,必须遵从 驼峰形式。
- 正例: localValue / getHttpMessage() / inputUserId
【强制】常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。
- 正例:MAX_STOCK_COUNT 反例:MAX_COUNT
【强制】抽象类命名使用 Abstract 或 Base 开头;异常类命名使用 Exception 结尾;测试类命名以它要测试的类的名称开始,以 Test 结尾。
【强制】Model 类中布尔类型的变量,都不要加 is,否则部分框架解析会引起序列化错误。
- 反例:定义为基本数据类型 Boolean isDeleted;的属性,它的方法也是 isDeleted(),RPC框架在反向解析的时候,“以为”对应的属性名称是 deleted,导致属性获取不到,进而抛出异常。
【强制】对于 Service 和 DAO 类,基于 SOA 的理念,暴露出来的服务一定是接口,内部的实现类用 Impl 的后缀与接口区别。
- 正例:CacheManagerImpl 实现 CacheManager 接口。
【推荐】为了达到代码自解释的目标,任何自定义编程元素在命名时,使用尽量完整的单词组合来表达其意。
- 正例:从远程仓库拉取代码的类命名为PullCodeFromRemoteRepository
- 反例:变量int a;的随意命名方式。
【推荐】接口类中的方法和属性不要加任何修饰符号(public 也不要加),保持代码的简洁 性,并加上有效 的Javadoc 注释。尽量不要在接口里定义变量,如果一定要定义变量,肯定是 与接口方法相关,并且是整个应用的基础常量。
- 正例:接口方法签名:void f(); 接口基础常量表示:String COMPANY = "alibaba";
- 反例:接口方法定义:public abstract void f(); 说明:JDK8 中接口允许有默认实现,那么这个default方法,是对所有实现类都有价值的默 认实现。
【参考】枚举类名建议带上 Enum 后缀,枚举成员名称需要全大写,单词间用下划线隔开。
- 说明:枚举其实就是特殊的常量类,且构造方法被默认强制是私有。
- 正例:枚举名字为 ProcessStatusEnum 的成员名称:SUCCESS / UNKOWN_REASON。
【参考】各层命名规约:
- A) Service/DAO 层方法命名规约
- 1) 获取单个对象的方法用 get 做前缀。
- 2) 获取多个对象的方法用 list 做前缀。
- 3) 获取统计值的方法用 count 做前缀。
- 4) 插入的方法用 save/insert 做前缀。
- 5) 删除的方法用 remove/delete 做前缀。
- 6) 修改的方法用 update 做前缀。
2.变量定义
【推荐】不要使用一个常量类维护所有常量,按常量功能进行归类,分开维护。 说明:大而全的常量类,非得使用查找功能才能定位到修改的常量,不利于理解和维护。
- 正例:缓存相关常量放在类 CacheConsts 下;系统配置相关常量放在类 ConfigConsts 下。
3.代码格式
【强制】大括号的使用约定。如果是大括号内为空,则简洁地写成{}即可,不需要换行;如果 是非空代码块则:
- 1) 左大括号前不换行。
- 2) 左大括号后换行。
- 3) 右大括号前换行。
- 4) 右大括号后还有 else 等代码则不换行 表示终止的右大括号后必须换行。
【强制】 左小括号和字符之间不出现空格;同样,右小括号和字符之间也不出现空格。
- 反例:if (空格a == b空格)
【强制】if/for/while/switch/do 等保留字与括号之间都必须加空格。
【强制】任何二目、三目运算符的左右两边都需要加一个空格。
- 说明:运算符包括赋值运算符=、逻辑运算符&&、加减乘除符号等。
【强制】采用 4 个空格缩进,禁止使用 tab 字符。
- 说明:Vue工程采用2个空格缩进
【强制】注释的双斜线与注释内容之间有且仅有一个空格。
- 正例:// 注释内容,注意在//和注释内容之间有一个空格。
【强制】方法参数在定义和传入时,多个参数逗号后边必须加空格。
- 正例:下例中实参的"a",后边必须要有一个空格。method("a", "b", "c");
【强制】IDE 的 text file encoding 设置为 UTF-8; IDE 中文件的换行符使用 Unix 格式,不要使用 Windows 格式。
【推荐】方法体内的执行语句组、变量的定义语句组、不同的业务逻辑之间或者不同的语义之间插入一个空行。相同业务逻辑和语义之间不需要插入空行。
- 说明:没有必要插入多个空行进行隔开。
4.OOP原则
【强制】所有的覆写方法,必须加@Override 注解。
【强制】不能使用过时的类或方法。
【强制】Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。
- 正例:"test".equals(object);
- 反例:object.equals("test");
【强制】所有的相同类型的包装类对象之间值的比较,全部使用 equals 方法比较。
- 说明:对于 Integer var = ? 在-128 至 127 范围内的赋值,Integer 对象是在IntegerCache.cache 产生,会复用已有对象,这个区间内的 Integer 值可以直接使用==进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑, 推荐使用 equals 方法进行判断。
【强制】RPC 方法的返回值和参数必须使用包装数据类型。
【强制】构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在 init 方法中。
【推荐】当一个类有多个构造方法,或者多个同名方法,这些方法应该按顺序放置在一起, 便于阅读。
【推荐】循环体内,字符串的连接方式,使用 StringBuilder 的 append 方法进行扩展。 说明:反编译出的字节码文件显示每次循环都会 new 出一个 StringBuilder 对象,然后进行 append 操作,最后通过 toString 方法返回 String 对象,造成内存资源浪费。 【推荐】慎用 Object 的 clone 方法来拷贝对象。 说明:对象的 clone 方法默认是浅拷贝,若想实现深拷贝需要重写 clone 方法实现属性对象 的拷贝。
5.索引规约
【强制】业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。
- 说明:不要以为唯一索引影响了 insert 速度,这个速度损耗可以忽略,但提高查找速度是明 显的;另外,即使在应用层做了非常完善的校验控制,只要没有唯一索引,根据墨菲定律,必 然有脏数据产生。
【强制】超过三个表禁止 join。需要 join 的字段,数据类型必须绝对一致;多表关联查询时, 保证被关联的字段需要有索引。
- 说明:即使双表 join 也要注意表索引、SQL 性能。
【强制】在 varchar 字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据 实际文本区分度决定索引长度即可。
- 说明:索引的长度与区分度是一对矛盾体,一般对字符串类型数据,长度为 20 的索引,区分度会高达 90%以上,可以使用 count(distinct left(列名, 索引长度))/count(*)的区分度 来确定。
【参考】创建索引时避免有如下极端误解:
- 1)宁滥勿缺。认为一个查询就需要建一个索引。
- 2)宁缺勿滥。认为索引会消耗空间、严重拖慢更新和新增速度。
- 3)抵制惟一索引。认为业务的惟一性一律需要在应用层通过“先查后插”方式解决。
6.SQL语句
【强制】不要使用 count(列名)或 count(常量)来替代 count( ),count( )是 SQL92 定义的 标准统计行数的语法,跟数据库无关,跟 NULL 和非 NULL 无关。 说明:count(*)会统计值为 NULL 的行,而 count(列名)不会统计此列为 NULL 值的行。
【强制】count(distinct col) 计算该列除 NULL 之外的不重复行数,注意 count(di col1, col2) 如果其中一列全为 NULL,那么即使另一列有不同的值,也返回为 0。
【强制】当某一列的值全是 NULL 时,count(col)的返回结果为 0,但 sum(col)的返回结果为NULL.
【强制】不得使用外键与级联,一切外键概念必须在应用层解决。
【强制】禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。
【推荐】in 操作能避免则避免,若实在避免不了,需要仔细评估 in 后边的集合元素数量,控 制在 1000 个之内。
【参考】如果有全球化需要,所有的字符存储与表示,均以 utf-8 编码,注意字符 的区别。
- 说明: SELECT LENGTH("轻松工作"); 返回为 12 SELECT CHARACTER_LENGTH("轻松工作"); 返回为 4 如果需要存储表情,那么选择 utfmb4 来进行存储,注意它与 -8 编码的区别。
【强制】更新数据表记录时,必须同时更新记录对应的 update_time 字段值为当前时间。
【参考】@Transactional 事务不要滥用。事务会影响数据库的 QPS,另外使用事务的地方需 要考虑各方面的回滚方案,包括缓存回滚、搜索引擎回滚、消息补偿、统计修正等。