当我们在写代码的时候,我们在写什么
这个世界上最远的距离,不是从马里亚纳海沟到珠穆朗玛峰,而是知道和做到之间。——罗翔
代码
if的写法
提前判断,提前退出
- 减少缩进,清晰代码
if条件是boolean或者无状态的判断表达式
- 尽量不在条件表达式内做状态变更
for的写法
与forEach和stream的区别
- forEach属于函数式,没有for直观,如果函数体内需修改共享变量也比较麻烦
- stream主要用于filter和map转换
与while的区别
- for用于已知范围的循环,while用于未知范围(比如,不知道具体的循环次数,不确定循环的始终)的循环
try的写法
为什么使用try
- 简化代码,不需要类似go的ok状态判断,保证代码主流程的清晰
- 统一处理,根据不同的异常类型进行处理
使用catch和throw的原则
- 当你知道如何处理异常时,使用catch,否则throw
- 只处理自己可以处理的异常
- catch块最好有log
函数的写法
入参尽可能的简单,且使用通用类型
- 新写一个函数,如果传一个现有自定义对象,但仅用到其中两三个字段,看似方便,但将极大增加系统的耦合,更不用拿日后的扩展当幌子
- 使用通用类型的好处就是使方法更加通用、简单
- 通用类型包括:JDK自带的class、系统框架的class(Spring等)、业务框架的class(公司、部门级框架)
不要在函数内暗置补偿逻辑
不要处理我们无法处理的异常,参考try的写法
- 入参异常时,如果不知道如何处理,或处理方式可能会引起使用者歧义时,直接异常
- 类似除法的除数传了0,我们完全不知道怎么处理,直接抛出异常
外部依赖
数据库操作
避免每次更新所有字段
不要跨方法传递和更新实体
比如在外层方法取出实体,在调用另一个方法内部去更新实体
- 一个方法最好是一个完整的事务,方法的嵌套也是事务的嵌套
事务与分布式锁
当使用分布式锁时,只有在获取到分布式锁后,再开启事务
- 事务的时间尽可能的短
- 必要的计算尽可能放在事务开始之前
具体步骤为:
- 先拿到分布式锁,锁内再次校验状态(二次判断,或通过db update where判断)
- 数据处理
- 开启事务,执行更新,提交事务,判断是否更新成功
代码命名
不建议抽象类用Abstract开头命名
added at 2024-07-04
同理,也不建议接口(interface)使用I开头
考虑以下几点:
- 大部分情况下,我们不应该关心一个类是抽象还是接口还是具体的类
- 更应该使用接口,而不是抽象类
- 抽象类虽然是抽象的,但实际上包含部分实现