DevOps 编程规约

muse117 · November 10, 2019 · 16 hits

一、 编程规约

(一)命名规约

  1. 代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。
    中英文的命名方式,会显得很另类,而且不方便理解,在某些编译器下,会提示单词错误等。推荐使用 intellij IDEA,会对英文拼写做校验。
  2. 注意使用驼峰形式的命名方式,类名使用 UpperCamelCase 风格,方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格,严格遵从驼峰形式。
  3. 常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。
    有些人为了缩短名字,往往使语义更加难以理解,方法的命名也同样如此。
  4. 抽象类命名使用 Abstract 或 Base 开头;异常类命名使用 Exception 结尾;测试类命名以它要测试的类的名称开始,以 Test 结尾。枚举类命名以 enum 结尾。枚举中的枚举成员必须全大写,而且单词间需要用下划线隔开。
    力求一眼能够看出特殊类的种类。
  5. 包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用单数形式,但是类名如果有复数含义,类名可以使用复数形式。
  6. 接口类中的方法和属性不要加任何修饰符号 (public 也不要加),保持代码的简洁性,并加上有效的 Javadoc 注释。
    接口注释的时候,必须注明方法的功能点,出入参的含义,如果有枚举的情况,需要关联到对应的枚举类,或者标出枚举的列表。
  7. 各层命名规约:
    A) Service/DAO 层方法命名规约
    1) 获取单个对象的方法用 get 做前缀。
    2) 获取多个对象的方法用 list 做前缀。
    3) 获取统计值的方法用 count 做前缀。
    4) 插入的方法用 save(推荐) 或 insert 做前缀。
    5) 删除的方法用 remove(推荐) 或 delete 做前缀。
    6) 修改的方法用 update 做前缀。
    B) 领域模型命名规约
    1) 数据对象:xxxDO,xxx 即为数据表名。
    2) 数据传输对象:xxxDTO,xxx 为业务领域相关的名称。
    3) 展示对象:xxxVO,xxx 一般为网页名称。
    4) POJO 是 DO/DTO/BO/VO 的统称,禁止命名成 xxxPOJO

(二)常量定义

  1. long 或者 Long 初始赋值时,必须使用大写的 L,不能是小写的 l,小写容易跟数字 1 混淆,造成误解。
    推荐使用 intellij IDEA,会对这个问题进行自动校验。
  2. 不要使用一个常量类维护所有常量,应该按常量功能进行归类,分开维护。
    如:缓存相关的常量放在类:CacheConsts 下;系统配置相关的常量放在类:ConfigConsts 下。枚举也是同样的要求。
    说明:大而全的常量类,非得使用查找功能才能定位到修改的常量,不利于理解和维护。
  3. 如果变量值仅在一个范围内变化用 Enum 类。如果还带有名称之外的延伸属性,必须使用 Enum 类,下面正例中的数字就是延伸信息,表示星期几。
    正例:public Enum{ MONDAY(1), TUESDAY(2), WEDNESDAY(3), THURSDAY(4), FRIDAY(5), SATURDAY(6), SUNDAY(7);}
  4. 常量的复用层次有五层:跨应用共享常量、应用内共享常量、类内共享常量。
    1) 跨应用共享常量:通常是 api 中的 constant 目录下。
    2) 应用内共享常量:放置 service 中的 constant 目录下。
    3) 类内共享常量:直接在类内部 private static final 定义。
    将常量区分开,便于了解常量的作用域,防止相互串用。
  5. 方法内的常量定义尽量谨慎,能够避免就尽量避免。过多的常量定义,容易使代码可读性变得很差。

(三)格式规约

  1. 注解必须放置在方法体上方,严禁和方法体存在同一行。
    反例:@override public void …
  2. 统一使用 intellij IDEA 中默认的 format 对代码进行格式化。
  3. 单行字符数限制不超过 120 个,超出需要换行,换行时遵循如下原则:
    1) 第二行相对第一行缩进 4 个空格,从第三行开始,不再继续缩进,参考示例。
    2) 运算符与下文一起换行。
    3) 方法调用的点符号与下文一起换行。
    4) 在多个参数超长,逗号后进行换行。
    5) 在括号前不要换行,见反例。
    例如:

    1234
    sb.append("zi").append("xin")...    .append("huang")...    .append("huang")...    .append("huang");

  4. IDE 的 text file encoding 设置为 UTF-8;IDE 中文件的换行符使用 Unix 格式,不要使用 windows 格式。便于一些代码中的 shell 脚本不用重新做修改。

  5. for 循环和 if 之后,如果只有一行代码,也必须加上中括号。便于后续的阅读以及代码修改中不会出现问题。
  6. 方法中需要进行参数校验的场景:
    1) 调用频次低的方法。
    2) 执行时间开销很大的方法,参数校验时间几乎可以忽略不计,但如果因为参数错误导致中间执行回退,或者错误,那得不偿失。
    3) 需要极高稳定性和可用性的方法。
    4) 对外提供的开放接口,不管是 RPC/API/HTTP 接口。
    5) 敏感权限入口。
  7. 方法中不需要参数校验的场景:
    1) 极有可能被循环调用的方法,不建议对参数进行校验。但在方法说明里必须注明外部参数检查。
    2) 底层的方法调用频度都比较高,一般不校验。毕竟是像纯净水过滤的最后一道,参数错误不太可能到底层才会暴露问题。一般 DAO 层与 Service 层都在同一个应用中,部署在同一台服务器中,所以 DAO 的参数校验,可以省略。
    3) 被声明成 private 只会被自己代码所调用的方法,如果能够确定调用方法的代码传入参数已经做过检查或者肯定不会有问题,此时可以不校验参数。

(四)OOP 规约

  1. 关于基本数据类型与包装数据类型的使用标准如下:
    1)所有的 POJO 类属性必须使用包装数据类型。
    2)RPC 方法的返回值和参数必须使用包装数据类型。
    3)所有的局部变量【推荐】使用基本数据类型。
    说明:POJO 类属性没有初值是提醒使用者在需要使用时,必须自己显式地进行赋值,任何 NPE 问题,或者入库检查,都由使用者来保证。
    正例:数据库的查询结果可能是 null,因为自动拆箱,用基本数据类型接收有 NPE 风险。
    反例:比如显示成交总额涨跌情况,即正负 x%,x 为基本数据类型,调用的 RPC 服务,调用不成功时,返回的是默认值,页面显示:0%,这是不合理的,应该显示成中划线-。所以包装数据类型的 null 值,能够表示额外的信息,如:远程调用失败,异常退出。

  2. POJO 类必须写 toString 方法。
    使用 IDE 的中工具:source> generate toString 时,如果继承了另一个 POJO 类,注意在前面加一下 super.toString。
    说明:在方法执行抛出异常时,可以直接调用 POJO 的 toString() 方法打印其属性值,便于排查问题。

  3. 在对外暴露的接口的 returnResult 中,禁止使用问号来表示返回类型,也就是说不能出现一个接口多种返回格式,不便于理解和对接。
  4. 业务接口禁止使用可变参数作为接口暴露。
    例如:

    1
    void (Integer ...userId);

  5. 接口过时必须加@Deprecated注解,接口调用不允许调用过时的类或方法。如果对接口进行过时注解,需要声明为何过时,以及造成的影响,还有过时时间。

  6. 所有的包装类的比较都是用 equals 来比较,防止一些特殊的坑。
  7. 类内方法定义顺序依次是:公有方法或保护方法>私有方法>getter/setter 方法。
    一般情况下,对实现类,比较关注的是公有方法或保护方法,私有方法只在方法内部使用,关注度相对较低,getter/setter 在写完之后基本不再关注和修改。
  8. 对于重复代码,将代码拎出来调用,减少了代码量,方便后续问题的修改。通用的方法,可以作为 util 提供出来。
  9. 所有 POJO 类属性不能有默认值,因为很多时候,默认值是有特殊意义的。
  10. 构造函数内禁止出现业务逻辑,如果需要有,移动到 init 方法中,初始化的时候会先调用构造函数,然后调用 init 方法,这样符合单一职责的设计原则。
  11. 针对数据库的一张表,原则上,一个 xml,一个 mapper,一个 domain 针对同一个表,不针对多张表。

(五)注释规约

  1. 类、类属性、类方法的注释必须使用 Javadoc 规范,使用/*内容/格式,不得使用//xxx 方式。
    使用这样的提示,可以在不进入方法或者类就可以查看注释。
  2. 所有的抽象方法 (包括接口中的方法) 必须要用 Javadoc 注释、除了返回值、参数、异常说明外,还必须指出该方法做什么事情,实现什么功能。
  3. 对于具有枚举属性的字段,必须加注释,列举出相应的枚举项。也可使用{@link ...}或者@see ...
  4. 所有的类都必须添加创建者信息。
    此处提供一个简单模板:

    1234567
    /** * Created with IntelliJ IDEA. * Description: * User: ${USER} * Date: ${YEAR}-${MONTH}-${DAY} * Time: ${TIME} */

  5. 注释掉的代码尽量要配合说明,而不是简单的注释掉。
    说明:代码被注释掉有两种可能性:
    1) 后续会恢复此段代码逻辑。
    2) 永久不用。
    前者如果没有备注信息,难以知晓注释动机。后者建议直接删掉 (代码仓库保存了历史代码)

  6. 禁止滥用注释,比如 POJO 类中的 get/set 方法,没有必要加入注释。
  7. 特殊注释标记,请注明标记人与标记时间。注意及时处理这些标记,通过标记扫,经常清理此类标记。线上故障有时候就是来源于这些标记处的代码。
    1) 待办事宜 (TODO):(标记人,标记时间,[预计处理时间]) 表示需要实现,但目前还未实现的功能。这实际上是一个 Javadoc 的标签,目前的 Javadoc 还没有实现,但已经被广泛使用。只能应用于类,接口和方法 (因为它是一个 Javadoc 标签)。
    2) 错误,不能工作 (FIXME):(标记人,标记时间,[预计处理时间]) 在注释中用 FIXME 标记某代码是错误的,而且不能工作,需要及时纠正的情况。

(六)日志规约

  1. 对 trace/debug/info 级别的日志输出,必须使用条件输出形式或者使用占位符的方式。
1
logger.debug("Processing trade with id: " + id + " symbol: " + symbol);

说明:如果日志级别是 warn,上述日志不会打印,但是会执行字符串拼接操作,如果 symbol 是对象,会执行 toString() 方法,浪费了系统资源,执行了上述操作,最终日志却没有打印。
正例:(条件)

123
if (logger.isDebugEnabled()) {   logger.debug("Processing trade with id: " + id + " symbol: " + symbol);}

正例:(占位符)

1
logger.debug("Processing trade with id: {} symbol : {} ", id, symbol);

(七)建表规约

  1. 表名、字段名必须使用小写字母或数字;禁止出现数字开头,禁止两个下划线中间只出现数字。在建字段的时候,两个单词之间使用下划线,以便于 generator 创建相关文件时,命名的准确。
  2. 禁用保留字,如 desc、range、match、delayed 等,请参考MySQL 官方保留字。也防止出现类似 type 这种特殊字段,具体可以查看 intellij IDEA 中 xml 校验。
  3. 小数类型为 decimal,禁止使用 float 和 double。
    说明:float 和 double 在存储的时候,存在精度损失的问题,很可能在值的比较时,得到不正确的结果。如果存储的数据范围超过 decimal 的范围,建议将数据拆成整数和小数分开存储。
  4. 表必备三字段:id,create_time,update_time,sys_time。
    sys_time 是随字段新增更新而修改,既能表示数据的时间,也能够为后续数据清洗提供依据。
  5. 使用 number 字段时,需要根据需求指定长度。

(八)SQL 规约

  1. 不要使用 count(列名) 或 count(常量) 来替代count()count()就是 SQL92 定义的标准统计行数的语法,跟数据库无关,跟 NULL 和非 NULL 无关。
    说明:count()会统计值为 NULL 的行,而 count(列名) 不会统计此列为 NULL 值的行。
  2. 数据订正时,删除和修改记录时,要先 select,避免出现误删除,确认无误才能执行更新语句。
  3. 在表查询中,一律不要使用作为查询的字段列表,需要哪些字段必须明确写明。推荐使用 generator 来创建数据库相关文件。
    说明:1) 增加查询分析器解析成本。2) 增减字段容易与 resultMap 配置不一致。
  4. sql 中禁止出现存在业务逻辑的数据,比如魔法数。相当于把业务逻辑隐藏在 sql 中。
No Reply at the moment.
You need to Sign in before reply, if you don't have an account, please Sign up first.