如何重构一个长期的if语句?

时间:2017-08-21 16:31:28

标签: javascript refactoring conditional cyclomatic-complexity

我的代码片段达到了极限,试图想出一种重构的方法。

if(item.oldLabelType === 'Fruits') {
  item.newLabel = this._processFruitsLabel(item.oldLabel);
}
else if(item.oldLabelType === 'Vegetables') {
  item.newLabel = this._processVegetablesLabel(item.oldLabel);
}
else if(item.oldLabelType === 'Animals') {
  item.newLabel = this._processAnimalsLabel(item.oldLabel);
}
else if(item.oldLabelType === 'Fish') {
  item.newLabel = this._processFishLabel(item.oldLabel);
}
else if(item.oldLabelType === 'Birds') {
  item.newLabel = this._processBirdsLabel(item.oldLabel);
}
else if(item.oldLabelType === 'Colors') {
  item.newLabel = this._processColorsLabel(item.oldLabel);
}
else if(item.oldLabelType === 'Countries') {
  item.newLabel = this._processCountriesLabel(item.oldLabel);
}
else if(item.oldLabelType === 'Drinks') {
  item.newLabel = this._processDrinksLabel(item.oldLabel);
}
else if(item.oldLabelType === 'Cars' || item.oldLabelType === 'Airplanes') {
  item.newLabel = this._processTransportationLabel(item.oldLabel);
}

概要 - 我正在重构代码库,后端返回不需要的值,即旧标签可能是“仅1000美元”,新标签需要“你今天只需支付1000美元。”。根据发回的item.oldLabelType,标签操作根本不同。因此,我无法真正编写一个适合所有旧标签的新功能。

怎么做!?

4 个答案:

答案 0 :(得分:2)

这里通常的答案是:

  1. 使用switch(但它没有太大的改进,或者可以说是改进)
  2. 使用查找Map或对象
  3. 使用字符串连接和括号表示法
  4. 以下是第三个看起来的样子:

    var functionName = item.oldLabelType === 'Cars' || item.oldLabelType === 'Airplanes'
        ? "_processTransportationLabel"
        : "_process" + item.oldLabelType + "Label";
    if (this[functionName]) {
        item.newLabel = this[functionName](item.oldLabel);
    }
    

答案 1 :(得分:1)

如果调用的大多数函数只是根据标签类型的名称略有不同而相互重复,则可以创建正确的函数名称以便即时调用。如果任何函数名称包含许多标签类型,则可以使用switch语句指定组函数名称。

if (item.oldLabelType) {
   let olt = item.oldLabelType;
   switch (olt) {
     case "Airplane":
     case "Car":
       olt = "Traffic"
       break;
   }
   let func = "_process" + olt + "Label";
   item.newLabel = this[func](item.oldLabel);
 }

答案 2 :(得分:1)

由于函数是JavaScript中的first-class公民,我们可以这样做:

var labelMapping = {
  Fruits: this._processFruitsLabel,
  Vegetables: this._processVegetablesLabel,
  Animals: this._processAnimalsLabel,
  Fish: this._processFishLabel,
  Birds: this._processBirdsLabel,
  Colors: this._processColorsLabel,
  Countries: this._processCountriesLabel,
  Drinks: this._processDrinksLabel,
  Cars: this._processTransportationLabel,
  Airplanes: this._processTransportationLabel
};

var processFn = labelMapping[item.oldLabelType];

if (typeof processFn === 'function') {
  item.newLabel = processFn(item.oldLabel);
} else {
  // Handle when we can't find the process function.
}

有一点需要注意的是,如果您在各种流程函数中使用this,那么您需要确保使用正确的this上下文调用它们。

有两种方法可以做到这一点:

  1. .bind提前履行职能
  2. Fruits: this._processFruitsLabel.bind(this),

    1. 使用.call并传入当前的this
    2. item.newLabel = processFn.call(this, item.oldLabel);

答案 3 :(得分:0)

构建一个对象,用于映射到正确的函数,如下所示:

var targetFunctionMap = {
    "Fruits": this._processFruitsLabel,
    "Vegetables": this._processVegetablesLabel,
    "Animals": this._processAnimalsLabel
    .............
    .............
    .............
    "Cars": this._processTransportationLabel,
    "Airplanes": this._processTransportationLabel
}

然后从那里调用

item.newLabel = targetFunctionMap[item.oldLabelType].call(this);