这里我就列出一些我认为应当遵守的,并且添加一些我自己在工作中的一些感受,如果照着文档抄,那完全变成练习打字了,浪费读者时间,如果你也认同我的看法,或者和我有类似感受,可以点个关注,共同进步,如果有不同意见,欢迎指出。
一、命名风格
这个看似很简单的问题,真的有必要好好研究一下,因为就我见过的就有很多种,有的单词乱用,翻译过来也不注意单词的使用场景,有的干脆用拼音来命名,这都还好,起码还能读得懂,但是甚至有用拼英首字母缩写的,这如果不是初始员工,后续接手,无异于看天书,举个栗子,xsdd - 销售订单,cjr - 创建人。
- 【强制】所有编程相关命名中不能使用下划线或美元符号开始或者结束
这个有点宽松了,一般我要求,除了常量的命名,可以用下划线。其它所有名称都不能出现下划线或者美元符号这些其它乱起八糟的符号。
- 【强制】所有编程相关的命名严禁使用拼音与英文混合方式,更不允许直接使用中文
有些场景下确实无法避免使用拼音,比如: aliyun,alibaba 这些国际通用名称,所以我们也没有完全禁止使用,除了这类的,其它必须使用英文。但是有一些特例,比如: Log4J,J2EE 这种
4
通for
,2
通to
也是被允许的。
- 【强制】代码和注释中避免使用任何人类语言中的种族歧视性或者侮辱性词语。
这个稍微注意一下就行,基本上也没有人会刻意这么做,阿里把这个列出来,这里面应该有故事。
- 【强制】类名使用 UpperCamelCase 风格,以下情形例外:DO/PO/DTO/BO/VO/UID 等。
一些约定俗成的东西,比如 VO,如果强制要求那么就会变成 UserViewObject 反而不够清晰。
- 【强制】方法名、参数名、成员变量、局部变量都统一用 lowerCamelCase 风格
这个没什么好说的,基础的 java 语言规范
- 【强制】常量全部大写,使用下划线隔开,词义表达完整,可以稍微长一点。
这个也没有什么好说的,但是也不要太长,写句子一样。
- 【强制】抽象类命名使用 Abstract 或 Base 开头,异常使用 Exception 结尾,测试类以测试类的名称后面加Test 组成。
遵守就行了,没有什么好说的
- 【强制】类型与中括号紧挨相连来定义数组
比如 int[] arraryDemo
【强制】POJO 类中的任何布尔型变量,都不要加~~is~~
前缀,否则部分框架解析会引起序列化错误。
这里造成虚拟化的错误的主要原因还是在生成 get、set 方法的时候,如果我们定义一个
Boolean
类型的isSuccess
字段,那么我们常用的 Lombok 或者快捷键自动生成,生成的 get、set 方法并不是我们预期中的 getIsSuccess 和 setIsSuccess 而是 getSuccess 和 setSuccess,这就会导致,一些序列化框架与数据库对象映射的时候导致无法正确匹配。看到这里你会想,那我们应该怎么做,毕竟要制定一个规范,像阿里一样不让用吗?网上前篇一律的都是上面的解释,但是估计也没几个人实际去操作过,人云亦云。**一般在使用POJO中定义布尔类型的时候用封装类型 Boolean,不要使用基本类型boolean,在使用封装类型的时候 Lombok 自动生成的 get、set 方法会如我们预期一样,但是如果使用的是基本类型,择会将 **
**is**
**自动去除掉。 多以在我的团队里,我要求的是POJO类任何的布尔型变量,都要使用封装类型,并且留意 ****is**
问题。
- 【强制】**POJO类任何的布尔型变量,都要使用封装类型,并且留意 **
**is**
问题。
这个是不同于阿里规范的,我希望保证数据库 is_xxxx 与 POJO 类中字段完全统一,自动映射,而不是通过设置 的方式完成映射关系。
- 【强制】包名全小写,每个分割符之间有且仅有一个自然语义的英语单词,包名统一用单数形式,类名如果有复数含义可以使用复数。、
可以理解为包即为复数概念,所以名称不用再加上复数
- 【强制】避免在子父类的成员变量之间,或者不同代码块的局部变量之间采用完全相同的命名,包括类方法的参数也要避免与成员变量重名,引起误解
虽然 java 中由于不同作用域的影响,是允许同名存在的,并且编译也 ok , 但是如果不加约束,这种同名情况泛滥,就会导致项目难以维护,会让人在排查问题的时候抓狂。
- 【强制】杜绝完全不规范的英文缩写,避免望文不知意。
建议缩写的时候百度一下,除了一些行业内大家约定俗成的,尽量不要缩写。不差那点内存。
【推荐】【强制】为了达到代码自解释的目的,任何自定义编程元素在命名时,使用完整的单词。
这里让我想到了,之前看的一本书好像是《重构》, 大致意思就是,如果当你发现你的代码需要大篇幅的注释的时候,证明这段代码需要重构了。如果方法命名规范,逻辑清晰,甚至不需要写注释。
禁止使用 int a ; 这种定义方式。
- 【推荐】在常量与变量命名时,表示类型的名词放在词尾,增加可读性。
这个大家一般都会默认遵循,算是基本素养了。举几个正反例子。
正例:startTime/workQueue/nameList
反例:stateAt/queueOfWork/listName
- 【推荐】如果模块、接口、类、方法使用了设计模式,在命名的时候体现出来具体的模式。
正例:public class OrderFactory
public class LoginProxy
public class ResourceObserver
- 【推荐】在接口类中方法和属性不要加任何修饰符号,保持代码简洁,加上有效 Javadoc 注释。尽量不要在接口定义常量,如果定义,最好确定该常量与接口方法相关,并且是整个应用的基础常量。
没有特别的要求,现在基本上多余的代码 IDEA 会提示,或者代码是暗灰的,表示无意义可以删除掉。
- 接口和实现类命名的两套规则:
- 【强制】先通过 Service 接口暴露服务,内部实现类通过后缀加 Impl,进行区分。
- 【推荐】如果形容一些能力的接口名称,取对应形容词为接口名(通常是 -able 结尾的形容词)
其实在大多数情况下,Service 和 Impl 都是一一对应的,基于 SOA 的理念有点牵强了,但是这也成了java里默认的规则了,所以就按这个来做吧。
【参考】【强制】枚举类名带上Enum后缀,枚举成员名称全大写,单词用下划线隔开
这个遵守就行了,没什么好说的。
- 【参考】【强制】各层命名规约:
- Service/DAO 层命名规约:
- 获取单个对象的方法用 get 做前缀
- 获取多个用 list 做前缀,复数结尾,如:listObjects
- 获取统计值的方法用 count 做前缀
- 插入方法用 save/insert 做前缀
- 删除方法用 remove/delete 做前缀
- 修改方法用 update 做前缀
- 领域模型命名规约:
- 数据对象:xxxDO,xxx即为数据表名
- 数据传输对象:xxxDTO,xxx 为业务领域相关名称
- 展示对象:xxxVO, xxx 一般为前端网页名称
- POJO 是 DO/DTO/BO/VO 的统称,禁止命名为 xxxPOJO
- Service/DAO 层命名规约:
二、定义常量
- 【强制】不允许任何魔法值,直接出现在代码里
这个就不解释了,魔法值会让代码可读性大大降低。
- 【强制】long 或 Long 赋值时,使用大写 L , 小写
l
容易和数字1
混淆
这个很好理解,不解释
- 【强制】浮点数类型同上,统一用大写 D 或 F
虽然 Double 类型可以不加 D,但是便于理解要求加上D
- 【推荐】不要使用一个常量类维护所有常量,按功能进行归类,分开维护
全部写在一个类里不易维护。
- 【推荐】常量复用分五层:跨应用,应用内,子工程内,包内,类内
- 跨应用:放二方库(公司内部中央仓库)通常为 client.jar 中的 constant 目录下
- 应用内:一方库(本项目子工程依赖的库) 通常为子模块中的 constant 目录下
- 子工程中共享:当前子工程 constant 目录下
- 包内共享:当前包下单独的 constant 目录下
- 类内共享:直接定义 private static final
- 【推荐】如果变量值仅在一个固定范围内变化用 枚举 类型来定义
比如一年四季,一周七天,性别男女
三、代码格式
- 【强制】如果大括号内为空,简洁写成
{}
即可,如果是非空按如下格式
public void addFilterCharacter(String filterCharacter, Integer type) {
if (xxx) {
...
} else {
...
}
}
左大括号前不换行,左大括号后换行,右大括号前换行
- 【强制】左右小括号与相邻字符之间不需要空格,大括号需要加空格
if (a==b) √
if( a== b ) ×
- 【强制】if/for/while/switch/do 等保留字左右括号之间必须加空格
if (a==b) {} √
if(a==b){} ×
- 【强制】任何二目、三目运算符左右两边都需要加一个空格
a = 1 √
a=1 ×
- 【强制】采用4个空格缩进,禁止使用 Tab 字符
这个主要是不同的编辑器以及不同的同事可能使用习惯不一样,就会提交代码的时候相互覆盖的问题,为了保证统一,强制要求 1个 tab = 4 个空格
- 【强制】注释的双斜线与注释内容之间有且仅有一个空格
// 这是一个正确的单行注释
//这是一个错误的单行注释
- 【强制】在进行类型强制转换时,右括号与轻质转换值之间不要加任何空格
int num = (int)doubuleNum + 2; ✔
int num = (int) doubuleNum + 2; ×
- 【强制】单行字符数限制不超过120个,超出需要换行,换行需要遵守以下原则:
- 第二行相对第一行缩进四个空格,从第三行开始与第二行对齐
- 运算符与下文一起换行
- 方法调用点符号与下文一起换行
- 方法调用中的多个参数换行,从逗号后开始换行
- 货号前不要换行
public void updateFilterCharacter(Integer id, String filterCharacter) {
lambdaUpdate().eq(EmailGlobalSetting::getId, id)
.set(EmailGlobalSetting::getFilterCharacter, filterCharacter)
.set(EmailGlobalSetting::getUpdateTime, LocalDateTime.now())
.update();
}
- 【强制】方法多个参数逗号后面必须加空格
public void updateFilterCharacter(Integer id, String filterCharacter) {}
- 【强制】IDE 的 text file encoding 设置为 UTF-8; IDE 中文件的换行符使用 Unix 格式,不要使用 windows
编码相信大家都能找到在哪设置,这里贴一下换行符修改位置
- 【强制】单个方法的总行数不超过80行
这个我要求的比较严格,我们要求不超过50行。不包括注释,以及一些格式换行。
- 【推荐】没有必要增加若干空格使变量的赋值等号与上一行对应位置等号对其
这个没有特别要求,如果你又代码洁癖,也可以这么做
// 正常这样就可以(推荐这样)
int one = 1;
long two = 2L;
float three = 3F;
// 这样也不算错
int one = 1;
long two = 2L;
float three = 3F;
- 【推荐】不同逻辑、不同语义、不同业务的代码之间插入一个空行,分割开来以提高可读性
我们写代码就类似于叙述一件事情一样,当一段落说完,添加一个空行,区分上下段落,便于理解代码层次。当然也可一行注释。