异步函数 assignDriver 用来为乘客分配司机,它接收乘客信息和可用司机列表作为参数。
函数先计算每个司机到乘客的距离,然后遍历所有可用司机,检查以下条件:
司机是否在 5 公里以内。
如果乘客有偏好的车型,那么司机的车型必须符合偏好。
司机的评分至少要 4.5 分,如果有高级司机偏好,还要确保司机是高级司机。
如果没有找到满足 4.5 分要求的司机,则接受评分为 4.0 分及以上的司机。
这个过程用了五层嵌套的 if 语句,虽然看起来不糟糕,但可以想象,如果再增加一些其他条件(比如高峰期加价、忠诚度计划等),代码会变得多么复杂。
解决问题
幸运的是,有一些方法可以把这些嵌套的逻辑"拍平",甚至最终可以做到不需要任何 if 语句,我们来看看如何重构这段代码。
1、卫语句(Guard Clauses)
卫子句(Guard Clauses)是一种编程技巧,用于在函数或方法的执行过程中尽早地检查错误条件或异常情况,并在满足这些条件时立即退出函数。
卫子句是一种有效的代码设计模式,有助于编写更加健壮和易于理解的代码。
def divide(a, b):
if b == 0:
raise ValueError("Cannot divide by zero")
return a / b
这个例子中,如果除数 b 为 0,函数会立即抛出一个 ValueError 异常。
我们可以利用卫子句,把最外层的 if 条件拿出来,直接跳过不符合条件的司机,减少嵌套。
下面是修改后的代码:
通过使用卫语句,我们减少了两层嵌套,让代码变得稍微清晰一点。
2、决策表(Decision Tables)
决策表是一种数据结构,用于以表格的形式表示复杂的逻辑决策,使得逻辑决策更加清晰和易于理解。
决策表通常用于替代复杂的条件语句(如if-else嵌套),特别是在逻辑判断较多且条件复杂的情况下。
在编程中,决策表可以通过多种方式实现,例如使用查找表、状态机或专门的决策表库。
以下是使用 Python 实现的一个简单示例:
def evaluate_decision_table(table, context):
for rule in table:
if all(context.get(k) == v for k, v in rule['conditions'].items()):
return rule['action']
return None
# 定义决策表
decision_table = [
{
'conditions': {'age': 18, 'has_license': True},
'action': 'Drive'
},
{
'conditions': {'age': 18, 'has_license': False},
'action': 'Learn to drive'
},
{
'conditions': {'age': 17, 'has_license': True},
'action': 'Cannot drive'
}
]
# 上下文
context = {'age': 18, 'has_license': True}
# 评估决策表
action = evaluate_decision_table(decision_table, context)
print(action) # 输出: Drive
在这个例子中,决策表定义了几条规则,每条规则包含条件和动作。evaluate_decision_table 函数遍历决策表,检查每条规则的条件是否满足,并执行相应的动作。
接下来,我们可以把 if-else 逻辑提取到独立的函数中,构建一个"决策表",这个表格的条目按照特定的顺序排列,从最严格的条件开始,逐个检查司机是否符合条件。
通过决策表,我们完全消除了嵌套的 if 语句,司机分配的逻辑也变得更加灵活,只需要修改条件数组即可。
3、函数组合(Function Composition)
函数组合是一种编程技巧,它允许你将多个函数组合起来,创建一个执行多个函数操作的新函数。
在不同的编程语言中,函数组合可以通过多种方式实现,如直接调用、使用高阶函数、使用函数式编程库等。
函数组合是一种强大的编程模式,可以帮助开发者以更简洁、更模块化的方式构建复杂的逻辑。
Python 示例:
def add(x, y):
return x + y
def multiply(x, y):
return x * y
def add_and_multiply(x, y, z):
return multiply(add(x, y), z)
result = add_and_multiply(1, 2, 3) # 输出: 18
在这个例子中,add_and_multiply 函数组合了 add 和 multiply 两个函数。
JavaScript 示例(使用高阶函数):
const add = (x, y) => x + y;
const multiply = (x, y) => x * y;
const addAndMultiply = (x, y, z) => multiply(add(x, y), z);
const result = addAndMultiply(1, 2, 3); // 输出: 9
最后一步,我们可以通过把 for 循环转换成 Array.find() 方法,并为每个 if 条件创建单独的函数,彻底消除代码中的 if 语句。
通过使用函数式编程的一些基本技巧,我们优化了以下内容:
移除了所有的嵌套 if 语句;
解耦了大部分逻辑,使其更容易修改;
通过将每个 if-else 块放入单独的函数中,使代码更易于理解;
最后,顺便让代码量减少了约三分之一。
参考链接:https://lackofimagination.org/2024/09/avoiding-if-else-hell-the-functional-style/