• Java后端开发规范


    一.命名规范

    1.命名使用英文词组合,严禁使用中文拼音或拼音首字母组合命名(专有名词例外) - OrganizationTreeNode, OrganizationVO ; 不推荐使用PSTree , Tlogs

    2.groupId,package包名前缀统一为: com.wiwj

    3.包名第三位为产品分类名,如com.wiwj.cbs

    4.常量命名全大写,单词间下划线分隔。如: DEFAULT_PAGE_SIZE

    5.类名:首字母大写的UpperCamelCase,如: Organization

    6.方法名、变量名:首字母小写的age,如: orgName

    7.特定标识命名:

    1. 领域模型增加类型后缀标识,如xxVO, yyDAO

    2. 基类/抽象类使用Base/Abstract等前缀标识

      package com.grand.weichat.entity;
      
      public class AbstractButton {
      	private String name;
      
      	public String getName() {
      		return name;
      	}
      
      	public void setName(String name) {
      		this.name = name;
      	}
      
      	public AbstractButton(String name) {
      		super();
      		this.name = name;
      	}
      
      }
      

        

    3. 设计模式类添加Factory,Builder,Proxy等标识

    4. Controller, Service, Mapper统一添加到对应分层目录

    5. 接口实现类添加Impl后缀标识

    6. 枚举类添加Enum后缀标识

    7. CRUD接口采用统一前缀: get, count, create, delete, update, batchCreate

    二、注释规范

    1.Java文件统一添加固定Header,通过IDE统一配置(code templates)

          /**

           * <Description> <br>

           * @author mazhicheng@5i5j.com<br>

           * @version 1.0<br>

           * @date {MONTH}/${DAY} <br>

          */

    2.接口和方法统一添加Java Doc标准注释

        /**

          *缓存key-value并设定过期时间

          * @param key 缓存对象的key

           * @param valueList 缓存对象

          * @return 缓存是否成功

          */

    3.需暂留的弃用类/方法添加 @Deprecated 废弃标记 和 @see 链接指向新接口

        * @see com.wiwj.common.cache.redis.JedisSentinelPoolUtil

        */

        @Deprecated

        public class JedisUtils {…}

    三.异常与日志

    1. 调用外部服务等可能异常的代码块,用 try/catch 代码块捕获并在catch中记录异常跟踪日志及业务逻辑处理

    2. 禁止吞掉异常信息

      2.1 禁止catch里不做任何记录和处理,吞掉异常及其堆栈信息
      2.2 禁止: logger.error(“XXX操作异常”) 或 logger.error(“XXX操作异常”+e) 或 e.printStackTrace()
      2.3 正确: logger.error("XXX操作异常", e)

    3. 对于非预期的条件,尽量增加else记录跟踪日志

    4. 禁止通过System.*.out()打印日志(单元测试例外)

    5. 日志记录logger需使用Slf4J代理声明,禁止绑死具体日志系统的API,避免后期更换日志组件导致代码的大量改动

      5.1 如采用了lombok,可用 @Slf4j 注解替代以下声明。

      private static final Logger log = LoggerFactory.getLogger(OrganizationServiceImpl.class);

    6. 对 trace/debug/info 级别的日志输出,必须使用占位符形式,避免直接String拼接异常信息(即使日志级别不匹配也会执行拼接操作空耗资源)。

        正确写法如:

           log.debug("当前用户id: {} ,操作对象: {}=>{} ", userId, objectType, objectId);

          或条件输出形式如:

            if(log.isDebugEnabled()){

               log.debug("当前用户id: “+id+” ,操作对象: “+ objectType +”=> “+ objectId);

             }

    加上这个logger.isDebugEnabled() 后,如果值为false,if里面的代码就不会执行,就节省了字符串的拼接,少生成几个对象,进而提高效率 ,如果不加,总会先拼接里面的字符串

    四.逻辑代码规范

    1. 废弃的/无用的代码一律直接删除,禁止以注释等方式保留。如需查看历史代码,通过SVN/Git的history找回

        (无用的代码会干扰团队成员的阅读/或被误调,越积越多会导致代码维护成本增高)

    2. 接口类中的方法不需添加 public 修饰符

    3. 需要序列化的Bean类统一实现Serializable接口并用IDE生成serialVersionUID

        public class MyEntity implements Serializable {

           private static final long serialVersionUID = 123456L;

           ...

        }

    4. 常用字符串统一定义在常量类里,如: “utf-8”, “yyyyMMdd”

    5. 避免数字类型比较的坑:

    统一采用equals进行比较其值,不用==进行比较,避免踩坑。

    6. if/else/for/while语句后必须使用大括号,即使只有一行代码。

    (需求总是变化的,一行是暂时的)

    7. 嵌套层次过多的代码块利用反向思维缩减层次

    8. 方法单一职责: 单个方法代码行数控制在100行以内,超长的需要拆分(拆分成多个方法或类)

    9. 避免NPE(NullPointException)的一些建议:

      9.1 equals比较将非空对象前置: 如 "true".equals(request.getParameter("isXx")),即使后者为空也不会导致NPE。
      9.2 数据库字段可空的映射属性使用包装类型定义: 如基本数据类型的int映射到数据库的null值将产生NPE,而用吧包装类型 Integer 则不会。
      9.3 可能为空的变量进行必要判空,并在非预期条件下打印必要的跟踪日志,不但避免NPE,还非常便于跟踪调试。如:
        •     级联调用 obj.getA().getB().getC() 易产生 NPE,先进行判空或使用 JDK8 的 Optional 类包装。

        •     调用Dubbo接口拿到返回值时,进行判空。

        •     封装统一的判空类用于常用类型的判空,代码需要判空时统一调用即可。如 XX.isEmpty(), XX.isNotEmpty()10 遵循:

    10 遵循: Don’t Repeat Yourself,即 DRY 原则。避免进行简单的复制粘贴修改,当出现重复代码时思考是否封装当代码中存在大量重复代码时,一旦代码逻辑变动将很容易导致顾此失彼,产生bug,非常不利于维护。

    11 Bean属性拷贝推荐用Spring BeanCopier或者Mapstruct,避免Apache BeanUtils或调用setter
    12 禁止在循环中执行耗时的操作,如在循环中执行SQL语句/调用外部服务等

        // 错误的示例:

        for(Long id : idList){

          // 循环执行SQL查询或调用外部系统接口,产生性能问题

          Entity entity = xxService.getEntityById(id);

           ...

        }

        // 此案例的更优方案是 通过idList一次性查询获取到Entity集合,然后转换为Map<Id, Entity>供后续获取。

    13 需要多次使用的可复用对象将对象单独定义,禁止多次调用取不同属性。如:

        String name = userService.getUser(id).getName();

        Long deptId = userService.getUser(id).getDepeId();

        替换为:

        User user = userService.getUser(id); String name = user.getName(), ….

    14 可异步执行的耗时操作采用异步处理:使用Spring @Async 或 MQ,或夜间Timer定时
    15 常用数据考虑缓存,存入Redis,设置缓存过期时间
    16 需要保证写一致性的逻辑,在外层方法上添加事务 @Transactional(rollbackFor = Exception.class)

     

  • 相关阅读:
    2019年4月
    20190423
    20190419
    20190418
    20190417
    free命令详解(转载)
    https改造过程中的一个坑
    GitLab 实现代码自动部署(转载自https://segmentfault.com/a/1190000011561808)
    js和php写日历
    shell递归遍历目录的方法
  • 原文地址:https://www.cnblogs.com/KdeS/p/12603606.html
Copyright © 2020-2023  润新知