Java编程规范.md 8.16 KB

Java Bean规范

  • 模型要严格分离,DO是数据库模型,BO是服务层模型,VO是Gateway对外暴露的模型,服务之间、gateway和服务之间,传输的对象是BO,Gateway对外暴露的是VO,访问数据库的事DO
  • bean需要实现tostring方法。 如果加入到hashmap、hashtable、set之类容器的bean,需要实现hashcode和equals方法
  • 如非必要,使用int,long,double、float代替包装类Integer、Long、Double、Float (自动生成的DO除外)
  • 所有的BO、VO、DO,必须向前兼容,只能添加属性,不能废弃原字段,原字段必须支持并正确赋值。通过@Deprated注解标注,并明确规划在未来的某个版本删除
  • 所有的VO类型必须为全字符串类型(新增接口和字段)

数据库操作

  • Dao方法命名规范,必须以select、delete、insert、update开始
  • Dao层接口的命名由I + 表名 + Dao构成,例如:IUserBaseDao.java, 对应表user_base;
  • 除非必要,禁止在sql中做运算功能
  • 禁止任何跨库关联查询
  • 尽可能把数据库当KV存储使用
  • 除非必要,禁止使用 join 查询
  • 禁止出现一个数据库表创建多个DAO,一个表只允许在一个工程中使用
  • 从数据库中获取非关键信息失败时,使用默认值
  • 禁止每次查询静态配置表,应在进程内缓存
  • 禁止for、while循环中存在数据库操作,以批量替代
  • Mybatis返回一个对象时,sql语句中默认添加limit 1

缓存Redis使用

  • 数据持久化使用mysql,不依赖redis持久化
  • redis的操作归集到一个类中,禁止修改缓存,需要修改的时候,直接delete key(单个key存在高并发场景的计数器除外)
  • 对缓存更新不用采取数据库和缓存同步更新,首先更新数据库,再删除缓存;后续在使用时,再次触发缓存;禁止修改redis中数据
  • 进程内的缓存,使用yoho-core框架中的LocalCache,禁止自行创建全局变量和更新线程
  • 浏览类业务,比如资源位、商品等,必须支持二级缓存(服务灾备)
  • 向Redis写数据时,必需设置有效期
  • 使用前台的Redis时,必需使用yoho-core框架中的YHRedisTemplate、YHValueOperation等,禁止使用其他方式操作redis。使用外部redis,参考core中,自己定义template
  • 所有缓存必需提供清理接口,由写入的服务提供
  • 禁止for、while循环中操作缓存,以批量替代
  • 尽可能使用一个key完成多个维度数据的缓存,比如使用ZSet、Hashes
  • 缓存中默认保存字符串,对象转换为json后再存储到redis中,禁止采用其他方式序列化对象
  • 有效期超过90天,必需使用longexpire
  • 所有redis操作失败,必须支持回源数据库
  • 禁止使用集合的并、交,模糊key,例如keys *

消息队列

  • 消费者处理时保证幂等性,支持重复处理同样的消息
  • 消费者对于处理失败的消息,并且不能丢弃时,需抛出异常; 如果消息可以丢弃,则吃掉所有异常;
  • 对于非实时感知结果的操作,尽量使用MQ,由后台进程处理;
  • 对于MQ的使用,必须经过开发经理确认,才可以使用; 禁止私自使用MQ;
  • 如果无性能瓶颈的场景,禁止使用MQ;如果必要使用,需向团队报备;

线程使用

  • 禁止在Gateway和服务中自行创建线程,需要异步线程处理的任务,由后台进程完成
  • 除非必要,禁止使用ThreadLocal;每个线程使用时,必须首先remove
  • 创建线程、线程池必须要添加名称;
  • 创建大量线程(线程数量>5)、循环中创建线程,需要和模块负责人确认

服务调用

  • 请求外部系统时,统一使用service.call,比如erp、search、短信sp等
  • 多次服务调用时,如果没有必然联系,使用异步并发调用
  • 非关键请求时,传入默认值,比如获取用户vip信息、获取促销信息失败,用户仍然可以下单、查看购物车
  • 服务调用选择最小化信息的接口,提高响应速度和降低负载
  • 禁止在for、while循环中调用服务,均以批量接口替代
  • 一次接口调用处理过程,对同一个服务,只能消费一次,需要聚合请求

服务提供者

  • 服务处理异常流程,返回ServiceException,并定义服务错误码和接口错误码
  • 禁止使用true、false做为返回值代替各种含义,比如成功、失败等,必须定义明确的返回值(失败可用ServiceException代替)
  • 避免提供大而全的服务接口,为不同场景提供不同粒度的服务

日志打印

  • Gateway 和 服务的所有 restapi的入口和返回、关键路径,都要打印info级别日志。日志内容包括请求参数,关键响应结果(对于过长的响应结果,只打印关键信息)
  • 处理非自定义业务Exception(例如网络异常、数据库异常)的时候,需要打印WARN异常堆栈
  • 关键业务,例如注册、支付、订单等需要打印专门的日志文件
  • 如非必要,禁止在循环中打印日志
  • Gateway所有接口增加trace注解,记录关键请求参数
  • 日志使用英文清晰描述场景,禁止打印中文
  • 用户关键信息打印时,比如(密码、电话号码)在日志中打印时需要模糊化处理
  • 非关键路径的日志,打印debug级别日志

性能指标

  • 一般情况下,服务接口延时不超过50ms
  • Gateway对外提供接口,延时不能超过200ms

工程依赖

  • 任何业务工程、子工程,不能存在互相依赖;
  • 业务工程之间公用部分,提取工程发布到maven私服;比如搜索各工程间共用dal
  • 所有工程、子工程的POM文件中,禁止出现依赖版本号,统一在yoho-parent中管理
  • 外部依赖的配置(例如外部redis地址、外部restful接口地址)添加到global配置中,自己工程的配置加入auto-conf中。

基础编程

  • 数字和字符串常量,统一定义final变量,命名规则全大写
  • 禁止if、else、try、catch多层嵌套,在核心业务逻辑处理前,优先处理异常逻辑
  • 禁止在Gateway、服务中定义全局变量
  • 如果获取非核心配置、信息失败,采用默认配置;比如,获取vip信息失败,导致无法下单
  • 类、public方法必须注释用途、参数含义、返回值含义,特别是restapi、service所有public必须明确注释
  • 关键业务的每个路径、普通业务的关键路径必须详细注释
  • 每个方法的实际代码不超过30行(排除注释、换行等)

金额计算

  • 如果首先计算商品本身价格,则丢弃精度,比如原价 81.1元,85折后68.935元,则商品价格取68.93元,让利用户
  • 如果首先计算优惠价格,则向上取, 比如原价 81.1元,满减计算时优惠 12.344元,则优惠金额取值为 12.35元,让利用户
  • 每次加减运算使用yoho-core中的YHMath

Git

  • 只能使用 SourceTree 作为客户端工具。 禁止使用任何其他工具。

命名规范

 Controller类是以英文单词组成;由模块名 + Controller构成,例如:UserController.java;
 Controller层方法的命名:同Service层方法的命名(绝大多数情况我们的Controller作为Service的访问跳板)

 Service层接口的命名由I + 模块名 + Service构成,例如:IUserService.java;
 Service层实现的命名由 模块名 + ServiceImpl构 成,例如:UserServiceImpl.java
 Service层方法的命名:以 操作动词 + ValueObject名
     创建前缀:create,比如:createUser(User user);
     修改前缀:update,比如:updateUser(User user);
     删除前缀:delete,比如:deleteUser(User user);
     查询前缀:find,比如:findUserByGroupId(Long groupId);
     统计前缀:stat,比如:statUser();

 Dao层接口的命名由I + 表名 + Dao构成,例如:IUserDao.java;
 Dao层方法的命名:以 操作动词 + ValueObject名
     创建前缀:insert
     修改前缀:update
     查询前缀:select