单一职责原则.
这是经常被违背的原则。一个类只能干一个事情, 一个方法最好也只干一件事情。 比较常见的违背是处理促销的时候,同时处理验券逻辑。
行为是否统一
比如缓存是否统一,错误处理是否统一, 日志打印是否统一, 方法实现是否统一等等。
同一逻辑/同一行为 有没有走同一出口【同样的service或者method】?低质量程序的另一个特征是,同一行为/同一逻辑,因为出现在不同的地方或者被不同的方式触发,没有走同一出口【同样的service或者method】或者各处有一份copy的实现, 导致非常难以维护。
代码污染
使用魔数,常量,例如直接比对数字。编写不容易阅读的代码,应用了很多复杂的设计。
重复代码
主要看有没有把公用组件,可复用的代码,函数抽取出来。
开放关闭原则
就是好不好扩展。 对扩展开放, 对修改封闭.(做好接口设计会很好解决这些问题)。
面向接口编程 和 不是 面向实现编程
主要就是看有没有进行合适的抽象, 把一些行为抽象为接口。
健壮性
对异常情况,边界条件【例如金额负数会怎样?】 有没有考虑完整,逻辑是否健壮?有没有潜在的bug?
有没有内存泄漏?有没有循环依赖?
有没有考虑线程安全性, 数据访问的一致性
错误处理
有没有很好的Error Handling?比如Price接口出错。
有没有增加必要的监控,及时报警。
改动是不是对代码的提升
新的改动是打补丁,让代码质量继续恶化,还是对代码质量做了修复?
效率/性能
两层循环,数据请求量的限制,较大数据等耗时操作是否处理得当。
关键算法的时间复杂度多少?有没有可能有潜在的性能瓶颈。
复杂需求,是否有必要的设计, 可预见的效率问题, 开发模式一致性的问题 应该尽早在Design Review阶段解决。如果Design阶段没有解决,那至少在Code Review阶段也要把它找出来。
大批量的数据处理尽量不用limit start, size的查询方式,可通过主键或其他索引字段逐步缩小范围,然后通过limit size方式查询。
sql是否写的合理,是否走索引,是否子查询,表的数据量大不大,qps预计多大,查询耗时多少,看扫描行数是否过大,是否用了函数,执行频率是否很高,是否事务竞争频率很频繁,这也是个技术优化,explain有时候不靠谱,要实际测试一下是否真的快,是否要强制加索引,索引的字段不同值多不多,优先选择不同值多的字段做索引
配置、基础数据一般走缓存处理,对于用户相关的数据要权衡变更和读取的频率,考虑是否要加缓存操作
可读性
衡量可读性的可以有很好实践的标准,就是Reviewer能否非常容易的理解这个代码。 如果不是,那意味着代码的可读性要进行改进。
命名对可读性非常重要,我倾向于函数名/方法名长一点都没关系,必须是能自我阐述的。
英语用词尽量准确一点(哪怕有时候需要借助Google Translate,是值得的)
函数长度/类长度
函数太长的不好阅读。 类太长了,比如超过了1000行【建议类控制在50-70行】,那你要看一下是否违反的“单一职责” 原则。
恰到好处的注释。
常见代码开发规范
- 缓存的key只能新增,不可以修改,如果要修改,要考虑兼容性问题风险是否过高,直接用新的会不会风险更低
- 缓存的value不可随意做改变,例如改变缓存类变量类型,修改变量名称,移动类路径等,如果修改,需考虑上线前后兼容性问题
- 非代码异常,不要写error日志,业务异常,如非必要,写warn就可以了
- 涉及到异步,线程池的,检查是否定义了固定线程池和固定的队列处理任务,不要用无限队列和无限创建线程,常见于一些批处理操作
- 配置类的东西【特别是全局性的】,尽量不要改,改之前一定要跟leader确认并通知所有人,并且自己要跑完单元测试或者测试用例
- 事务方法要尽量拆小,且尽量不要包含redis操作、分布式锁、引用第三方接口等;用事务前要考虑下能否不使用,能否通过其他方式处理,例如定时器补偿,MQ补偿
- 新增数据表字段不建议设置成not null,这样需要通篇考虑设值的问题,特别是之前已序列化成缓存的,往往会遗漏,导致插入或修改记录失败
- MQ消费者一定要做好幂等操作,还要注意并发的可能性,一般可以加锁、判重处理
- 注意安全性问题,对于敏感字段一般不由前端来传,前端传的话后端也要做多一遍检测
原文: …