阿里开发手册规范(JAVA)

目录


一、编程规约 

(一) 命名规范

1. 代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束。 反例:_name / __name / $name / name_ / name$ / name__ 。

2. 禁止使用拼音和英文混合。反例:DaZhePromotion [打折] / getPingfenByName() [评分] 。

3. 类名使用大驼峰式命名法;方法名、参数名、成员变量、局部变量都统一使用小驼峰式命名法。

4. 常量命名全部大写,单词间用下划线隔开;:MAX_STOCK_COUNT / CACHE_EXPIRED_TIME 。

5. 类型与中括号紧挨相连来表示数组。 :定义整形数组 int[] arrayDemo。 

6. boolean类型变量,不要以is开头,避免部分序列化框架出错。反例boolean isExists。

7. 杜绝完全不规范的缩写,避免望文不知义。 反例:AbstractClass“缩写”成AbsClass;condition“缩写”成 condi。

8. 对于Service和DAO类,一定是接口,实现需要以Impl的后缀结尾。区别于接口
如:CacheService CacheServiceImpl。

9. 枚举类名带上Enum后缀,枚举成员名称需要全大写,单词间用下划线隔开。 

10. 类接口中属性和方法不要加任何修饰符。

(二) 常量定义

1. 不允许任何魔法值(即未经预先定义的常量)直接出现在代码中。  反例:String key = “id=” + id;

2. long和Long初始赋值时,必须使用大写,为了避免和数字1搞混。
:Long a = 2L   反例:Long a = 2l

3. 不要使用一个常量类维护所有常量,尽可能根据功能进行拆分归类,分开维护。便于理解和维护。

(三) 代码格式 

1. 如果是大括号内为空,则写成{}即可,大括号中间无需换行和空格;如果是非空代码块则:( 1) 左大括号前不换行,左大括号后换行。  (2) 右大括号前换行。  

2. 左括号与后一个字符之间不出现空格,右括号与前一个字符之间不出现空格
:if (flag == 0)。

3. if/for/while/switch/do 等保留字与括号之间都必须加空格。 

4. 何二目、三目运算符的左右两边都需要加一个空格。 

5. 注释的双斜线与注释内容之间有且仅有一个空格。 

6. 方法参数在定义和传入时,多个参数逗号后必须加空格。 :method(“a”, “b”, “c”);

(四) OOP规约

1. 直接使用类名来访问一个类的静态变量或静态方法。

2. 所有的覆写方法,必须加@Override注解,可以准确判断是否覆盖成功。

3. 对外的接口,原则上避免修改,可以增加新接口,过时接口使用@Deprecated注解

4. Object的 equals方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals。:”test”.equals(object); 

5. 所有整型包装类对象之间值的比较,全部使用equals方法比较,使用==进行判断的话会有数值范围的限制。

6. 循环体内字符串拼接,使用StringBuilder的append方法。

7. 构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在 init方法中。 

8. 浮点数之间的等值判断,基本数据类型不能用==来比较,包装数据类型不能用equals 来判断。 

(五) 日期时间

1. 日期格式化时,传入pattern 中表示年份统一使用小写的y。 

2. 获取当前毫秒数:System.currentTimeMillis(); 而不是new Date().getTime()。 

(六) 集合处理 

1. 只要重写equals,就必须重写hashCode。

2. 判断所有集合内部的元素是否为空,使用isEmpty()方法,而不是size()==0的方式。

3. ArrayList的subList方法结果不可转成ArrayList。(subList返回的是ArrayList的内部类,并不是ArrayList,而且是ArrayList的一个视图,对SubList所有的操作都会反映到ArrayList原列表上。)

4. 使用集合转数组方法,必须使用集合的toArray(T[] array)。

5. 不要在foreach循环里进行元素的remove/add操作。remove元素请使用Iterator 方式,如果并发操作,需要对Iterator对象加锁。 

6. 使用工具类Arrays.asList()将数组转换成集合时,不能使用修改集合相关方法,如:add/remove/clear都将抛出UnsupportedOperationException异常。

(七) 并发处理

1. 获取单例对象需要保证线程安全,其中的方法也要保证线程安全。 

2. 线程资源必须通过线程池提供,不允许在应用中自行显式创建线程,避免过多创建线程、减少创建和销毁线程开销。

3. 线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,Executors返回的线程池对象的缺点是可能会创建大量线程或堆积大量请求,导致OOM。

4. 并发情况,多考虑锁的性能损耗。能不用锁就不用锁;能锁区块,就不要锁整个方法;能锁对象就别锁类。

5. 对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序,否则可能会造成死锁。

6. 如果访问冲突概率不高,推荐使用乐观锁。

7. HashMap 在容量不够进行resize时由于高并发可能出现死链,导致CPU飙升,在 开发过程中注意规避此风险。 

8. ThreadLocal对象建议使用static修饰

(八) 控制语句

1. switch块内,每个case要么通过break/return终止,要么注释说明将执行到哪一个case为止;在一个switch必须包含default,就算是空的。

2. 当switch 括号内的变量类型为String并且此变量为外部参数时,必须先进行null 判断。

3. 在 if/else/for/while/do语句中必须使用大括号。 

4. 在高并发场景中,避免使用”等于”判断作为中断或退出的条件。 反例:判断剩余奖品数量等于 0 时,终止发放奖品,但因为并发处理错误导致奖品数量瞬间变成了负数, 这样的话,活动无法终止。 

(九) 注释规约

1. 类、类属性、类方法的注释必须使用Javadoc规范,使用/**内容*/格式,不得使用 // xxx方式。

2. 所有的抽象方法(包括接口中的方法),必须要用Javadoc注释

3. 所有的类都必须添加创建者和创建日期。 

(十) 前后端规约

1. 前后端交互的API,需要明确协议、域名、路径、请求方法、请求内容、状态码、响应体。

2. 前后端数据列表相关的接口返回,如果为空,则返回空数组[]或空集合{}。 

3. 服务端发生错误时,返回给前端的响应信息必须包含HTTP状态码,errorCode、 errorMessage、用户提示信息四个部分。

二、异常日志 

(一) 错误码

1. 错误码不体现版本号和错误等级信息。 

2. 错误码不能直接输出给用户作为提示信息使用。 

(二) 异常处理

1. 不要捕获继承自RuntimeException的运行时异常,这类异常需要自行检查规避,如:IndexOutOfBoundsException / NullPointerException。

2. 异常捕获后不要用来做流程控制,条件控制。 

3. 捕获异常是为了处理它,不要捕获了却什么都不处理而抛弃之,如果不想处理它,请将该异常抛给它的调用者。

4. finally块必须对资源对象、流对象进行关闭,有异常也要做try-catch;不要在finally块中使用return。 

(三) 日志规约 

1. 不要执行使用日志实现类,而应该使用SLF4J的API接口,使用门面模式,容易做到所有类的日志处理方式统一。

2. 所有日志文件至少保存15天,因为有些异常具备以“周”为频次发生的特点。

3. 避免重复打印日志,浪费磁盘空间,务必在日志配置文件中设置 additivity=false。 

4. 日志打印时禁止直接用JSON工具将对象转换成String。

三、单元测试 

1. 好的单元测试必须遵守 AIR原则,即具有自动化、独立性、可重复执行的特点。

2. 单元测试是可以重复执行的,不能受到外界环境的影响。 

3. 保持单元测试的独立性。为了保证单元测试稳定可靠且便于维护,单元测试用例之间 决不能互相调用,也不能依赖执行的先后次序。 

四、安全规约

1. 隶属于用户个人的页面或者功能必须进行权限控制校验。 

2. 用户敏感数据禁止直接展示,必须对展示数据进行脱敏。 

3. 用户输入的 SQL参数严格使用参数绑定或者 METADATA字段值限定,防止 SQL注入, 禁止字符串拼接 SQL访问数据库。 

4. 表单、AJAX提交必须执行 CSRF安全验证。 

五、MySQL数据库 

(一) 建表规约

1. 表达是与否概念的字段,必须使用is_xxx的方式命名,数据类型是unsigned tinyint (1表示是,0表示否)。 

2. 表名字段名必须使用小写字符或数字;禁止出现数字开头,禁止两个下划线之间只有数字。:aliyun_admin,rdc_config,level3_name。

3. 禁用保留字,如desc、range、match、delayed等。

4. 表名不使用复数名词。 

5. 主键索引名为 pk_字段名;唯一索引名为 uk_字段名;普通索引名则为 idx_字段名。 说明:pk_ 即primary key;uk_ 即 unique key;idx_ 即index的简称。 

6. 小数类型为decimal,禁止使用float和double。 

7. 如果存储的字符串长度几乎相等,使用 char定长字符串类型。

8. varchar为变长字符串,长度不要超过5000,如果存储长度超过该值,使用text,并独立表出来。

9. 表必备三字段:id, create_time, update_time。 

(二) 索引规约 

1. 业务上具有唯一特性的字段,即使是组合字段,也必须建成唯一索引。 

2. 超过三个表禁止 join。需要 join的字段,数据类型保持绝对一致;多表关联查询时, 保证被关联的字段需要有索引。

3. 在 varchar字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据 实际文本区分度决定索引长度。 

4. 严禁左模糊或者全模糊。

5. 利用覆盖索引来进行查询操作,避免回表。 

(三) SQL语句

1. 不要使用count(列名)或count(常量)来替代count(*),count(*)是SQL92定义的标 准统计行数的语法,跟数据库无关,跟NULL和非 NULL无关。 

2. 当某一列的值全是NULL时,count(col)的返回结果为0,但 sum(col)的返回结果为 NULL,因此使用sum()时需注意NPE问题。 

3. in操作能避免则避免,若实在避免不了,需要仔细评估 in后边的集合元素数量,控 制在1000个之内。 

(四) ORM映射

1. 在表查询中,一律不要使用 * 作为查询的字段列表,需要哪些字段必须明确写明。

2. POJO类的布尔属性不能加is,而数据库字段必须加is_,要求在resultMap中进行 字段与属性之间的映射。 

3. sql.xml配置参数使用:#{},#param# 不要使用${} 此种方式容易出现 SQL注入。

4. 更新数据表记录时,必须同时更新记录对应的update_time字段值为当前时间。 

六、工程结构 

(一) 应用分层

1. 分层领域模型规约: 
• DO(Data Object):此对象与数据库表结构一一对应,通过 DAO层向上传输数据源对象。 
• DTO(Data Transfer Object):数据传输对象,Service 或Manager 向外传输的对象。 
• BO(Business Object):业务对象,可以由Service层输出的封装业务逻辑的对象。 
• Query:数据查询对象,各层接收上层的查询请求。注意超过2 个参数的查询封装,禁止使用 Map 类 来传输。 
• VO(View Object):显示层对象,通常是 Web 向模板渲染引擎层传输的对象。 

(二) 二方库依赖 

1. 二方库版本号命名方式:主版本号.次版本号.修订号。

2 .二方库里可以定义枚举类型,参数可以使用枚举类型,但是接口返回值不允许使用枚 举类型或者包含枚举类型的 POJO对象。 

3. 依赖于一个二方库群时,必须定义一个统一的版本变量,避免版本号不一致。 

4. 禁止在子项目的 pom依赖中出现相同的 GroupId,相同的 ArtifactId,但是不同的 Version。

(三) 服务器 

1. 高并发服务器建议调小 TCP协议的 time_wait超时时间。

2. 给JVM环境参数设置-XX:+HeapDumpOnOutOfMemoryError参数,让JVM碰到OOM 场景时输出dump 信息。

七、设计规约 

1. 在需求分析阶段,如果与系统交互的User超过一类并且相关的User Case超过5个, 使用用例图来表达更加清晰的结构化需求。 

2. 如果某个业务对象的状态超过3个,使用状态图来表达并且明确状态变化的各个触发条件。

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
乘风的头像乘风管理团队
上一篇 2023年12月21日
下一篇 2023年12月21日

相关推荐