【强制】POJO类中布尔类型的变量,都不要加is前缀,否则部分框架解析会引起序列化错误
【强制】不允许任何魔法值(即未经预先定义的常量)直接出现在代码中(对for循环中的循环变量(i或j等)的赋值,暂且不认为是魔法值)
【强制】不允许任何魔法值(即未经预先定义的常量)直接出现在代码中(对for循环中的循环变量(i或j等)的赋值,暂且不认为是魔法值)
**【强制】**Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用equals(说明:推荐使用 java.util.Objects#equals(JDK7 引入的工具类))
**【强制】**定义 DO/DTO/VO 等 POJO 类时,不要设定任何属性默认值
**【强制】**使用集合转数组的方法,必须使用集合的toArray(T[] array),传入的是类型完全一样的数组,大小就是 list.size()(说明:使用 toArray 带参方法,入参分配的数组空间不够大时,toArray 方法内部将重新分配内存空间,并返回新数组地址;如果数组元素个数大于实际所需,下标为[ list.size() ] 的数组元素将被置为 null,其它数组元素保持原值,因此最好将方法入参数组大小定义与集合元素个数一致)
正例: List<String> list = new ArrayList<String>(2);
list.add("guan"); list.add("bao");
String[] array = new String[list.size()];
array = list.toArray(array);
使用工具类 Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方 法,它的 add/remove/clear 方法会抛出 UnsupportedOperationException 异常(说明:asList 的返回对象是一个 Arrays 内部类,并没有实现集合的修改方法。Arrays.asList体现的是适配器模式,只是转换接口,后台的数据仍是数组)
String[] str = new String[] { “you”, “wu” }; List list = Arrays.asList(str);
第一种情况:list.add(“yangguanbao”); 运行时异常
第二种情况:str[0] = “gujin”; 那么list.get(0)也会随之修改
**【强制】**不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator方式,如果并发操作,需要对 Iterator 对象加锁
正例:List list = new ArrayList<>(); list.add(“1”);list.add(“2”);
Iterator iterator = list.iterator();
while (iterator.hasNext()) { String item = iterator.next();if (删除元素的条件) { iterator.remove(); } }
反例:for (String item : list) { if (“1”.equals(item)) {list.remove(item);} }
- 【**强制**】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险
说明:Executors 返回的线程池对象的弊端如下:
\1) FixedThreadPool 和 SingleThreadPool:允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM
\2) CachedThreadPool 和 ScheduledThreadPool:允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM
- 在高并发场景中,避免使用”等于”判断作为中断或退出的条件(说明:如果并发控制没有处理好,容易产生等值判断被“击穿”的情况,使用大于或小于的区间 判断条件来代替)
1. 反例:判断剩余奖品数量等于 0 时,终止发放奖品,但因为并发处理错误导致奖品数量瞬间变成了负数,这样的话,活动无法终止
- **【强制】**不要在 finally 块中使用 return(说明:finally 块中的 return 返回后方法结束执行,不会再执行 try 块中的 return 语句)
- **【强制】**类、类属性、类方法的注释必须使用 Javadoc 规范,使用/**内容*/格式,不得使用 // xxx方式(说明:在 IDE 编辑窗口中,Javadoc 方式会提示相关注释,生成 Javadoc 可以正确输出相应注 释;在 IDE 中,工程调用方法时,不进入方法即可悬浮 示方法、参数、返回值的意义, 提高阅读效率)
- **【强制】**所有的类都必须添加创建者和创建日期
- 【推荐】可以使用warn日志级别来记录用户输入参数错误的情况,避免用户投诉时,无所适从。如非必要,请不要在此场景打出 error 级别,避免频繁报警(说明:注意日志输出的级别,error 级别只记录系统逻辑出错、异常或者重要的错误信息)
- 【推荐】尽量用英文来描述日志错误信息,如果日志中的错误信息用英文描述不清楚的话使用 中文 述即可,否则容易产生歧义。
- 禁止事务内有rpc 调用
- 禁止事务传播、嵌套
- insert每次批量插入的行限制在200
```java
@Transactional(rollbackFor = Exception.class)
public void updateOrderCount(Req request) {
xxxMapper.batchUpdateStatus(request);
xxxMapper.batchUpdate(request);
}
【强制】数字运算表达式,因为先进行等式右边的运算,再赋值给等式左边的变量,所以等式两边的类型要一致
double d = 24/7; //结果是3.0
double d = (double)24/7; //结果是正确的3.42857
int与int相乘,哪怕被赋值给long,仍然会溢出。需要强制将乘数的一方转换为long。
long l = Integer.MAX_VALUE * 2; // 结果是溢出的-2
long l = Integer.MAX_VALUE * 2L; //结果是正确的4294967294
随机IO:随机IO是指读写操作时间连续,但访问地址不连续,随机分布在磁盘的地址空间中。
对需求方提出的所有需求,进行详细的分析。这个阶段一般需要和客户反复确认,以保证能充分理解客户需求。最终会形成需求分析文档。
根据需求分析的结果,对整个软件系统进行抽象和设计,如系统框架设计,数据库设计等等。最后会形成架构设计文档。
特别注意:
将架构设计和界面设计的结果转换成计算机能运行的程序代码。
生产者:重复@Retryable发送MQ,同步或异步阻塞拿到结果
消费者:消费逻辑不成功时,通过RECONSUME_LATER再次重试消费MQ,直到设定的最大重试次数时,不管成功与否,MQ的状态都为CONSUME_SUCCESS
禁止return null,使用 Optional
接口必须抛出 TException
MTthrift注解方式声明rpc接口时,TException必须要声明(否则调用方会看到UndeclaredThrowableException,而隐藏了真实的异常信息)。TException代表的是网络异常、服务注册异常等非业务异常;不可以在业务异常的情况下抛出TException。调用方应该对TException类异常做单独处理:譬如重试机制;譬如异常信息的独立封装。
接口不对外显示抛出业务异常
thrift接口定义不对外显示抛出Exception,业务层可以抛出BizXXXException,但异常必须有service层统一处理,不对外抛出,而是将异常转成对应的errorCode返回。
1、方向、rd、详细设计、技术方案预计完成时间、是否完成评审、备注
2、技术方案评审todo项
1、方向、rd(前后端)、研发排期(含PD)、联调时间、QA测试时间
2、是否提测完成
是否有变更需要周知数据组
降级、灰度
方向、rd、灰度方案(有的方向不需要)、灰度顺序、回滚方案、备注
方向、rd、上线checklist、上线时间、是否完成上线、备注(服务1依赖服务2先上线等)
项目名称、项目负责人(产品主R、技术主R)、项目背景、项目收益、计划上线时间、灰度节奏(灰度方案)
风险类别(业务风险-不可用、稳定性风险)、风险内容、风险评估人员、风险预案措施
审批人(灰度放量等)