Skip to content
快速预览

解决if多层嵌套问题

✍️ w 🕒 2023-07-23 12:23:51(10 months ago) 🔗 G.设计模式

我们经常会遇到嵌套的条件表达式,例如if...else if...else if...else这样的结构。这种结构虽然在逻辑上没有问题,但是在阅读和理解代码的时候,可能会造成一定的困扰,因为需要跟踪多个条件和分支。

造成缩进的原因是 if 语句。通常来说,if 语句造成的缩进,很多时候都是在检查某个先决条件,只有条件通过时,才继续执行后续的代码。这样的代码可以使用卫语句(guard clause)来解决,也就是设置单独的检查条件,不满足这个检查条件时,立刻从函数中返回。

这种解决问题的方法叫做以卫语句取代嵌套的条件表达式(Replace Nested Conditional with Guard Clauses)。他是一种典型的重构手法

案例

java
private void distributeEpub(final Epub epub) {

    if (epub.isValid()) {
      boolean registered = this.registerIsbn(epub);
      if (registered) {
        this.sendEpub(epub);
      }
    }
  }
  • 卫语句(Guard Clauses)是一种替代嵌套条件表达式的方法。卫语句是一种早期退出的策略,当函数的某个条件被满足时,就直接返回,不再执行后面的代码。这样可以减少代码的复杂性,提高代码的可读性。
java
private void distributeEpub(final Epub epub) {

    if (!epub.isValid()) {
      return;
    }

    boolean registered = this.registerIsbn(epub);
    if (!registered) {
      return;
    }
    this.sendEpub(epub);
  }

减少else

函数至多有一层缩进,这是“对象健身操(《ThoughtWorks 文集》书里的一篇)”里的一个规则。前面讲“[大类]”的时候,我曾经提到过“对象健身操”这篇文章,其中给出了九条编程规则,下面我们再来讲其中的一条:不要使用 else 关键字。

没错,else 也是一种坏味道,这是挑战很多程序员认知的。在大多数人印象中,if 和 else 是亲如一家的整体,它们几乎是比翼齐飞的

举个例子

java
public double getEpubPrice(final boolean highQuality, final int chapterSequence) {

    double price = 0;

    if (highQuality && chapterSequence > START_CHARGING_SEQUENCE) {
      price = 4.99;
    } else if (sequenceNumber > START_CHARGING_SEQUENCE
          && sequenceNumber <= FURTHER_CHARGING_SEQUENCE) {
      price = 1.99;
    } else if (sequenceNumber > FURTHER_CHARGING_SEQUENCE) {
      price = 2.99;
    } else {
      price = 0.99;
    }
    return price;
  }

如果想不使用 else,一个简单的处理手法就是让每个逻辑提前返回,这和我们前面提到的卫语句的解决方案如出一辙:

java
public double getEpubPrice(final boolean highQuality, final int chapterSequence) {

    if (highQuality && chapterSequence > START_CHARGING_SEQUENCE) {
      return 4.99;
    }

    if (sequenceNumber > START_CHARGING_SEQUENCE
          && sequenceNumber <= FURTHER_CHARGING_SEQUENCE) {
      return 1.99;
    }

    if (sequenceNumber > FURTHER_CHARGING_SEQUENCE) {
      return 2.99;
    }
    return 0.99;
    }

圈复杂度

无论上面那种方式,都是为了解决一段代码的分支过多,其复杂度就会大幅度增加

在软件开发中,有一个衡量代码复杂度常用的标准,叫做圈复杂度(Cyclomatic complexity,简称 CC),圈复杂度越高,代码越复杂,理解和维护的成本就越高。在圈复杂度的判定中,循环和选择语句占有重要的地位。

只要我们能够消除嵌套,消除 else,代码的圈复杂度就不会很高,理解和维护的成本自然也就会随之降低。

Released under the MIT License.