「这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战」。
前言
好的开发习惯能帮助我们在日常开发工作中达到事半功倍的效果,增强代码的可读性、健壮性,减少代码漏洞,因此我们应当不懈的追求代码精进,培养好的开发习惯。
代码规范
- 写完代码,自测一下
- 方法入参尽量都校验
- 对于复杂的代码逻辑,添加清楚的注释
- 使用完IO资源流,需要关闭
- 代码采取措施避免运行时错误(如数组边界溢出,被零除等)
- 尽量不在循环里远程调用、或者数据库操作,优先考虑批量进行
- 获取对象的属性,先判断对象是否为空
- Set集合或者Map集合中的key为自定义对象时,要重写该对象的equals和hashCode方法
避免使用双括号new Person{{setName("xxx")}}的方式实例化对象,该写法虽然简洁但会生成匿名内部类,容易造成内存泄漏- 不要在条件判断中写复杂的表达式
- 条件判断使用卫语句,增强代码可读性和健壮性
- 使用equals()方法时,常量(有确定值)放前面
- spring官方推荐使用
构造器注入 - 尽量不在循环中使用try-catch,应把其放在最外层
- 常量声明为static final,并以大写命名
- 不要创建一些不使用的对象,不要导入一些不使用的类
- 不要对超出范围的基本数据类型做向下强制转型
代码优化
- 尽量指定类、方法、变量的final修饰符
- 尽量重用对象
- 尽可能使用局部变量
- 尽量减少对变量的重复计算
- 尽量采用懒加载的策略
- 如果能预估到数组、集合的内容长度,应在创建时指定长度
- 复制大量数据时,使用System.arraycopy()
- 乘法和除法使用移位操作
- 数组优先于列表
- 尽量在合适的场合使用单例
- 尽量避免使用静态变量
- 尽量避免使用反射
- 尽量使用
池化技术(数据库连接池、线程池) - 使用带缓冲的输入输出流进行IO操作
- public方法不要有太多的形参
- 使用最有效率的方式去遍历Map(推荐使用entrySet()遍历)
接口规约
- 接口需要考虑幂等性
- 接口入参需要做校验,推荐使用@valid或者@validated校验框架
- 接口出参不允许为枚举值或任何包含枚举值的pojo对象
- 修改老接口的时候,考虑接口的兼容性
- 调用第三方接口,需要考虑异常处理,安全性,超时重试这几个点
并发编程
- 多线程情况下,考虑线性安全问题
- 写完代码,脑洞一下多线程执行会怎样,注意并发一致性问题
- 多线程异步优先考虑恰当的线程池,而不是new thread,同时考虑线程池是否隔离
- 使用
ThreadPoolExecutor构造器创建线程池,避免使用Executors的 静态方法创建线程池 - 使用synchronized时尽量同步代码块
- 使用锁时尽量缩小锁定范围
缓存(redis)
- 使用缓存的时候,考虑缓存跟DB的一致性
- 考虑缓存穿透、缓存雪崩、缓存击穿、缓存热点问题
- 避免使用redis事务功能
- 禁止线上使用
keys、flushall、flushdb等,通过redis的rename机制禁掉命令,或者使用scan的方式渐进式处理 - 使用批量操作的命令提升效率
- 拒绝big key(拆分key,使用合适的数据类型)
- 控制key的生命周期(分散设置过期时间)
- key名设计要有可读性、可管理性、简洁性,不要包含特殊字符
- 设置合适的内存淘汰策略
数据库
- 手动写完代码业务的SQL,先拿去数据库跑一下,同时也explain看下执行计划
- 数据库主从延迟问题考虑(必要时强制读主库)
- 避免在循环内做数据库的操作