为什么我不建议你用去 “ ! = null " 做判空?
字节跳动的面试算法题,实在太变态了
爱奇艺的实时数据架构到底有多牛?
求求你!别再这样用 HashMap 了好吗?
刷题一个半月,一口气拿下腾讯、华为、Oppo、微软7个大厂offer,字节跳动薪资涨幅60%!
点击“开发者技术前线”,选择“星标🔝”
在看|星标|留言, 真爱
if else 是所有高级编程语言都有的必备功能。但现实中的代码往往存在着过多的 if else。
作者:艾瑞克·邵 图片来自 Pexels
编辑:陶家龙
出处:https://www.cnblogs.com/eric-shao/p/10115577.html
虽然 if else 是必须的,但滥用 if else 会对代码的可读性、可维护性造成很大伤害,进而危害到整个软件系统。
现在软件开发领域出现了很多新技术、新概念,但 if...else 这种基本的程序形式并没有发生太大变化。
使用好 if else 不仅对于现在,而且对于将来,都是十分有意义的。今天我们就来看看如何“干掉”代码中的 if else,还代码以清爽。
问题一:if else 过多
问题表现
if else 过多的代码可以抽象为下面这段代码。其中只列出 5 个逻辑分支,但实际工作中,能见到一个方法包含 10 个、20 个甚至更多的逻辑分支的情况。
另外,if else 过多通常会伴随着另两个问题:逻辑表达式复杂和 if else 嵌套过深。
if (condition1) {
} else if (condition2) {
} else if (condition3) {
} else if (condition4) {
} else {
}
通常,if else 过多的方法,通常可读性和可扩展性都不好。
从软件设计角度讲,代码中存在过多的 if else 往往意味着这段代码违反了违反单一职责原则和开闭原则。
因为在实际的项目中,需求往往是不断变化的,新需求也层出不穷。所以,软件系统的扩展性是非常重要的。
而解决 if else 过多问题的最大意义,往往就在于提高代码的可扩展性。
如何解决
接下来我们来看如何解决 ifelse 过多的问题,下面我列出了一些解决方法:
表驱动
职责链模式
注解驱动
事件驱动
有限状态机
Optional
Assert
多态
if (param.equals(value1)) {
doAction1(someParams);
} else if (param.equals(value2)) {
doAction2(someParams);
} else if (param.equals(value3)) {
doAction3(someParams);
}
// ...
可重构为:
Map<?, Function<?> action> actionMappings = new HashMap<>(); // 这里泛型 ? 是为方便演示,实际可替换为你需要的类型
// When init
actionMappings.put(value1, (someParams) -> { doAction1(someParams)});
actionMappings.put(value2, (someParams) -> { doAction2(someParams)});
actionMappings.put(value3, (someParams) -> { doAction3(someParams)});
// 省略 null 判断
actionMappings.get(param).apply(someParams);
下面借用《编程珠玑》中的一个税金计算的例子:
if income <= 2200
tax = 0
else if income <= 2700
tax = 0.14 * (income - 2200)
else if income <= 3200
tax = 70 + 0.15 * (income - 2700)
else if income <= 3700
tax = 145 + 0.16 * (income - 3200)
......
else
tax = 53090 + 0.7 * (income - 102200)
重构前:
public void handle(request) {
if (handlerA.canHandle(request)) {
handlerA.handleRequest(request);
} else if (handlerB.canHandle(request)) {
handlerB.handleRequest(request);
} else if (handlerC.canHandle(request)) {
handlerC.handleRequest(request);
}
}
重构后:
public void handle(request) {
handlerA.handleRequest(request);
}
public abstract class Handler {
protected Handler next;
public abstract void handleRequest(Request request);
public void setNext(Handler next) { this.next = next; }
}
public class HandlerA extends Handler {
public void handleRequest(Request request) {
if (canHandle(request)) doHandle(request);
else if (next != null) next.handleRequest(request);
}
}
表驱动通常是一对一的关系;事件驱动通常是一对多。
表驱动中,触发和执行通常是强依赖;事件驱动中,触发和执行是弱依赖。
有限状态机通常被称为状态机(无限状态机这个概念可以忽略)。先引用维基百科上的定义:
有限状态机(英语:finite-state machine,缩写:FSM),简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。
①Apache Mina State Machine
https://mina.apache.org/mina-project/userguide/ch14-state-machine/ch14-state-machine.html
②Spring State Machine
Spring 子项目众多,其中有个不显山不露水的状态机框架,可以通过 DSL 和注解两种方式定义。
https://projects.spring.io/spring-statemachine/
String str = "Hello World!";
if (str != null) {
System.out.println(str);
} else {
System.out.println("Null");
}
使用 Optional 之后:
Optional<String> strOptional = Optional.of("Hello World!");
strOptional.ifPresentOrElse(System.out::println, () -> System.out.println("Null"));
Kotlin 带有一个被称为 Null Safety 的特性:
bob?.department?.head?.name
Apache Commons Lang 中的 Validate 类:
https://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/Validate.html
Spring 的 Assert 类:
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/util/Assert.html
https://refactoring.com/catalog/replaceConditionalWithPolymorphism.html
问题二:if else 嵌套过深
问题表现
if else 多通常并不是最严重的的问题。有的代码 if else 不仅个数多,而且 if else 之间嵌套的很深,也很复杂,导致代码可读性很差,自然也就难以维护。
if (condition1) {
action1();
if (condition2) {
action2();
if (condition3) {
action3();
if (condition4) {
action4();
}
}
}
}
如何解决
抽取方法
卫语句
public void add(Object element) {
if (!readOnly) {
int newSize = size + 1;
if (newSize > elements.length) {
Object[] newElements = new Object[elements.length + 10];
for (int i = 0; i < size; i++) {
newElements[i] = elements[i];
}
elements = newElements
}
elements[size++] = element;
}
}
重构后:
public void add(Object element) {
if (readOnly) {
return;
}
if (overCapacity()) {
grow();
}
addElement(element);
}
直接看代码:
double getPayAmount() {
double result;
if (_isDead) result = deadAmount();
else {
if (_isSeparated) result = separatedAmount();
else {
if (_isRetired) result = retiredAmount();
else result = normalPayAmount();
};
}
return result;
}
重构之后:
double getPayAmount() {
if (_isDead) return deadAmount();
if (_isSeparated) return separatedAmount();
if (_isRetired) return retiredAmount();
return normalPayAmount();
}
问题三:if else 表达式过于复杂
问题表现
当 condition 1、2、3、4 分别为 true、false,请大家排列组合一下下面表达式的结果:
if ((condition1 && condition2 ) || ((condition2 || condition3) && condition4)) {
}
如何解决
总结