暗黑模式
JAVA 开发规范
TIP
本篇规范基于阿里巴巴集团技术团队Java开发手册,添加了我们团队的开发风格规范,补充了一些细节。感谢前人的经验和付出,让我们可以有机会站在巨人的肩膀上眺望星辰大海。
一、编程规范
1、好代码的原则
我们参考 Kent Beck 的简单设计四原则来指导我们的如何写出优秀的代码,如何有效地判断我们的代码是优秀的。
- 通过所有测试(Passes its tests):强调的是外部需求,这是代码实现最重要的
- 尽可能消除重复 (Minimizes duplication):代码的模块架构设计,保证代码的正交性,保证代码更容易修改
- 尽可能清晰表达 (Maximizes clarity):代码的可阅读性,保证代码是容易阅读的
- 更少代码元素 (Has fewer elements):保证代码是简洁的,在简洁和表达力之间,我们更看重表达力
以上四个原则的重要程度依次降低, 这组定义被称做简单设计原则。
2、项目命名规范
全部采用小写方式, 以中划线分隔。
正例:pms-module-project / pms-module-workflow / common-platform
反例:pms_module-project / PmsModuleProject / pmsModuleProject
3、TODO/FIXME 规范
TODO/TBD(to be determined) 注释一般用来描述已知待改进、待补充的修改点,并且加上作者名称。 FIXME 注释一般用来描述已知缺陷,它们都应该有统一风格,方便文本搜索统一处理。如:
java
// TODO <author-name>: 补充XX处理
// FIXME <author-name>: XX缺陷4、方法参数规范
无论是 controller,service,dao 亦或是其他的代码,每个方法最多 3 个参数,如果超出 3 个参数的话,要封装成 javabean 对象。
- 方便他人调用,降低出错几率。尤其是当参数是同一种类型,仅仅依靠顺序区分,稍有不慎便是灾难性后果,而且排查起来也极其恶心。
- 保持代码整洁、清晰度。当一个个方法里充斥着一堆堆参数的时候,再坚强的人,也会身心疲惫。
反例:
java
/**
* 使用证书加密数据工具方法
*
* @param param
* @param password 加密密码
* @param priCert 私钥
* @param pubCert 公钥
* @return 返回加密后的字符串
*/
public String signEnvelop(JdRequestParam param, String password, String priCert, String pubCert){}5、注释规范
5-1、注释和代码一样重要
注释是我们披荆斩棘历经磨难翻越需求这座大山时,留下的踪迹和收获的经验教训,这些宝贵的知识除了证明我们曾经存在过,也提醒着后来的人们殷鉴不远、继往开来。
注释除了说明作用、逻辑之外。还有一个很重要的原因:当业务逻辑过于复杂,代码过于庞大的时候,注释就变成了一道道美化环境、分离与整理逻辑思路的路标。这是很重要的一点,它能有效得帮助我们免于陷入代码与业务逻辑的泥沼之中。
正例:
java
/**
* 开始抽奖方法
* 保存中奖信息、奖励用户积分等
* @param luckDrawDTO
* @return ResponseDTO 返回中奖信息
*/
public ResponseDTO<String> startLuckDraw(LuckDrawDTO luckDrawDTO) {
// -------------- 1、校验抽奖活动基本信息 ------------------------
xxx伪代码一顿操作
// -------------- 2、新增抽奖记录 -------------------------------
xxx伪代码一顿操作
// -------------- 3、如果需要消耗积分,则扣除钢镚积分 -------------
xxx伪代码一顿操作
// -------------- 4、获取奖品信息,开始翻滚吧 --------------------
xxx伪代码一顿操作
return ResponseDTO.succ(luckDrawPrizeVO);
}5-2、注释和代码的一致性
注释并不是越多越好,当注释过多,维护代码的同时,还需要维护注释,不仅变成了一种负担,也与我们当初添加注释的初衷背道而驰。
首先:大家应该通过清晰的逻辑架构,好的变量命名来提高代码可读性;需要的时候,才辅以注释说明。注释是为了帮助阅读者快速读懂代码,所以要从读者的角度出发,按需注释。注释内容要简洁、明了、无二义性,信息全面且不冗余。
其次:无论是修改、复制代码时,都要仔细核对注释内容是否正确。只改代码,不改注释是一种不文明行为,破坏了代码与注释的一致性,会让阅读者迷惑、费解,甚至误解。
反例:
java
// 查询部门
EmployeeDTO employee = employeeDao.listByDeptId(deptId);5-3、方法注释
方法要尽量通过方法名自解释,不要写无用、信息冗余的方法头,不要写空有格式的方法头注释。
方法头注释内容可选,但不限于:功能说明、返回值,用法、算法实现等等。尤其是对外的方法接口声明,其注释,应当将重要、有用的信息表达清楚。
正例:
java
/**
* 解析转换时间字符串为 LocalDate 时间类
* 调用前必须校验字符串格式 否则可能造成解析失败的错误异常
*
* @param dateStr 必须是 yyyy-MM-dd 格式的字符串
*/
public static LocalDate parseYMD(String dateStr){}反例:
java
/**
* 校验对象
*
* @param t
* @return String
*/
public static <T> String checkObj(T t);反例中出现的问题:
- 方法注释没有说明具体的作用、使用事项。
- 参数、返回值,空有格式没内容。这是非常重要一点,任何人调用任何方法之前都需要知道方法对参数的要求,以及返回值是什么。
二、项目规范
TIP
// TODO 项目规范内容待进一步完善
1、代码目录结构
统一的目录结构是所有项目的基础。
plain
src 源码目录
|-- config 项目的配置信息
|-- constants 全局公共常量
|-- controller 控制器
|-- dao 数据库操作
|-- facade 基于Feign的远程调用客户端
|-- model 实体类
|-- service 业务逻辑类
|-- utils 全局工具类
|-- Application.java 启动类2、 model 包中实体类的命名规范
1) 实体类的整体要求:
- 不得有任何的业务逻辑或者计算
- 基本数据类型必须使用包装类型
(Integer, Double、Boolean 等) - 不允许有任何的默认值
- 每个属性必须添加注释,并且必须使用多行注释。
- 必须使用
lombok简化getter/setter方法 - 建议对象使用
lombok的@Builder ,@NoArgsConstructor,同时使用这两个注解,简化对象构造方法以及set方法。
正例:
java
@Builder
@NoArgsConstructor
@Data
public class DemoDTO {
private String name;
private Integer age;
}
// 使用示例:
DemoDTO demo = DemoDTO.builder()
.name("yeqiu")
.age(66)
.build();2)DAO对象;要求:
- Xxxx 与数据库表名保持一致
- 类中字段要与数据库字段保持一致,不能缺失或者多余
- 类中的每个字段添加注释,并与数据库注释保持一致
- 不允许有组合
- 项目内的日期类型必须统一,建议使用
java.util.Date,java.sql.Timestamp,java.time.LocalDateTime其中只一。
3)传输对象;XxxxDTO,要求:
- 不可以继承自 Dao对象
DTO可以继承、组合其他DTO,VO,BO等对象DTO只能用于前端、RPC 的请求参数
3)视图对象;XxxxVO,要求:
- 不可继承自 Dao对象
VO可以继承、组合其他DTO,VO,BO等对象VO只能用于返回前端、rpc 的业务数据封装对象
4)业务对象 BO,要求:
- 不可以继承自 Dao对象
BO对象只能用于service,manager,dao层,不得用于controller层
三、数据库 规范
1 建表规范
表必备三字段:id, create_time, update_time
- id 字段 Long 类型,单表自增,自增长度为 1
- create_time 字段 datetime 类型,默认值 CURRENT_TIMESTAMP
- update_time 字段 datetime 类型,默认值 CURRENT_TIMESTAMP, On update CURRENT_TIMESTAMP
2 枚举类表字段注释需要将所有枚举含义进行注释
修改或增加字段的状态描述,必须要及时同步更新注释。 如下表的 sync_status 字段 同步状态 0 未开始 1同步中 2同步成功 3失败。
正例:
sql
CREATE TABLE `t_change_data` (
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`sync_status` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' COMMENT '同步状态 0 未开始 1同步中 2同步成功 3失败',
`sync_time` DATETIME NULL DEFAULT NULL COMMENT '同步时间',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`change_data_id`)
)反例:
sql
CREATE TABLE `t_change_data` (
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`sync_status` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' COMMENT '同步状态 ',
`sync_time` DATETIME NULL DEFAULT NULL COMMENT '同步时间',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`change_data_id`)
)3 合理结合业务给表字段添加索引和唯一索引
具体索引规范请参照《阿里巴巴 Java 开发手册》索引规约
四、其他
1、代码提交规范
- 提交前应该冷静、仔细检查一下,确保没有忘记加入版本控制或不应该提交的文件。
- 提交前应该先编译一次(idea里ctrl+F9),防止出现编译都报错的情况。
- 提交前先更新pull一次代码,提交前发生冲突要比提交后发生冲突容易解决的多。
- 提交前检查代码是否格式化,是否符合代码规范,无用的包引入、变量是否清除等等。
- 提交时检查注释是否准确简洁的表达出了本次提交的内容。
2、maven项目
- pom禁止出现相同 groupId,artifactId 的依赖配置。
- 项目名称应该与 artifactId 保持一致。
- 定期检查jar包依赖关系,及时排除解决冲突的jar包。
3、保持项目整洁
使用git,必须添加 .gitignore 忽略配置文件。 不要提交与项目无关的内容文件:idea配置、target包等。

