阅读 22

[重构实践]如何避免代码多层嵌套

原标题《如何避免多层嵌套-案例分析》,创作于2020-07-15

问题

解决箭头型代码和多层嵌套的问题,尽管很符合代码执行顺序,但是难于理解和维护。

解决思路

通常可以使用卫语句,遵循“尽早返回”的原则和面向异常的编程思维对代码进行重构。例子如下:

例子

该例子来自项目真实代码,并且这位同事习惯性的多层嵌套。

<?php

public function nestCode($param1, $status)
{
    if ($param1 == 1) {
      $weNeedParam = 'value_1';
    } elseif ($param1 == 2) {
      if ($status == 1) {
        $weNeedParam = 'value_2';
      } else {
        $weNeedParam = 'value_3';
      }
    } else {
      return false;
    }

  return $this->anotherFunction($weNeedParam);
}
复制代码

当时看完这些相关代码的心情……
截屏2020-10-18 上午2.20.10.jpg

重构

<?php

public function nestCode($param1, $status)
{
  // 优化点 1,尽早返回,考虑异常情况,不符合直接打断
  if (!in_array($param1, [1, 2])) {
    return false;
  }

  // 优化点 2,param1 等于 1 的情况不依赖 status,单独拿出来
  if ($param1 == 1) {
    $weNeedParam = 'value_1';
  }
  // 优化点 3,param1 等于 2的情况 还要判断 status, 这几行作为参考
  if ($param1 == 2 && $status == 1) {
    $weNeedParam = 'values_2';
  }
  if ($param1 == 2 && $status != 1) {
    $weNeedParam = 'values_3';
  }
  
  // 可以处理其他逻辑,我们要使用 $weNeedParam 参数
  // 但是 IDE 可能会提示 Variable '$weNeedParam' is probably undefined 的波浪线标黄提示
  // 所以优化点 4, 会对 $weNeedParam 再进行判断一次,仅作为 防御性 或 严谨性 的判断
  // 至于是否有必要,智者见智
  if (empty($weNeedParam)) {
    return false;
  }

  return $this->anotherFunction($weNeedParam);
}
复制代码

注意
对于优化点 3,当然也可以写成如下,问题不大,不过也避免不来要嵌套

<?php

    // 优化点 3,的另外一种写法
  if ($param1 == 2) {
    $weNeedParam = 'values_3';
    if ($status == 1) {
      $weNeedParam = 'values_2';
    }
  }
复制代码


当然亦可写成如下,看起来少了一个 if 关键字判断,但是效果一样

<?php

    // 优化点 3,的另外一种写法
  if ($param1 == 2) {
    // 针对 $param1 == 2 的情况直接赋值
    $weNeedParam = 'values_3';
    // 对于特殊情况再单独判断
    $status == 1 && $weNeedParam = 'values_2';
  }
复制代码

待优化

param1的等值判断12,还有param1 的等值判断 1、2,还有 status 的 1 都属于神秘数字,或者说是 魔法值,我们不知道这个值代表的含义是什么。更多案例可以参考《阿里巴巴Java开发手册》关于_常量定义_的章节。

总结

  • 理清头绪,明白什么是预期的主逻辑,把次要的、异常的,单独判断出来,把主逻辑显露出来。
  • 优化无止境,但是优化意识少不了。

好代码看着就是舒服

重构.jpg

扩展