降低 if elseif 条件的复杂性

reduce complexity of if elseif conditions

我有一个函数有 if elseif 条件,圈复杂度接近 5。我该如何降低它?

function testFunc() {
    var step = getModel('step');
    if(step === 1) {
        this.resetTask(); //calling some function
        this.updateStep(0);
        return true;
    } else if(step === 2) {
        this.initTask; //some other function
        return true;
    } else if(step === 3) {
        this.name === 'add' ? this.add() : this.edit();
        return true;
    }
    return false;
}

尝试用 switch case 替换,但没有用。

对我来说,像这样改变它可以让理解变得不那么复杂。尽管对某些人来说可读性较差。也快了一点。

function testFunc() {
 var step = getModel('step');
 if(step==1){this.editTask(); this.updateStep(0); return true;} 
 if(step==2){this.initTask; return true;} 
 if(step==3){this.name==='add' ? this.add() : this.edit();return true;}
 return false;
}

非常简单的重构 - 删除您现在拥有的所有条件逻辑,并将每个部分作为单独的函数提取到映射中。由于每次只执行一个分支,根据 step,您可以将该值作为键并获取需要执行的内容。然后,当没有任何内容对应于 step 时,您可以提供回退。

现在圈复杂度为 2,因为代码分支只有一个地方 - 您要么找到 step 的相应处理程序,要么找不到。此外,步骤 3 中的分支现在是一个完全独立的函数,因此它不需要算作 testFunc

的一部分
function testFunc() {
  var step = getModel('step');

  var steps = {
    1: function() {
      this.editTask(); //calling some function
      this.updateStep(0);
      return true;
    },
    2: function() {
      this.initTask; //some other function
      return true;
    },
    3: function() {
      this.name === 'add' ? this.add() : this.edit();
      return true;
    },
    default: function() { 
      return false; 
    }
  };

  var fn = steps[step] || steps.default;

  return fn();
}

这将降低代码的复杂性并提高可读性。 您可以将条件解耦为多个函数,并将该函数附加到条件对象中。在这里,我在参数中传递了这个,但你可以使用不同的方法。在这里我也给出了 this 的值,只是为了 运行 的例子。复制并粘贴到您的编辑器中并尝试。

function meaningfulFuncName1() {
  this.editTask(); //calling some function
  this.updateStep(0);
  return true;
}

function meaningfulFuncName2() {
  this.initTask; //some other function
  return true;
}

function meaningfulFuncName3(context) {
  context.name === 'add' ? context.add() : context.edit();
  return true;
}

function defaultCase() {
  return false;
}

function testFunc() {
  this.name = 'add'
  const step = getModel('step')
  conditionObject = {
    1: meaningfulFuncName1,
    2: meaningfulFuncName2,
    3: meaningfulFuncName3,
    default: defaultCase
  }
  return conditionObject[step](this);
}