当前位置:   article > 正文

统一JAVA软件开发规范

java软件开发规范

目录

 前言

1:基本规范

1.1:命名规范

1.2:修饰符规范

1.3 :强制约定

1.4:异常处理 

1.5:不允许任何未经预先定义的常量值直接出现在代码中

1.6:对Long或者long赋值时,数值后必须加大写字母L

1.7:在 if/else/for/while/do 语句中必须使用大括号,即使只有一行代 码。禁止采用单行编码方式。

1.8:单行字符数限制不超过 120 个,超出需要换行,换行时遵循如下原则

1.9:使用equals对比数值时,应将数值放在equals前面,避免潜在的空指针异常

2.0:获取当前毫秒数应使用统一范式代码

2.1创建集合时,必须指定泛型

2.2禁止在foreach 循环里进行集合元素的 remove/add 操作

 2:并发处理

2.1禁止在代码里自行创建线程进行异步操作,应使用线程池

2.2SimpleDateFormat使用,锁的使用

3:事务处理

4:接口规范

5:代码分层

6: 日志处理 

7:数据库规范

7.1:建表规范

7.2:索引规范

7.3:SQL规范

8:版本规范

9: 代码性能 

9.1 代码性能

 9.2:可读性


 前言

  1. ● 本规范基于jdk1.8进行编制,文档内出现的某些类可能在低版本jdk不存在
  2. ● 数据库规范基于MYSQL数据库,ORACLE数据库

1:基本规范

1.1:命名规范

  1. ● 类名必须使用驼峰式风格,首字母大写,但以下情形例外:DO / BO / DTO / VO / AO / PO / UID等
  2. ○ 正例:MarcoPolo / UserDO / XmlService / TcpUdpDeal / serialVersionUID
  3. ○ 反例:macroPolo / UserDo / XMLService / TCPUDPDeal / TAPromotion
  4. ● 方法名、参数名、成员变量、局部变量强制统一使用驼峰式风格进行命名,首字母小写
  5. ○ 正例:localValue / getHttpMessage() / inputUserId
  6. ○ 反例:LocalValue / GetHttpMessage() / InputUserId
  7. ● 常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长
  8. ○ 正例:MAX_STOCK_COUNT
  9. ○ 反例:MAXCOUNT
  10. ● 代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式
  11. ○ 正例:alibaba / taobao / youku / hangzhou 等国际通用的名称,可视同英文
  12. ○ 反例:DaZhePromotion [打折] / getPingfenByName() [评分] / int 某变量 = 3
  13. ● POJO类中布尔类型的属性禁止加 is 前缀,否则部分框架解析会引起序列化错误
  14. ○ 正例:deleted
  15. ○ 反例:isDeleted
  16. ● 包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。
  17. 包名统一使用单数形式,但是类名如果有复数含义,类名可以使用复数形式
  18. ○ 正例:com.petrochina.ai.util
  19. ○ 反例:com.PetroChina.ai.util
  20. ● 杜绝完全不规范的缩写,避免望文不知义
  21. ○ 反例:AbstractClass“缩写”命名成 AbsClass;condition“缩写”命名成 condi,
  22. 此类随 意缩写严重降低了代码的可阅读性
  23. ● 接口名不要加Interface后缀,接口的实现类统一加Impl后缀
  24. ○ 正例:CacheService CacheServiceImpl
  25. ○ 反例:CacheServiceInterface CacheService

1.2:修饰符规范

  1. ● 接口中的方法不要加任何修饰符号
  2. ○ 正例:void commit();
  3. ○ 反例:public void commit();
  4. ● 枚举类需带上 Enum 后缀,枚举成员名称需要全大写,单词间用下划线隔开
  5. ○ 正例:枚举名字为ProcessStatusEnum的成员名称:SUCCESS / UNKNOWN_REASON
  6. ● 方法命名规则:
  7. ○ Service/DAO层方法命名规则
  8. ■ 获取单个对象的方法用get做前缀
  9. ■ 获取多个对象的方法用list做前缀,复数形式结尾如:listObjects
  10. ■ 获取统计值的方法用count做前缀
  11. ■ 插入的方法用save/insert做前缀
  12. ■ 删除的方法用remove/delete做前缀
  13. ■ 修改的方法用update做前缀
  14. ● 领域模型命名规则:
  15. ○ 数据库实体类:xxxPO,类中的属性和数据库字段严格一一映射
  16. ○ 数据对象: xxxDO, 类中的属性可以和数据库字段一一映射,可以是PO的子集
  17. ○ 数据传输对象:xxxDTO,包括controller层返回给前端的对象,和外部系统交互的对象
  18. ○ 业务对象:xxxBO,该对象可包含多个PO或DO,作为业务层返回结果给controller使用

1.3 :强制约定

  1. ● IDE的标黄警告必须全部处理,禁止提交包含警告提示的代码
  2. ● 提交代码时必须进行代码格式化,非格式化的代码不允许提交
  3. ● 禁止在业务类中定义和使用内部类
  4. ● 禁止将所有的业务都写在一个类里,一个类应处理单一业务
  5. ● 禁止使用过时的类或方法
  6. ● 所有的覆写方法,必须加@Override 注解
  7. ● 禁止类中import无用的包,IDEA可以通过勾选Optimize imports on the fly选项自动剔除无用的包
  8. ● 禁止在 POJO 类中,同时存在对应属性 xxx 的 isXxx()和 getXxx()方法
  9. ● 重载方法必须按照顺序放在一起,同理,如果存在多个构造方法也遵从此规则
  10. ● 不用的代码块及时删除,禁止注释多行代码,如果某些代码今后可能会重新启用,
  11. 应采用版本管理,例如在类名或者方法名后加版本号;而事实上大多数开发场景,
  12. 注释掉的代码95%的情况下不会重新启用,所以应及时删除,避免代码过于臃肿且可读性差。
  13. ● 单行注释使用//,注释的双斜线与注释内容之间有且仅有一个空格;多行注释使用/* */
  14. ● 关于 hashCode 和 equals 的处理,遵循如下规则
  15. ○ 只要重写equals,就必须重写hashCode
  16. ○ 向set集合中放业务对象时,必须重写该对象的equals和hashCode方法
  17. ○ 同理,如果map的key是业务对象,也必须重写该对象的equals和hashCode方法
  18. ● 单个方法的总行数不得超过80行,如果代码过长可以利用IDE的方法提取快捷键
  19. ○ IDEA: Ctrl+Alt+M
  20. ○ Eclipse: Alt+Shift+M
  21. ● 当拼接的字符串数目超过5个时,禁止使用+进行拼接,应使用Stringbuilder,
  22. 如果需要保证线程安全,则需使用Stringbuffer
  23. ● 使用try..catch时,在catch块里捕获的异常要么进行业务处理,要么利用日志框架进行log记录,
  24. 要么向上抛出由调用方处理,禁止吞掉异常,什么都不做。
  25. ○ 反例:try {...} catch (Exception e) { System.out.println("xxxx");}

1.4:异常处理 

  1. ● 禁止在finally 块中使用 returnfinally 块中的 return 返回后方法结束执行,不会再执行 try 块中的 return 语句
  2. ● 如果使用到资源对象或者流对象,必须在finally块中对其进行关闭
  3. ● 关于基本数据类型与包装数据类型的使用标准如下
  4. ○ 所有的POJO类属性使用包装数据类型
  5. ○ RPC方法的返回值和参数使用包装数据类型
  6. ○ 所有的局部变量使用基本数据类型
  7. ○ 正例:
  8. public class BusinessBO {
  9. // 禁止使用boolean定义 private Integer count; // 禁止使用int定义
  10. private Boolean deleted;
  11. }

 1.5:不允许任何未经预先定义的常量值直接出现在代码中

  1. ○ 正例:
  2. private static final String KEY_PREFIX = "petro_cnpc#id_";
  3. ...String key = KEY_PREFIX + tradeId;
  4. cache.put(key, value);
  5. ○ 反例:
  6. String key = "petro_cnpc#id_" + tradeId;cache.put(key, value);

 1.6:对Long或者long赋值时,数值后必须加大写字母L

  1. ○ 正例:
  2. long count = 2L;
  3. ○ 反例:
  4. long count = 2;long number = 2l; // 如果是小写l,很容易和数字1混淆

 1.7:在 if/else/for/while/do 语句中必须使用大括号,即使只有一行代             码。禁止采用单行编码方式。

  1. ○ 正例:
  2. if (condition) { statements;}
  3. ○ 反例:
  4. if (condition) statements;if (condition) statements;

 1.8:单行字符数限制不超过 120 个,超出需要换行,换行时遵循如下原则

  1. ○ 运算符与下文一起换行
  2. ○ 方法调用的点符号与下文一起换行
  3. ○ 方法调用中的多个参数需要换行时,在逗号后进行
  4. ○ 在括号前不要换行
  5. ○ 正例:
  6. StringBuffer sb = new StringBuffer();
  7. sb.append("zi").append("xin")
  8. .append("huang") .append("huang")
  9. .append("huang");

1.9:使用equals对比数值时,应将数值放在equals前面,避免潜在的空指针异常

  1. ○ 正例:
  2. "test".equals(object);Objects.equals("test",object); // 建议使用jdk1.7引入的Objects工具类
  3. ○ 反例:
  4. object.equals("test");

 2.0:获取当前毫秒数应使用统一范式代码

  1. ○ 正例:
  2. long now = System.currentTimeMillis();
  3. ○ 反例:
  4. long now = new Date().getTime();

 2.1创建集合时,必须指定泛型

  1. ○ 正例:
  2. List<String> list = new ArrayList<>();
  3. ○ 反例:
  4. List list = new ArrayList();

2.2禁止在foreach 循环里进行集合元素的 remove/add 操作

  1. ○ 正例:
  2. List<String> list = new ArrayList<>();
  3. list.add("1");
  4. list.add("2");
  5. Iterator<String> iterator = list.iterator();
  6. while (iterator.hasNext()) {
  7. String item = iterator.next();
  8. if (删除元素的条件) {
  9. iterator.remove();
  10. }
  11. }
  12. ○ 反例:
  13. for (String item : list) {
  14. if ("1".equals(item)) {
  15. list.remove(item);
  16. }
  17. }

2:并发处理

2.1禁止在代码里自行创建线程进行异步操作,应使用线程池

  1. ● 禁止使用Executors创建线程池,而是通过 ThreadPoolExecutor 的方式
  2. ○ Executors创建的线程池是无界任务队列,在高并发下有耗尽系统资源的风险
  3. ○ 一个正确创建线程池的案例:
  4. // 这里创建了一个核心线程数是10,最大线程数是20,任务等待队列100的线程池
  5. // 线程池内的线程应有自己的命名,在这里是mine-threadPool-xxx
  6. // 如果任务队列超负载,则抛出异常,由任务调用方进行补偿处理
  7. // ThreadPoolExecutor的其余构造方法请见源码
  8. ThreadPoolExecutor threadPoolExecutor =
  9. new ThreadPoolExecutor(10, 20, 30,TimeUnit.SECONDS,
  10. new ArrayBlockingQueue<>(100), r -> { Thread t = new Thread(r);
  11. t.setName("mine-threadPool-" + t.getId()); return t; },
  12. (r, e) -> { throw new RejectedExecutionException(); });

2.2SimpleDateFormat使用,锁的使用

  1. ● SimpleDateFormat线程不安全,禁止在单例对象(spring的bean默认都是单例的)的属性中定义SimpleDateFormat,或者将SimpleDateFormat定义成static属性。
  2. ○ 可以在方法体内部去定义,但是这样会频繁创建对象导致性能下降
  3. ○ 最理想的方案是使用ThreadLocal
  4. ○ jdk8可以用DateTimeFormatter替代SimpleDateFormat
  5. ● 高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁。
  6. ○ 使用synchronized时尤其需要注意锁住的资源到底是什么
  7. synchronized用在实例方法上,锁住的是对象,不建议这样加锁
  8. synchronized用在静态方法上,锁住的是类,不建议这样加锁
  9. ○ 尽量使用Lock锁, 避免使用synchronized
  10. ■ 尽管synchronized在jdk1.6之后经过优化已经基本不存在性能问题,但是如果阻塞时间过久,synchronized仍然会升级成重量级锁,极大影响系统性能
  11. synchronized在代码层面对锁的控制不够灵活
  12. ■ Lock锁使用标准范式:
  13. // 范式一:使用lock()阻塞获取资源
  14. Lock lock = new ReentrantLock();lock.lock(); try{ ...} finally{ lock.unlock();}
  15. // 范式二:使用tryLock()阻塞式获取资源,但是增加最大等待时间,推荐
  16. Lock lock = new ReentrantLock();if (lock.tryLock(long timeout, TimeUnit unit)) { try{ ... } finally{ lock.unlock(); }}
  17. // 范式三:使用tryLock()非阻塞式获取资源,获取不到则走else逻辑
  18. Lock lock = new ReentrantLock();if (lock.tryLock()) { try{ ... } finally{ lock.unlock(); }} else { ...}
  19. ● 业务预估如果每次访问冲突概率小于 20%,应使用乐观锁,否则使用悲观锁。乐观锁的重试次数不得小于 3 次。典型的乐观锁是数据库的version字段版本控制以及Lock锁的tryLock方法
  20. ● 使用ThreadLocal时,线程执行完逻辑之后,必须执行ThreadLocal.remove()方法,否则会造成内存泄漏
  21. ● 使用CompletableFuture提交异步任务时,必须指定线程池,禁止用默认的线程池,使用get方法获取异步任务的执行结果时必须指定最大等待时间,禁止一直阻塞等待
  22. ● 对容器有同步要求时,禁止使用HashTable和Vector,应使用JUC包下的ConcurrentHashMap和ConcurrentLinkedDeque等高并发容器替代

3:事务处理

  1. ● 禁止将一大长串业务代码包装成事务,应仅包含可回滚的代码
  2. ○ 事务方法内部应只包含数据库的INSERT,UPDATE, DELETE操作,相关逻辑校验和查询应放在事务外部
  3. ● 能不使用分布式事务就不使用分布式事务,分布式服务之间的一致性可利用补偿机制实现
  4. ● 禁止在类上直接标注@Transactional,需要针对每一个方法作精准区分
  5. ● 在事务方法内使用try..catch需谨慎,如需使用,需要显式抛出异常并指定rollbackFor,
  6. 避免事务失效导致无法回滚
  7. ● 禁止使用this.xxx()方式调用事务方法,事务方法必须存在于事务层中,
  8. 由上层业务进行调用。this.xxx()形式调用会使事务失效

4:接口规范

  1. ● 所有提供给前端的http接口应使用restful风格并遵循restful架构规范
  2. ● HTTP请求类型应按照以下四类作为区分:
  3. ○ GET 获取资源
  4. ○ POST 新建资源
  5. ○ PUT 更新资源
  6. ○ DELETE 删除资源
  7. ○ 如某些前端框架不支持发送PUT和DELETE请求,
  8. 则需严格区分GET和POST,避免所有请求都用POST
  9. ● 接口名称不允许出现动词,应使用资源名词的单数或者复数形式,如:
  10. ○ 获取商品详情:GET /product/{id}
  11. ○ 获取商品列表: GET /products
  12. ○ 添加商品: POST /product
  13. ○ 修改商品:PUT /product/{id}
  14. ○ 删除商品:DELETE /product/{id}
  15. ● 接口返回必须指定http状态码:
  16. ○ 200 :业务处理成功
  17. ○ 500 : 服务端业务异常或运行时异常
  18. ○ 404 : 资源不存在
  19. ○ 403 :没有权限访问资源
  20. ○ 503 :服务不可用,可能发生在系统限流或熔断时

 5:代码分层

  1. ● 代码工程应至少具有以下四层结构:
  2. ○ DAO层:数据访问层,负责和数据库的交互
  3. ○ Service层:数据服务层,该层处理事务回滚以及封装外部接口调用等。
  4. ○ Manager层:业务服务层,该层执行具体业务逻辑
  5. ○ Web层:该层负责处理前端数据交互,负责参数校验
  6. ■ web层可抽离出controller层和api层
  7. ■ controller层负责和前端交互,api层负责为外部系统提供接口
  8. ● 各层的业务类必须加层名后缀,如: xxxService,xxxDAO,xxxController,
  9. 禁止不加后缀单独命名
  10. ● DAO层和Service层的方法禁止返回map,需要把map封装成PO或者DO对象

6: 日志处理 

  1. ● 代码里绝对禁止使用System.out.print记录日志,必须使用日志框架。
  2. ● 应用中不可直接使用日志系统(Log4j、Logback)中的 API,
  3. 而应依赖使用日志框架SLF4J 中的 API,使用门面模式的日志框架,
  4. 有利于维护和各个类的日志处理方式统一
  5. ○ 方式一:类上加@Slf4j注解
  6. ○ 方式二:
  7. import org.slf4j.Logger;import org.slf4j.LoggerFactory;private static final Logger logger
  8. = LoggerFactory.getLogger(Abc.class);
  1. ● 生产环境日志文件至少保存 15 天,需根据日志级别对日志文件进行区分记录:
  2. ○ info级别: 记录业务日志,包括业务异常也用info记录
  3. ○ warn级别:记录可能导致系统运行异常的各种警告信息
  4. ○ error级别:记录系统错误日志,包括各种运行时异常堆栈以及影响系统正常运行的错误信息
  5. ● 日志文件命名方式:appName_logType_logName.log
  6. ○ appName: 应用名称
  7. ○ logType:日志类型,如 stats/monitor/access 等
  8. ○ logName:日志描述
  9. ● 对 trace/debug/info 级别的日志输出,禁止采用字符串拼接方式输出日志。
  10. ○ 正例:
  11. logger.info("Processing trade with id: {} and symbol : {} ", id, symbol);
  12. ○ 反例:
  13. logger.info("Processing trade with id: " + id + " and symbol: " + symbol);
  1. ● 异常日志必须记录异常堆栈信息
  2. ○ 正例:
  3. logger.error(e.getMessage(), e);logger.error("system error", e);
  4. ○ 反例:
  5. logger.error("system error");logger.error(e.getMessage());
  1. ● 生产环境禁止输出debug日志,有选择地输出info日志,
  2. 禁止在info日志中随意打印各种无关信息,如果需要debug信息,则可以这么写:
  3. if (logger.isDebugEnabled()) {
  4. logger.debug("Processing trade with id:{}",id);
  5. }

7:数据库规范

7.1:建表规范

  1. ● 所有表必须具备3个字段: id, created_time, modified_time
  2. ○ id: 主键,bigint unsigned 类型,不得随意更改名称,
  3. 采用自增序列,禁止采用uuid作为主键
  4. ○ created_time: 记录创建时间,datetime类型
  5. ○ modified_time:记录修改时间,datetime类型
  6. ● 表名、字段名必须使用小写字母或数字,但是禁止以数字开头。单词之间用下划线分隔
  7. ○ 正例: petro_admin,rdc_config
  8. ○ 反例: PetroAdmin,rdcConfig
  9. ● 表达是与否概念的字段,必须使用 is_xxx 的方式命名,数据类型是 unsigned tinyint
  10. ○ 说明:任何字段如果为非负数,必须是 unsigned
  11. ○ 正例:表达逻辑删除的字段名 is_deleted,1 表示删除,0 表示未删除
  12. ● 小数类型为 decimal,禁止使用 floatdouble
  13. ○ floatdouble 在存储的时候,存在精度损失的问题,
  14. 很可能在值的比较时,得到不 正确的结果
  15. ● 如果存储的字符串长度几乎相等,使用 char 定长字符串类型
  16. ● varchar类型长度不要超过 5000,如果存储长度大于此值,定义字段类型为 text,
  17. 独立出来一张表,用主键来对应,避免影响其它字段索引效率。
  18. ● 禁止使用外键,表之间的关联关系采用代码进行维护
  19. ● 时间类型应使用datetime类型,禁止使用varchar

7.2:索引规范

  1. ● 频繁被查询的且区分度较高的字段应该建立索引;
  2. 多表join的关联字段应该建立索引; 排序字段应该建立索引
  3. ● 索引命名规则:
  4. ○ 主键索引: id
  5. ○ 唯一索引:uk_字段名
  6. ○ 普通索引:idx_字段名
  7. ○ 联合索引: idx_字段名1_字段名2
  8. ● 业务上具有唯一特性的字段组合,需要建立唯一索引,大幅增加查询速度
  9. ● 禁止在区分度低的字段上建立索引,如性别,类型,是否删除等
  10. ● 建立联合索引时,区分度高的字段处于左侧
  11. ● 每张表的索引数量不得超过6

 7.3:SQL规范

  1. ● 禁止使SELECT * 查询,只查询需要的字段
  2. ● 代码里所有的sql关键字必须全大写,如 SELECT,FROM,COUNT
  3. ● 统计记录数使用COUNT(*),不要使用 COUNT(列名)或 COUNT(常量)来替代 COUNT(*)
  4. ● SQL语句写好后,需要查询执行计划,如果查询计划显示该条SQL需要执行全表扫描,则不合格,可以通过加索
  5. 引或者优化SQL来解决
  6. ○ 很多全表扫描是由于SQL不规范导致的索引失效进而引起全表扫描
  7. ○ 典型的造成索引失效的案例就是在索引字段上使用函数,以及 like '%%'
  8. ● 禁止使用where进行多表关联查询,应当使用join
  9. ○ join关联的字段需要建立索引
  10. ○ 禁止超过3个表进行关联查询
  11. ● 操作生产环境数据库时,每条查询语句必须加上LIMIT 指定查询出的最大行数,一般不超过20

8:版本规范

  1. ● 每个代码工程应该至少具有以下分支:
  2. ○ master分支: 生产环境分支
  3. ○ hotfix分支: 生产环境的热修复分支,用于修复验证生产环境的bug
  4. ○ develop分支:开发分支,开发人员提交代码的主分支
  5. ○ test分支:测试分支,测试人员用于测试的分支
  6. ● 开发人员禁止直接向develop分支提交代码,应根据需求或者人员作为区分,从develop分支拉取子分支进行开
  7. 发,开发完成的代码完成自测后,提交合并请求,由相关代码审核人员审核通过之后,才能进入develop分支,
  8. 各开发人员每天应至少从develop分支合并一次代码到自己开发所在的子分支,以便及时处理潜在的代码冲突
  9. ● 代码版本命名规范:
  10. ○ 遵循:【v + 主版本号.子版本号.修订版本号.日期_版本阶段 】命名规则
  11. ○ 新建立的工程版本号应从1.0.0开始
  12. ○ 日期和版本阶段非必填,以下几个版本名称都是符合要求的
  13. v1.0.2v1.0.2.20220501v1.0.2.20220501_RELEASEv1.0.2_RELEASEv1.0.2_BETA
  14. ● 每次在生产环境发布master分支之前,必须对master分支的代码打tag,tag命名规范:
  15. 【v + 主版本号.子版本号.修订版本号】

9: 代码性能 

9.1 代码性能

  1. ● 选择合理的集合遍历方式,特别是集合数据比较大时
  2. ○ 使用entrySet遍历Map类集合KV,而不是keySet方式进行遍历
  3. ○ 使用iterator遍历LinkedList,使用for遍历ArrayList
  4. ● 初始化ArraryList和HashMap时,如果能预估集合的元素数量,那么最好指定元素数量,因为ArraryList和
  5. HashMap每次动态扩容时都是比较耗费性能的
  6. // 这个例子演示初始化一个元素容量为50的
  7. listList<String> list = new ArrayList<>(50);
  8. // 这个例子演示初始化一个元素容量为50的map
  9. // map扩容因子默认0.75,故初始容量需要大于
  10. 50/0.75 = 66.6666Map<String,Object> map = new HashMap<>(67);
  1. ● 使用parallelStream替代Stream
  2. ○ 多核cpu服务器下parallelStream并行流比Stream串行流性能提升较大
  3. ● 在for循环里对数据库的进行操作需要极其慎重,这种操作有时候完全可以通过优化sql的方式避免
  4. ● 合理使用线程池,线程池的线程数量并不是越多越好,过多的线程数量会造成cpu上下文切换的开销过大,
  5. 一般线程池的最大线程数设置为cpu核心数的2-3倍即可
  6. ● 应用池化技术,如数据库连接池,Http连接池,但是连接池使用应遵循以下规范:
  7. ○ 从连接池中获取连接必须指定超时时间,不可永久等待
  8. ○ 连接池中的连接使用完毕之后必须及时放回池中,有些池化框架需要手写代码归还连接
  9. ○ 连接池的连接数量不可随意指定,应从硬件方面和性能测试结果方向综合考量
  10. ● 所有对资源的访问,应设置最大等待时间,如http访问,数据库访问,锁竞争,
  11. 避免资源一直获取不到导致线程持久阻塞
  12. ● 利用spring的@bean单例创建方式去管理代码里需要复用的自定义对象,避免重复new创建增加开销

 9.2:可读性

  1. ● 重复的代码需要抽离出公用方法,避免采用复制粘贴的方式;
  2. 一般代码行数超过10行并且重复引用次数大于2次就需要做方法抽离
  3. ● 每一个类开头上都应有注释,标注该类的作用,每一个public方法上也应该有注释,
  4. 标明该方法的入参和出参含义以及方法
  5. ● Optional的频繁使用会降低代码的可读性,尽管代码写起来很优雅,在一般情况下,
  6. 可以用if的形式替代Optional,让代码易于维护
  7. ● if..else控制语句不要超过3层嵌套,会大大增加代码阅读的复杂度,可以通过如下方式进行优化:
  8.  if (...) { return;}
  1. ● 方法内部对于一个完整的业务流程,应增加详尽的注释并标明步骤编号,
  2. 每一步骤业务代码写完之后,另起一行,如:
  3. // 1. xxxxx....// 1.1 xxxserviceA();// 2. xxxserviceB();
  4. ● 使用map和枚举类替换冗长的if语句判断,如以下代码会使得代码极度臃肿:
  5. if (type == 1) {
  6. return "A";
  7. } else if (type == 2) {
  8. return "B";
  9. } else if (type == 3)
  10. { return "C";
  11. } .......
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/785265
推荐阅读
相关标签
  

闽ICP备14008679号