什么是卫语句

卫语句(Guard Clause)是一种编程中的设计模式,用来提前处理异常情况或不符合预期的条件,从而避免深层嵌套和复杂的条件逻辑

快速认识卫语句

假设有一个函数,它的任务是接收用户信息并发送欢迎邮件。需要对用户信息进行多项验证,比如检查用户是否为 null、是否激活账户、是否有有效的邮箱地址等。如果所有条件都满足,就执行发送邮件操作。

反例:未使用卫语句(嵌套过深)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void sendWelcomeEmail(User user) {
if (user != null) { // 检查用户是否为空
if (user.isActive()) { // 检查用户是否激活
if (user.getEmail() != null && !user.getEmail().isEmpty()) { // 检查邮箱是否有效
System.out.println("正在向 " + user.getEmail() + " 发送欢迎邮件");
} else {
System.out.println("邮箱地址无效");
}
} else {
System.out.println("用户未激活");
}
} else {
System.out.println("用户为空");
}
}

问题分析:

  • 多重嵌套使得代码的可读性差,很难一眼看出主要的逻辑是“发送欢迎邮件”。
  • 需要逐层阅读每个 if-else 条件,理解起来费力。

使用了卫语句重构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public void sendWelcomeEmail(User user) {
// 使用卫语句提前返回处理特殊情况
if (user == null) {
System.out.println("用户为空");
return;
}

if (!user.isActive()) {
System.out.println("用户未激活");
return;
}

if (user.getEmail() == null || user.getEmail().isEmpty()) {
System.out.println("邮箱地址无效");
return;
}

// 通过条件后,执行主逻辑
System.out.println("正在向 " + user.getEmail() + " 发送欢迎邮件");
}

重构后的优点:

  • 通过提前退出 (return) 来处理各种不符合条件的情况,避免了多层 if-else 嵌套。
  • 主逻辑部分(发送欢迎邮件)保持在函数的末尾,使代码清晰地表达出主要目的:发送邮件。
  • 更容易维护:如果需要新增条件,只需添加新的卫语句,而不影响主逻辑的可读性。

进一步优化:使用异常代替 return

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public void sendWelcomeEmail(User user) {
if (user == null) {
throw new IllegalArgumentException("用户对象不能为 null");
}

if (!user.isActive()) {
throw new IllegalStateException("用户未激活,无法发送欢迎邮件");
}

if (user.getEmail() == null || user.getEmail().isEmpty()) {
throw new IllegalArgumentException("邮箱地址无效,无法发送欢迎邮件");
}

// 主逻辑部分
System.out.println("正在向 " + user.getEmail() + " 发送欢迎邮件");
}

卫语句的特点

  1. 条件判断简洁明了:卫语句通过在函数的开头放置判断条件,使得代码的控制流清晰易懂。
  2. 提前退出:如果某个条件不满足,函数会立刻终止(返回或抛出异常),不再执行后续的代码逻辑。
  3. 减少嵌套:由于提前处理不符合条件的分支,主逻辑部分的代码不会受到多重嵌套的影响,从而保持代码的平坦性。

卫语句的作用

  1. 提高代码的可读性和可维护性: 卫语句能将函数中的异常情况和特殊条件处理放在前面,使得正常流程保持在函数的主干部分,从而让代码更易于理解和维护。

  2. 减少嵌套和代码复杂度: 通过尽早返回或抛出异常,避免了在函数中层层嵌套 if-else 语句。这样不仅减少了代码的层次深度,还让主流程更加直观。

  3. 提高错误处理的透明度: 通过卫语句可以清楚地表明哪些输入参数、条件是合法的,并能够快速处理不合法的情况,使得代码对异常情况的处理变得更加直接。

参考资料

阿里巴巴Java开发手册(嵩山版)八、控制语句第7点:
超过3层的 if-else 的逻辑判断代码可以使用卫语句、策略模式、状态模式等来实现