编程规约
命名风格:
1.代码中命名不能用下划线或者美元符号开头,也不能用下划线和美元符号结尾
2.严禁使用拼音和英文混合模式,不能直接使用中文方式,
3.代码注释中避免是用任何语言的种族歧视词语
4.类名用UpperCamelCase风格
5.方法、参数名、成员变量、局部变量同意使用lowerCamelCase风格
6.常量命名前全部大写,单次间用下划线隔开
7.抽象雷命名以Abstract或者Base开头,异常类名使用Exception结尾,测试类命名使用Test结尾
8.类型中括号紧挨相连来表示数组
9.类中任何布尔类型变量都不要使用is开头,否则部分框架解析会引起序列化错误
10包名称统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词,包名统一使用单数形式,但是类名如果有复数含义,类名可以使用复数形式
11.避免在子父类成员变量之间、或者不同代码块的局部变量之间采用完全相同的命名,使可理解性降低
说明:子类、父类成员变量名相同,即使是 public 类型的变量也能够通过编译,另外,局部变量在同一方 法内的不同代码块中同名也是合法的,这些情况都要避免。对于非 setter/getter 的参数名称也要避免与成 员变量名称相同。
12.杜绝完全不规范的缩写,避免望文不如义
13.为了达到代码自解释的目标,任何自定义变成元素在命名时候,使用尽量完整的单次组合来表达
14.在常量与变量的命名时候,表示类型的名词放在词尾,以提升辨识度
15.如果模块、接口、类、方法使用了设计模式,在命名时候需要体检具体模式(OrderFactory、 LoginProxy、ResourceObserver)
16.接口类中的方法和属性不要添加任何修饰符号,保持代码的简洁性,并加上有效的注释,尽量不要在接口里面定义变量,如果一定要定义变量,确定与接口方法相关,并且是整个应用的基础常量
17.各层命名规约:
A) Service/DAO 层方法命名规约
1) 获取单个对象的方法用 get 做前缀。
2) 获取多个对象的方法用 list 做前缀,复数结尾,如:listObjects。
3) 获取统计值的方法用 count 做前缀。
4) 插入的方法用 save/insert 做前缀。
5) 删除的方法用 remove/delete 做前缀。
6) 修改的方法用 update 做前缀。
B) 领域模型命名规约 Java 开发手册 4/59
1) 数据对象:xxxDO,xxx 即为数据表名。
2) 数据传输对象:xxxDTO,xxx 为业务领域相关的名称。
3) 展示对象:xxxVO,xxx 一般为网页名称。
4) POJO 是 DO/DTO/BO/VO 的统称,禁止命名成 xxxPOJO。
常量定义:
1.不允许任何魔法值(即未经预先定义的常量)直接出现在代码中。
2.不要使用一个常量类维护所有常量,要按常量功能进行归类,分开维护。 说明:大而全的常量类,杂乱无章,使用查找功能才能定位到修改的常量,不利于理解,也不利于维护。 正例:缓存相关常量放在类 CacheConsts 下;系统配置相关常量放在类 SystemConfigConsts 下。
3.常量的复用层次有五层:跨应用共享常量、应用内共享常量、子工程内共享常量、包 内共享常量、类内共享常量。
1) 跨应用共享常量:放置在二方库中,通常是 client.jar 中的 constant 目录下。
2) 应用内共享常量:放置在一方库中,通常是子模块中的 constant 目录下。 反例:易懂变量也要统一定义成应用内共享常量,两位工程师在两个类中分别定义了“YES”的变量: 类 A 中:public static final String YES = “yes”; 类 B 中:public static final String YES = “y”; A.YES.equals(B.YES),预期是 true,但实际返回为 false,导致线上问题。
3) 子工程内部共享常量:即在当前子工程的 constant 目录下。
4) 包内共享常量:即在当前包下单独的 constant 目录下。
5) 类内共享常量:直接在类内部 private static final 定义。
4.如果变量值仅在一个固定范围内变化用 enum 类型来定义。 说明:如果存在名称之外的延伸属性应使用 enum 类型,下面正例中的数字就是延伸信息,表示一年中的 第几个季节。
代码格式:
1.如果是大括号内为空,则简洁地写成{}即可,大括号中间无需换行和空格;如果是非 空代码块则:
1) 左大括号前不换行。
2) 左大括号后换行。
3) 右大括号前换行。
4) 右大括号后还有 else 等代码则不换行;表示终止的右大括号后必须换行。
2.左小括号和右边相邻字符之间不出现空格;右小括号和左边相邻字符之间也不出现空 格;而左大括号前需要加空格
3.if/for/while/switch/do 等保留字与括号之间都必须加空格。
4.任何二目、三目运算符的左右两边都需要加一个空格。
5.采用 4 个空格缩进,禁止使用 Tab 字符。
6.注释的双斜线与注释内容之间有且仅有一个空格。
7.在进行类型强制转换时,右括号与强制转换值之间不需要任何空格隔开。
8.单行字符数限制不超过 120 个,超出需要换行,换行时遵循如下原则:
1)第二行相对第一行缩进 4 个空格,从第三行开始,不再继续缩进,参考示例。
2)运算符与下文一起换行。
3)方法调用的点符号与下文一起换行。
4)方法调用中的多个参数需要换行时,在逗号后进行。
5)在括号前不要换行
9.方法参数在定义和传入时,多个参数逗号后面必须加空格。
10.IDE 的 text file encoding 设置为 UTF-8; IDE 中文件的换行符使用 Unix 格式,不要 使用 Windows 格式。
11.单个方法的总行数不超过 80 行。
12.没有必要增加若干空格来使变量的赋值等号与上一行对应位置的等号对齐。
13.不同逻辑、不同语义、不同业务的代码之间插入一个空行分隔开来以提升可读性。 说明:任何情形,没有必要插入多个空行进行隔开。
OOP规约:
1.避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可。
2.所有的覆写方法,必须加@Override 注解。
3.相同参数类型,相同业务含义,才可以使用可变参数,避免使用 Object。 说明:可变参数必须放置在参数列表的最后。(建议开发者尽量不用可变参数编程)
4.外部正在调用或者二方库依赖的接口,不允许修改方法签名,避免对接口调用方产生 影响。接口过时必须加@Deprecated 注解,并清晰地说明采用的新接口或者新服务是什么。
5.不能使用过时的类或方法。
6.任何货币金额,均以最小货币单位且整型类型来进行存储。
7.当一个类有多个构造方法,或者多个同名方法,这些方法应该按顺序放置在一起,便 于阅读,此条规则优先于下一条。
8.类内方法定义的顺序依次是:公有方法或保护方法 > 私有方法 > getter / setter 方法。
说明:公有方法是类的调用者和维护者最关心的方法,首屏展示最好;保护方法虽然只是子类关心,也可 能是“模板设计模式”下的核心方法;而私有方法外部一般不需要特别关心,是一个黑盒实现;因为承载 的信息价值较低,所有 Service 和 DAO 的 getter/setter 方法放在类体最后。
9.setter 方法中,参数名称与类成员变量名称一致,this.成员名 = 参数名。在 getter/setter 方法中,不要增加业务逻辑,增加排查问题的难度。
日期时间:
1.日期格式化时,传入 pattern 中表示年份统一使用小写的 y。
2.在日期格式中分清楚大写的 M 和小写的 m,大写的 H 和小写的 h 分别指代的意义。
说明:日期格式中的这两对字母表意如下:
1) 表示月份是大写的 M;
2) 表示分钟则是小写的 m;
3) 24 小时制的是大写的 H;
4) 12 小时制的则是小写的 h。
3.不要在程序中写死一年为 365 天,避免在公历闰年时出现日期转换错误或程序逻辑错误
4.
并发处理:
1.获取单例对象需要保证线程安全,其中的方法也要保证线程安全。 说明:资源驱动类、工具类、单例工厂类都需要注意。
2.创建线程或线程池时请指定有意义的线程名称,方便出错时回溯。
控制语句:
1.在一个 switch 块内,每个 case 要么通过 continue/break/return 等来终止,要么 注释说明程序将继续执行到哪一个 case 为止;在一个 switch 块内,都必须包含一个 default语句,并且放在最后,即使他什么代码都没有。
2.当 switch 括号内的变量类型为 String 并且此变量为外部参数时,必须先进行 null 判断。
3.在 if/else/for/while/do 语句中必须使用大括号。
4.三目运算符 condition? 表达式 1 : 表达式 2 中,高度注意表达式 1 和 2 在类型对齐 时,可能抛出因自动拆箱导致的 NPE 异常。 说明:以下两种场景会触发类型对齐的拆箱操作: 1) 表达式 1 或表达式 2 的值只要有一个是原始类型。 2) 表达式 1 或表达式 2 的值的类型不一致,会强制拆箱升级成表示范围更大的那个类型。
5.在高并发场景中,避免使用”等于”判断作为中断或退出的条件。 说明:如果并发控制没有处理好,容易产生等值判断被“击穿”的情况,使用大于或小于的区间判断条件 来代替。
前后端规约:
1.前后端交互的 API,需要明确协议、域名、路径、请求方法、请求内容、状态码、响 应体。 说明:
1) 协议:生产环境必须使用 HTTPS。
2) 路径:每一个 API 需对应一个路径,表示 API 具体的请求地址:
a) 代表一种资源,只能为名词,推荐使用复数,不能为动词,请求方法已经表达动作意义。
b) URL 路径不能使用大写,单词如果需要分隔,统一使用下划线。
c) 路径禁止携带表示请求内容类型的后缀,比如”.json”,”.xml”,通过 accept 头表达即可。
3) 请求方法:对具体操作的定义,常见的请求方法如下:
a) GET:从服务器取出资源。
b) POST:在服务器新建一个资源。
c) PUT:在服务器更新资源。
d) DELETE:从服务器删除资源。
4) 请求内容:URL 带的参数必须无敏感信息或符合安全要求;body 里带参数时必须设置 Content-Type。
5) 响应体:响应体 body 可放置多种数据类型,由 Content-Type 头来确定。
2.前后端数据列表相关的接口返回,如果为空,则返回空数组[]或空集合{}。 说明:此条约定有利于数据层面上的协作更加高效,减少前端很多琐碎的 null 判断。
3.服务端发生错误时,返回给前端的响应信息必须包含 HTTP 状态码,errorCode、 errorMessage、用户提示信息四个部分。
说明:四个部分的涉众对象分别是浏览器、前端开发、错误排查人员、用户。其中输出给用户的提示信息 要求:简短清晰、提示友好,引导用户进行下一步操作或解释错误原因,提示信息可以包括错误原因、上 下文环境、推荐操作等。 errorCode:参考附表 3。errorMessage:简要描述后端出错原因,便于错误排 查人员快速定位问题,注意不要包含敏感数据信息。 正例:常见的 HTTP 状态码如下
1) 200 OK: 表明该请求被成功地完成,所请求的资源发送到客户端。
2) 401 Unauthorized: 请求要求身份验证,常见对于需要登录而用户未登录的情况。
3) 403 Forbidden:服务器拒绝请求,常见于机密信息或复制其它登录用户链接访问服务器的情况。
4) 404 Not Found: 服务器无法取得所请求的网页,请求资源不存在。
5) 500 Internal Server Error: 服务器内部错误。
4.在前后端交互的 JSON 格式数据中,所有的 key 必须为小写字母开始的 lowerCamelCase 风格,符合英文表达习惯,且表意完整。
5.errorMessage 是前后端错误追踪机制的体现,可以在前端输出到 type=”hidden” 文字类控件中,或者用户端的日志中,帮助我们快速地定位出问题。
6.HTTP 请求通过 body 传递内容时,必须控制长度,超出最大长度后,后端解析会出 错。 说明:nginx 默认限制是 1MB,tomcat 默认限制为 2MB,当确实有业务需要传较大内容时,可以通过调 大服务器端的限制。
7.在翻页场景中,用户输入参数的小于 1,则前端返回第一页参数给后端;后端发现用 户输入的参数大于总页数,直接返回最后一页。
8.