Replace Nested Conditional with Guard Clauses

原创
2014/03/28 11:05
阅读数 144

Summary 函数中的条件逻辑使人难以看清正常的执行路径。使用卫语句表现所有特殊情况。

                         

动机:

  条件表达式通常有两种表现形式。第一种形式是:所有分支都属于正常行为。第二种形式则是:条件表达式提供的答案中只有一种是正常行为,其他都是不常见的情况。

这两类条件表达式有不同的用途,这一点应该通过代码表现出来。如果两条分支都是正常行为,就应该使用如if…else…的条件表达式;如果某个条件极其罕见,就应该单独检查该条件,并在该条件为真时立刻从函数中返回。这样的单独检查常常被称为“卫语句”(guard clauses

Replace Nested Conditional with Guard Clauses的精髓就是:给某一条分支以特别的重视。如果使用if-then-else结构,你对if分支的重视是同等的。这样的代码结构传递给阅读者的消息就是:各个分支有同样的重要性。卫语句就不同了,它告诉阅读者:“这种情况很罕见,如果它真地发生了,请做一些必要的整理工作,然后退出。”

“每个函数只能有一个入口和一个出口”的观念,根深蒂固于某些程序员的脑海里。当我们处理他们编写的代码时,经常需要使用Replace Nested Conditional with Guard Clauses。现金的编程语言都会强制保证每个函数只有一个入口,至于“单一出口”规则,其实不是那么有用。保持代码清晰才是最关键的:如果单一出口能是这个函数更清楚一度,那么就使用单一出口;否则就不必这么做

做法:

1.对于每个检查,放进一个卫语句。

 卫语句要不就从函数中返回,要不就抛出一个异常。

2.每次将条件检查替换成卫语句后,编译并测试。

 如果所有卫语句都导致相同结果,请使用Consolidate Conditional Expressions 

  范例:

   想象一个薪资系统,其中以特殊规则处理死亡员工、驻外员工、退休员工的薪资。这些情况不常有,但的确偶尔会出现。

假设我们在这个系统中看到下列代码:

double getPayAmount(){
    double result;
    if(_isDead){
        result = deadAmount();
    }else{
        if(_isSeparated){
            result = separatedAmount();
        }else{
            if(_isRetired){
                result = retiredAmount();
            }else{
                result = normalPayAmount();
            }
        }
    }
    return result;
}

在这段代码中,非正常情况的检查掩盖了正常情况的检查,所以应该用卫语句来取代这些检查,以提高程序清晰度。我们可以逐一引入卫语句。让我们从最上面的条件检查动作开始,:

double getPayAmoutn{
    double result;
    if(_isDead){
        return deadAmount();
    }
    if(_isSeparated){
            result = separatedAmount();
        }else{
            if(_isRetired){
                result = retiredAmount();
            }else{
                result = normalPayAmount();
            }
        }
     }
     return result
}

然后继续下去,仍然一次替换一个检查动作,直到最后一个:

double getPayAmoutn{
    double result;
    if(_isDead){
        return deadAmount();
    }
    if(_isSeparated){
        return separatedAmount()
    }
    if(_isRetired){
        return retiredAmount();
    }
    result = normalPayAmout();
    return result;
}

此时,result变量已经没有价值了,所以我们把它删掉:

double getPayAmoutn{
    double result;
    if(_isDead){
        return deadAmount();
    }
    if(_isSeparated){
        return separatedAmount()
    }
    if(_isRetired){
        return retiredAmount();
    }
    return normalPayAmout();
}

嵌套条件代码往往由那些深信“每个函数只能有一个出口”的程序员写出。我发下那条规则实在有点太简单粗暴了。如果对函数剩余部分不再有兴趣,当然应该立刻退出。引导阅读者去看一个没有用的else区段,只会妨碍他们的理解。

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部