开发规范手册

基础

  1. 推荐 防御式编程
  2. 推荐 声明式编程
  3. 推荐 测试驱动编程

公共

基础

  1. 强制 long或者Long初始赋值时,使用大写的L,不能是小写的l,小写容易跟数字1混淆,造成误解。

    • 说明:Long a= 2L;写的是数字的21,还是Long型的2?
  2. 强制 IDE的textfileencoding设置为UTF-8;IDE中文件的换行符使用Unix格式,不要使用Windows格式。

  3. 强制 避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可。

  4. 强制 所有的覆写方法,必须加@Override注解。

  5. 强制 Object的equals方法容易抛空指针异常,应使用常量或确定有值的对象来调用equals。

  6. 强制 日志必须使用自有受控的日志接口进行输出

  7. 推荐 尽量使用短生命周期的变量,使模块间的相互影响降到最低。

  8. 推荐 模块内非公开的方法和字段一律使用private修饰。

  9. 推荐 公开方法方法返回值尽量不要返回null,如果必要通过注解注明

  10. 强制 异常处理原则

  1. 明确异常:只有在真正的异常情况下抛出异常,不要使用异常来处理正常的控制流。

  2. 提供有意义的异常信息:当抛出异常时,提供清晰、详细的信息,以帮助其他开发者理解和解决问题。

  3. 最小化捕获范围:尽量减少 try-catch 块的大小,只捕获你期望处理的特定异常,而不是捕获所有异常。

  4. 不要吞掉异常:捕获异常后,要么处理它,要么重新抛出。避免空的 catch 块,这可能会掩盖问题。

  5. 使用特定的异常:尽量抛出和捕获具体的异常类型,而不是使用通用的异常,如 ExceptionRuntimeException

  6. 清理资源:确保在异常发生时,所有的资源(如文件、数据库连接等)都被正确地关闭或释放。可以考虑使用 finally 块或其他清理机制。

  7. 避免在构造函数中抛出异常:如果对象的构造函数抛出异常,对象可能处于不稳定的状态。考虑使用工厂方法或其他初始化方法。

  8. 文档化异常:在方法或函数的文档中明确指出它可能抛出哪些异常,以及在什么情况下。

  9. 考虑线程安全:在多线程环境中,确保异常处理是线程安全的。

  10. 使用异常链:当捕获一个异常并抛出另一个异常时,考虑将原始异常作为新异常的原因,以保留完整的异常堆栈信息。

  11. 避免频繁的异常:异常处理可能会影响性能,所以避免在性能关键的代码路径中频繁地抛出和捕获异常。

结构

  1. 推荐 90%函数代码行数需少于50
  2. 推荐 代码重复度少于5%
  3. 推荐 方法圈复杂度小于等于15

并发

  1. 强制 创建线程或线程池时请指定有意义的线程名称,方便出错时回溯。
  2. 强制 高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁。
    • 说明:尽可能使加锁的代码块工作量尽可能的小,避免在锁代码块中调用RPC方法。

日志

  1. 强制 划分不同日志等级,并有分级开关控制
  2. 强制 高等级日志不能过度使用,只在重要时机使用
  3. 强制 Error级别不用于打印业务逻辑相关阶段性日志
  4. 推荐 日志使用统一的格式,便于查找过滤
  5. 推荐 特殊事件可以添加标识便于调试时查看

单元测试

  1. 强制 好的单元测试必须遵守AIR原则。说明:单元测试在线上运行时,感觉像空气(AIR)一样并不存在,但在测试质量的保障上,却是非常关键的。好的单元测试宏观上来说,具有自动化、独立性、可重复执行的特点。

    • A:Automatic(自动化)
    • I:Independent(独立性)
    • R:Repeatable(可重复)
  2. 强制 单元测试应该是全自动执行的,并且非交互式的。测试框架通常是定期执行的,执行过程必须完全自动化才有意义。输出结果需要人工检查的测试不是一个好的单元测试。单元测试中不准使用System.out来进行人肉验证,必须使用assert来验证。

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

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

  5. 强制 核心业务、核心应用、核心模块的增量代码确保单元测试通过。

  6. 推荐 编写单元测试代码遵守BCDE原则,以保证被测试模块的交付质量。

    • B:Border,边界值测试,包括循环边界、特殊取值、特殊时间点、数据顺序等。
    • C:Correct,正确的输入,并得到预期的结果。
    • D:Design,与设计文档相结合,来编写单元测试。
    • E:Error,强制错误信息输入(如:非法数据、异常流程、非业务允许输入等),并得到预期的结果。
  7. 推荐 对于不可测的代码建议做必要的重构,使代码变得可测,避免为了达到测试要求而书写不规范测试代码。

  8. 推荐 和数据库相关的单元测试,可以设定自动回滚机制,不给数据库造成脏数据。或者对单元测试产生的数据有明确的前后缀标识。

  9. 推荐 尽量使用显式断言

    • 应该总是优先使用 assertEquals(a, b) 而不是 assertTrue(a == b)
  10. 推荐 确保用例覆盖边界值

    • 对于数字, 测试负数, 0, 正数, 最小值, 最大值, NaN (非数字), 无穷大等。 对于字符串, 测试空字符串, 单字符, 非 ASCII 字符串, 多字节字符串等。 对于集合类型, 测试空, 1, 第一个, 最后一个等。 对于日期, 测试 1月1号, 2月29号, 12月31号等。
  11. 强制 单元测试需要保证测试代码同步性,对于异步代码的测试需要同步化

    • 不应使用Thread.sleep进行结果同步,这样会造成不确定性

二方库规范

  1. 强制 定义GAV遵从以下规则:

    • GroupID格式:com.{标识}.业务线.[子业务线],最多4级。
    • {标识} 例如:google等
    • ArtifactID格式:产品线名-模块名。语义不重复不遗漏,先到中央仓库去查证一下。
    • Version:详细规定参考下方。
  2. 强制 版本规范

    • 项目名称-v主版本号.次版本号.修订版本号.编译版本号.[时间]-[意图或变种]-阶段
      • 项目名称主要标识项目与产品
      • 主版本号大版本标识(迭代可能存在不兼容)
      • 次级版本号主要用一般性功能迭代
      • 修订版本号主要用于测试时 BUG 修复与小范围调整
      • 编译版本号每次构建所对应的版本号
      • 意图或变种指明此版本的使用意图
      • 阶段标识此次迭代所处的阶段
  3. 强制 禁止在子项目的pom依赖中出现相同的GroupId,相同的ArtifactId,但是不同的Version。

三方库规范

  1. 强制 项目中引用第三方库必须指定明确的版本,不应使用+的形式依赖

  2. 强制 同一个项目各个模块应使用同一版本的依赖

  3. 推荐 尽量隔离和封装对三方库的调用。这样,如果将来需要替换或移除该库,更改会更加集中和简单。

. 推荐 为直接依赖添加注释,并简要说明为什么需要它们。

版本控制

  1. 强制 整个开发流程必须按照版本控制规范模型进行

  2. 强制 一个长期维护版本只能有一个主线分支

  3. 强制 版本控制提交注释必须符合规范

计划

  1. 强制 定制的任务必须可衡量与评估(参考SMART原则)

  2. 推荐 开发与自测时间比例不应大于1

  3. 推荐 划分后的单个可执行的任务周期不应大于2天

  4. 推荐 任务的优先级应以重要性优先原则

服务端

  1. 强制除非有高版本JDK特性必须使用,项目JDK版本统一使用11

  2. 强制 迭代上线都必须上对应的预发布环境

  3. 强制 严格执行上线流程规范(需要落实)

  4. 强制 严格执行代码管理规范(需要落实)

  5. 推荐 能随时随地及时处理线上出现的问题(对运维和支撑的同事是强制的,其它团队建议)

  6. 推荐 文档尽量使用公司统一提供的文档模板

客户端

  1. 强制 客户端内置的服务器地址必须为域名

  2. 强制 发布版本必须与测试通过版本一致

  3. 强制 正式发布的产品必须经过混淆处理

  4. 强制 系统api的使用必须考虑兼容性与用户权限

  5. 强制 每个发布或线上测试的产品必须留档添加说明

  6. 强制 所有调试日志必须可控,线上版本不允许有调试日志产生

  7. 推荐 业务逻辑需要考虑应用异常中断造成的影响

埋点

  1. 强制 埋点名称与参数必须简短明确

    • 名称不宜过长(<10个字符)
    • 名称使用缩写
    • 名称格式
      • xxx_xxx_xx 下划线分隔
      • xxxXxxx 驼峰
  2. 强制 同一个埋点名下的参数必须有统一的释义,不能出现同一个埋点参数不同用途

  3. 强制 新增埋点时必须评估埋点发送数量(极端情况下)

  4. 强制 根据埋点的意义和数量对埋点进行分级或精细控制,高频和数量大的埋点必须受服务端控制

  5. 强制 每个埋点必须确定一个维护人,维护人需要根据埋点统计的信息,定期优化整理其名下的所有埋点

  6. 强制 新增埋点必须在埋点管理页面,添加埋点信息

业务名称 埋点名称 说明文档 维护人 需求方 是否弃用 埋点等级 新增日期
XXX XXXX XXX XXX XXX运营 业务 2019-09-12
  1. 强制 每个埋点必须有对应的说明文档(如果当时较为紧急,可以7天内必须补齐文档)

  2. 强制 埋点不应影响业务逻辑

  3. 推荐 新增埋点必须考虑后续查询与分析的便利性

  4. 推荐 埋点的参数尽量一个参数对应一个值,如果参数不够一个参数传多个值时请使用json格式

  5. 推荐 尽量减少孤立埋点使用(无上下文关系)

  6. 推荐 埋点参数只有一个值时不应携带描述性信息
    错误:width=18p
    正常:1800