我们如何针对Java中的If Else Optimization优化以下代码?

时间:2017-01-04 07:10:39

标签: java if-statement refactoring

任何人都可以帮助优化此代码,以减少if_else语句切换案例,因为Sonar显示主要缺陷和NpathComplexity。

if (status != null) {
            if (MDOConstants.DOCREATED.equalsIgnoreCase(status)) {
                return null;
            } else if (MDOConstants.INPROGRESS.equalsIgnoreCase(status)
                    && MDOConstants.MDO_Stored.equalsIgnoreCase(subStatus)) {
                return MDOConstants.INPROGRESS;
            } else if (MDOConstants.INPROGRESS.equalsIgnoreCase(status)
                     && MDOConstants.GCSS_SUBMITTED.equalsIgnoreCase(subStatus)) {
                return MDOConstants.INPROGRESS;
            } else if (MDOConstants.INPROGRESS.equalsIgnoreCase(status)
                     && MDOConstants.PENDING_TASKS.equalsIgnoreCase(subStatus)) {
                return MDOConstants.INPROGRESS;
            } else if (MDOConstants.INPROGRESS.equalsIgnoreCase(status)
                     && MDOConstants.ISSUANCE_OK.equalsIgnoreCase(subStatus)) {
                return MDOConstants.INPROGRESS;
            } else if (MDOConstants.INPROGRESS.equalsIgnoreCase(status)
                    && MDOConstants.GCSS_REQUESTED.equalsIgnoreCase(subStatus)) {
                return MDOConstants.ISSUANCE_REQUESTED;
            } else if (MDOConstants.INPROGRESS.equalsIgnoreCase(status)
                     && MDOConstants.GCSS_ISSUED.equalsIgnoreCase(subStatus)) {
                return MDOConstants.ISSUANCE_REQUESTED;
            } else if (MDOConstants.INPROGRESS.equalsIgnoreCase(status)
                     && MDOConstants.DEADLINE_PASSED.equalsIgnoreCase(subStatus)) {
                return MDOConstants.INPROGRESS;
            } else if (MDOConstants.INPROGRESS.equalsIgnoreCase(status)
                     && MDOConstants.DEADLINE_PASSED_OR_NEW_PICKUPDATE_NEEDED.equalsIgnoreCase(subStatus)) {
                return MDOConstants.INPROGRESS;
            } else if (MDOConstants.MNLHNDLD.equalsIgnoreCase(status)
                    && MDOConstants.MNLHNDLD_TECHNICAL.equalsIgnoreCase(subStatus)) {
                return MDOConstants.MNLHNDLD;
            } else if (MDOConstants.MNLHNDLD.equalsIgnoreCase(status)
                     && MDOConstants.MNLHNDLD_OUTSIDE_MDO.equalsIgnoreCase(subStatus)) {
                return MDOConstants.MNLHNDLD;
            } else if (MDOConstants.DOISSUED.equalsIgnoreCase(status)) {
                return MDOConstants.DOISSUED;
            }
        }

5 个答案:

答案 0 :(得分:4)

首先,由于性能不佳,您不应该重构此代码;或声纳抱怨。

你应该重构它,原因很简单,像这样的东西不可读。人们可以在这样的代码中隐藏3,5个拼写错误,并且数十人会忽视这一点。

那么,你想做什么:应用single layer of abstraction原则。

因此,返工可能如下所示:

public Whatever findWhateverForPotentiallyNull(String status) {
  if (status == null) {
    return null;

  return findWhatEverFor(status.toUpperCase());
}

private Whatever findWhateverFor(String ucStatus) {
  if (ucStatus.equals(DOCREATED)) {
    return null;
  }

  if (ucStatus.equals(INPROGRESS)) {
    return findWhateverForSubStatus(substatus);
  }

......等等。注意:

  • 使用equals()equalsIgnoreCase()便宜;所以不要一直做晚些时候;只需确保您的传入状态与常量具有相同的效果
  • 我建议对所有这些常量使用静态导入;班级名经常在那里重复;所以它真的没有价值;与此相反的;它使阅读更难。
  • 是的 - 你真的进入并用一整套小私有助手方法替换那个冗长的if / else树。关键是:简单,简短的方法可以比任何大得多的方法更快地阅读和理解10倍。

超越纯粹的重构:

  • 使用字符串获取状态...听起来像是不好的做法。 Java是一种强类型语言,您应该努力使用特定的类来模拟核心数据;而不是遍布整个地方的字符串!
  • 并且,如某些评论所述:您可以考虑使用其他类型的"查找"这里;例如,通过使用潜在状态列表;或地图;或类似的东西。

答案 1 :(得分:1)

我想出了类似的东西

if (status != null)
{
    if (MDOConstants.DOCREATED.equals(status)) 
    {
        return null;
    }
    else if(MDOConstants.INPROGRESS.equals(status)) 
    {
        if(MDOConstants.MDO_Stored.equals(subStatus) || 
            MDOConstants.GCSS_SUBMITTED.equals(subStatus) ||
            MDOConstants.PENDING_TASKS.equals(subStatus) ||
            MDOConstants.ISSUANCE_OK.equals(subStatus) || 
            MDOConstants.DEADLINE_PASSED.equals(subStatus) ||
            MDOConstants.DEADLINE_PASSED_OR_NEW_PICKUPDATE_NEEDED.equals(subStatus))
        {
            return MDOConstants.INPROGRESS;
        } 
        else if(MDOConstants.GCSS_REQUESTED.equals(subStatus) ||
            MDOConstants.GCSS_ISSUED.equals(subStatus))
        {
            return MDOConstants.ISSUANCE_REQUESTED;
        }
    }  
    else if(MDOConstants.MNLHNDLD.equals(status))
    {
        if(MDOConstants.MNLHNDLD_TECHNICAL.equals(subStatus) ||
            MDOConstants.MNLHNDLD_OUTSIDE_MDO.equals(subStatus))
        {
            return MDOConstants.MNLHNDLD;
        }
    } 
    else if(MDOConstants.DOISSUED.equals(status))
    {
        return MDOConstants.DOISSUED;
    }
}

答案 2 :(得分:1)

如果这是您的确切业务逻辑,与上面的所有返回路径相反,您的代码实际上只返回5个不同的值,一个为null,另外四个为状态。

所有子状态中只有2个甚至在状态结果中也有所不同。

如果上面的代码是正确的,那么这段代码将实现完全相同的结果:

if (status == null || MDOConstants.DOCREATED.equalsIgnoreCase(status))
    return null;


if (MDOConstants.INPROGRESS.equalsIgnoreCase(status))
{
    if (MDOConstants.GCSS_REQUESTED.equalsIgnoreCase(subStatus) || MDOConstants.GCSS_ISSUED.equalsIgnoreCase(subStatus))
        return MDOConstants.ISSUANCE_REQUESTED;
    else
        return MDOConstants.INPROGRESS
}
else if (MDOConstants.MNLHNDLD.equalsIgnoreCase(status)
    return MDOConstants.MNLHNDLD;
else if (MDOConstants.DOISSUED.equalsIgnoreCase(status))
    return MDOConstants.DOISSUED;

//Maybe have some default if all else fails here.

答案 3 :(得分:0)

像GhostCat说的那样,我不会因为不好的原因而更新这个。但是我使用这种逻辑对你的未来代码进行了小评论,我将在这里使用一个小块

if (MDOConstants.INPROGRESS.equalsIgnoreCase(status)
                && MDOConstants.MDO_Stored.equalsIgnoreCase(subStatus)) {
    return MDOConstants.INPROGRESS;
} else if (MDOConstants.INPROGRESS.equalsIgnoreCase(status)
                 && MDOConstants.GCSS_SUBMITTED.equalsIgnoreCase(subStatus)) {
     return MDOConstants.INPROGRESS;
} else if (MDOConstants.INPROGRESS.equalsIgnoreCase(status)
                 && MDOConstants.PENDING_TASKS.equalsIgnoreCase(subStatus)) {
     return MDOConstants.INPROGRESS;
} else if (MDOConstants.INPROGRESS.equalsIgnoreCase(status)
                 && MDOConstants.ISSUANCE_OK.equalsIgnoreCase(subStatus)) {
     return MDOConstants.INPROGRESS;
}

这是重要的。你总是先做同样的检查。只需在此块中进行一次,即可进行特定测试。

if (MDOConstants.INPROGRESS.equalsIgnoreCase(status)){
    if(MDOConstants.MDO_Stored.equalsIgnoreCase(subStatus)) {
        return MDOConstants.INPROGRESS;
    } else if (MDOConstants.GCSS_SUBMITTED.equalsIgnoreCase(subStatus)) {
         return MDOConstants.INPROGRESS;
    } else if (MDOConstants.PENDING_TASKS.equalsIgnoreCase(subStatus)) {
         return MDOConstants.INPROGRESS;
    } else if (MDOConstants.ISSUANCE_OK.equalsIgnoreCase(subStatus)) {
         return MDOConstants.INPROGRESS;
    }
}

然后,你有很多return,所以你可以存储结果返回,这更容易跟踪(但这是个人的)。

当然,你只返回几个不同的值,你可以使用一个大的条件

if (MDOConstants.INPROGRESS.equalsIgnoreCase(status)){
    if(MDOConstants.MDO_Stored.equalsIgnoreCase(subStatus) ||  
               MDOConstants.GCSS_SUBMITTED.equalsIgnoreCase(subStatus) || 
               MDOConstants.PENDING_TASKS.equalsIgnoreCase(subStatus)) || 
               MDOConstants.ISSUANCE_OK.equalsIgnoreCase(subStatus)) {
         return MDOConstants.INPROGRESS;
    }
}

最后,我喜欢用Collection或Arrays编写它。

static final List<String> STATUS_IN_PROGRESS = Arrays.asList(
      MDOConstants.MDO_Stored.toLowerCase(), 
      MDOConstants.GCSS_SUBMITTED.toLowerCase(),
      MDOConstants.PENDING_TASKS.toLowerCase(), 
      MDOConstants.ISSUANCE_OK.toLowerCase()
);

if (MDOConstants.INPROGRESS.equalsIgnoreCase(status)){
    if(STATUS_IN_PROGRESS.contains(subStatus.toLowerCase()){
         return MDOConstants.INPROGRESS;
    }
}

答案 4 :(得分:0)

您可以尝试创建HashMap<Condition,String>

class Condition
{
    String status;
    String subStatus;

    public Condition(String s, String subS)
    {
        status = s;
        subStatus = subS;
    }

    public boolean equals(Condition c)
    {
         return c.status.equalsIgnoreCase(status)
                && c.subStatus.equalsIgnoreCase(subStatus);
    }
}

map.put(new Condition(MDOConstants.INPROGRESS, MDOConstants.DEADLINE_PASSED), MDOConstants.INPROGRESS);
//...
//...

map.get(new Condition(MDOConstants.INPROGRESS, MDOConstants.DEADLINE_PASSED)); // This will give you result.

当然,还有改进的余地,但你可能会得到一些暗示。