如何优雅的避免代码嵌套

避免过度代码嵌套是保持代码可读性和可维护性的关键步骤,特别是在编程中。以下是每一种方法,并附上在未优化代码和优化后代码的例子。

表驱动法

这种方法通过使用查找表替代复杂的条件语句来简化代码,减少嵌套。

未优化代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
function calculateTax(income) {
let tax;
if (income < 20000) {
tax = income * 0.1;
} else if (income < 40000) {
tax = income * 0.2;
} else if (income < 80000) {
tax = income * 0.3;
} else {
tax = income * 0.4;
}
return tax;
}

优化后的代码示例:

1
2
3
4
5
6
7
8
9
10
11
const taxBrackets = [
{ threshold: 80000, rate: 0.4 },
{ threshold: 40000, rate: 0.3 },
{ threshold: 20000, rate: 0.2 },
{ threshold: 0, rate: 0.1 },
];

function calculateTax(income) {
const bracket = taxBrackets.find((bracket) => income > bracket.threshold);
return income * bracket.rate;
}

状态模式

状态模式允许对象在内部状态改变时改变它的行为。

未优化代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Order {
constructor() {
this.state = "Taking Order";
}

nextStage() {
if (this.state === "Taking Order") {
this.state = "Order Preparing";
} else if (this.state === "Order Preparing") {
this.state = "Order Ready";
} else if (this.state === "Order Ready") {
this.state = "Order Served";
}
}
}

优化后的代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class OrderState {
next(order) {
throw new Error("OrderState.next needs to be implemented");
}
}

class TakingOrderState extends OrderState {
next(order) {
order.setState(new OrderPreparingState());
}
}

class OrderPreparingState extends OrderState {
next(order) {
order.setState(new OrderReadyState());
}
}

class OrderReadyState extends OrderState {
next(order) {
order.setState(new OrderServedState());
}
}

class OrderServedState extends OrderState {
next(order) {
// Final state, no next state
}
}

class Order {
constructor() {
this.state = new TakingOrderState();
}

setState(state) {
this.state = state;
}

nextStage() {
this.state.next(this);
}
}

Lambda 表达式

Lambda 表达式可以减少匿名类的冗余代码。

未优化代码示例:

1
2
3
4
5
6
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
System.out.println("Button Pressed");
}
});

优化后的代码示例:

1
button.addActionListener(ae -> System.out.println("Button Pressed"));

空值判断

使用 Optional 或者类似的可选类型可以避免深层次的空值检查。

未优化代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
public String getCountry(User user) {
if (user != null) {
Address address = user.getAddress();
if (address != null) {
Country country = address.getCountry();
if (country != null) {
return country.getName();
}
}
}
return "Unknown";
}

优化后的代码示例:

1
2
3
4
5
6
7
public String getCountry(User user) {
return Optional.ofNullable(user)
.map(User::getAddress)
.map(Address::getCountry)
.map(Country::getName)
.orElse("Unknown");
}

设计模式

使用设计模式可以提高代码的可读性和可维护性,比如策略模式可以避免条件语句。

未优化代码示例:

1
2
3
4
5
6
7
8
9
function calculateDiscount(items, type) {
if (type === "fixed") {
return items * 10;
} else if (type === "percentage") {
return items * 0.1;
} else {
return items;
}
}

优化后的代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class DiscountStrategy {
applyDiscount(items) {
throw new Error("DiscountStrategy.applyDiscount needs to be implemented");
}
}

class FixedDiscountStrategy extends DiscountStrategy {
applyDiscount(items) {
return items - 10;
}
}

class PercentageDiscountStrategy extends DiscountStrategy {
applyDiscount(items) {
return items * 0.9;
}
}

function calculateDiscount(items, strategy) {
return strategy.applyDiscount(items);
}

// Usage:
const fixedStrategy = new FixedDiscountStrategy();
const percentageStrategy = new PercentageDiscountStrategy();
calculateDiscount(100, fixedStrategy);
calculateDiscount(100, percentageStrategy);

创建子函数

一个简单的技巧是将复杂函数拆解为多个子函数,这有助于减少嵌套层次。

未优化代码示例:

1
2
3
4
5
6
7
8
9
10
11
function processData(data) {
if (data) {
// 假设这里有10行处理 data 的代码
if (data.hasDetail()) {
// 又是一些复杂的处理
if (data.detail.isComplete()) {
// 处理完成
}
}
}
}

优化后的代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function processDetail(detail) {
if (detail.isComplete()) {
// 处理完成
}
}

function processData(data) {
if (!data) {
return;
}
// 简化的处理 data 的代码

if (data.hasDetail()) {
processDetail(data.detail);
}
}

异步编程的优化

在 JavaScript 中,过度的嵌套通常出现在处理异步操作时,可以使用Promiseasync/await来减少嵌套。

未优化代码示例:

1
2
3
4
5
6
7
8
9
getData(function (a) {
getMoreData(a, function (b) {
getEvenMoreData(b, function (c) {
getSoMuchData(c, function (d) {
// 嵌套太深
});
});
});
});

优化后的代码示例:

1
2
3
4
5
6
7
8
9
10
11
async function processData() {
try {
let a = await getData();
let b = await getMoreData(a);
let c = await getEvenMoreData(b);
let d = await getSoMuchData(c);
// 流程清晰
} catch (error) {
// 错误处理
}
}

利用早期返回规避嵌套

早期返回意味着一旦满足特定条件就立即从函数返回,而不是继续进入下一层嵌套。

未优化代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function login(user) {
if (user) {
if (user.active) {
if (checkPassword(user)) {
// 登录成功
} else {
// 密码错误
}
} else {
// 用户未激活
}
} else {
// 用户不存在
}
}

优化后的代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function login(user) {
if (!user) {
// 用户不存在
return;
}
if (!user.active) {
// 用户未激活
return;
}
if (!checkPassword(user)) {
// 密码错误
return;
}
// 登录成功
}