优化代码中的if/else逻辑
“如果你的代码里有if/else,那么你的代码设计就有问题!“。这几年对这话颇有感触。过多的if/else往往反应出coder的”慵懒“。数量过度或嵌套太深的if/else代码,对维护这份代码的人而言是噩梦!
我认为过度使用if/else存在以下几点坏处:
1、用if/else表达的业务逻辑是链式的,一旦业务逻辑经过多次迭代后变得复杂,其逻辑也变得臃肿且晦涩;
2、if/else缺乏可扩展性,遇到新增功能只能不断地嵌套或堆叠if/else,最终形成人人喊打的”金字塔“代码结构;
3、if/else不好把控判断条件,if/elseif1/elseif2/.../else,elseif需要关注前面的判断结果,极易造成逻辑判断错误,而很多线上问题均源于此。
综上所述,我不建议在代码中使用过多的if/else块。本文提供一些实用的技巧,帮你减少if/else代码块的使用。不一定都对,欢迎拍砖讨论。
阅读本文你讲得到
- 为什么会产生if/else代码块
- 为什么要避免过度使用if/else代码块
- 如何优化”金字塔“式的代码块
1、为什么会产生if/else代码块
通常我们会用if/else控制业务流程,在不同场景下的执行过程是不一样的。if/else符合面向过程编程的思想,符合我们习以为常的线性化的思维模式。当业务逻辑无法用不含嵌套的if/else表达时,代码变得臃肿且缺乏可读性。
2、为什么要避免过度使用if/else代码块
- 用if/else表达的逻辑可扩展性差
- 代码可读性差,影响迭代效率
- 维护成本高,增加开发成本
3、如何优化”金字塔“式的if/else代码块
3.1 提前return
判断上下文是否符合条件再执行正常流程而异常流程仅需打日志的场景,if代码块可列举异常场景并提前返回。以买家在电商平台购买商品为例:
if (买家是风险用户) {
return 风险用户购买失败;
}
if (商品库存不足) {
return 商品库存不足;
}
...
// 处理正常的购买逻辑
...
而不是采用叠罗汉式的if/else块:
if (符合正常购买的条件) {
// do something
} elseif (买家是风险用户) {
return 风险用户购买失败;
} elseif (商品库存不足) {
return 商品库存不足;
} else {
// unknown scene
}
3.2 利用多态
编写基础设置层代码时,有根据不同场景类型调用不同处理器的逻辑,而处理器一般处理相同的业务流程。以电商平台的库存系统为例,以扣减模式为准,分为付款前(拍下)扣库存和付款减库存,或者其它模式。也许你的代码会是这样:
if (deductInventoryType.equals(BEFORE_PAY_DEDUCT_INVENTORY_TYPE)) {
// do something
} elseif (deductInventoryType.equals(AFTER_PAY_DEDUCT_INVENTORY_TYPE)) {
// do someting
} elseif (...) {
// do something
} else {
throw new Exception("Unknown deduct inventory type!");
}
随着业务体量变大,你的if/else块变得臃肿而难以维护,新人在迭代开发时必须得小心翼翼避免踩坑,业务之间隔离性差,这都讲阻碍模块迭代速度。
我们可以用多态的方式优化:
// DeductInventoryHandler.class
public interface DeductInventoryHandler {
Result deductInventory(...) throws Exception;
}
// deductInventoryHandlerMap是以key=deductInventoryType, value=DeductInventoryHandler的Map结构
if (deductInventoryHandlerMap.containsKey(deductInventoryType)){
Result result = deductInventoryHandlerMap.get(deductInventoryType).deductInventory(...);
// do something
}
我可以在服务启动时实例化子类并用Map接口管理起来:
Map<String, DeductInventoryHandler> handlers;
...
handlers.do(deductInventoryType);
相比if/else的方式,代码量骤减但可读性增强,handlers的拥有者专注控制执行流程,而把业务逻辑交给Handler处理。
3.3 利用Optional减少if判空次数(仅限于java)
我们知道,Optional封装了空和非空两条执行链,利用Optional.orElse()处理空的场景。
// itemInfo类型为class ItemInfo
// if/else版本
if (itemInfo == null) {
itemInfo = new ItemInfo();
}
itemInfo.doSomething(...);
// Optional版本
Optional.ofNullable(itemInfo).orElse(new ItemInfo()).doSomethign(...);