降低开关声明的环形复杂性 - 声纳

时间:2016-11-15 10:43:38

标签: java switch-statement sonarqube cyclomatic-complexity

我希望减少交换机案例的圈复杂度 我的代码是:

public String getCalenderName() {
        switch (type) {
    case COUNTRY:
        return country == null ? name : country.getName() + HOLIDAY_CALENDAR;
    case CCP:
        return ccp == null ? name : ccp.getName() + " CCP" + HOLIDAY_CALENDAR;
    case EXCHANGE:
        return exchange == null ? name : exchange.getName() + HOLIDAY_CALENDAR;
    case TENANT:
        return tenant == null ? name : tenant.getName() + HOLIDAY_CALENDAR;
    default:
        return name;
    }
}

此代码块的复杂度为16,并希望将其减少到10。 country,ccp,exchange和tenant是我不同的对象。根据类型,我将调用各自的方法。

8 个答案:

答案 0 :(得分:2)

我认为这是Sonar警告。我认为Sonar警告不是必须遵守的规则,而只是指南。您的代码块原样为READABLEMAINTAINABLE。它已经很简单,但是如果你真的想要改变它,你可以尝试下面的两种方法,看看复杂性是否会降低:

注意:我现在没有编译器,所以可能会有错误,提前抱歉。

第一种方法:

Map<String, String> multipliers = new HashMap<String, Float>();
    map.put("country", country);
    map.put("exchange", exchange);
    map.put("ccp", ccp);
    map.put("tenant", tenant);

然后我们可以使用地图来抓取正确的元素

    return map.get(type) == null ? name : map.get(type).getName() + HOLIDAY_CALENDAR;

第二种方法:

您的所有对象都使用相同的方法,因此您可以在其中添加Interface getName()方法并更改方法签名,如:

getCalendarName(YourInterface yourObject){
    return yourObject == null ? name : yourObject.getName() + HOLIDAY_CALENDAR;
}

答案 1 :(得分:1)

据我所知,不要在switch语句中使用return语句。使用变量在switch语句之后应用该逻辑。 创建一个检查null值的方法并从switch调用该方法,然后就可以减少Cyclomatic Complexity

答案 2 :(得分:0)

您可以删除所有空比较并在切换案例之前进行检查。在这种情况下,复杂性将减少4或更多。

答案 3 :(得分:0)

如果您的对象:country,cpp,exchange和tenant共享相同的界面,例如ObjectWithGetName你可以重构你的代码如下:

  public String getCalenderName() {
    ObjectWithGetNameMethod calendarType = null;
    switch (type) {
        case COUNTRY:
           calendarType = country;
           break;
        case CCP:
           calendarType = cpp;
           break;
        case EXCHANGE:
           calendarType = exchange;
           break;
        case TENANT:
           calendarType = tenant;
           break;
        default:
           calendarType = null;
    }
    return (calendarType != null ? (calendarType.getName() + HOLIDAY_CALENDAR) : name);
  }

另外我认为将切换移到单独的方法会很好,因为它看起来像是会在很多不同的地方使用。

答案 4 :(得分:0)

如果您的第一个目标只是降低圈复杂度,则应为每种获取名称的方法创建方法,如下所示。

 public String getCalenderName() {
    switch (type) {
    case COUNTRY:
        return getCountryName();
    case CCP:
        return getCcpName();
    case EXCHANGE:
        return getExchangeName();
    case TENANT:
        return getTenantName();
    default:
        return name;
    }
}

private String getCountryName() {
    return country == null ? name : country.getName() + HOLIDAY_CALENDAR;
}

private String getCcpName() {
    return ccp == null ? name : ccp.getName() + " CCP" + HOLIDAY_CALENDAR;
}

private String getExchangeName() {
    return exchange == null ? name : getName.toString() + HOLIDAY_CALENDAR;
}

private String getTenantName() {
    return tenant == null ? name : getName.toString() + HOLIDAY_CALENDAR;
}

请注意,在您的具体示例中,我认为您有一个类(至少)收集了4个非常相似的行为。重构肯定会更有意义,例如有一个基本实现(抽象或非抽象),以及其他4个继承类。

答案 5 :(得分:0)

我认为您可以通过确保代码中的其他内容固定来降低复杂度。

以案件为例:

case COUNTRY:
  return country == null ? name : country.getName() + HOLIDAY_CALENDAR;

这意味着如果日历类型为COUNTRY,则日历所关联的国家可以为null。这是您应设计避免的事情,因为我看不出为什么这可能是有效的情况。为什么您会在没有国家的情况下拥有国家日历?

因此,一旦为日历分配了type,请确保没有与日历关联的非空对象。这样,您的情况将像

case COUNTRY:
  return country.getName() + HOLIDAY_CALENDAR;

将循环复杂度降低到5。

答案 6 :(得分:0)

您可以用Dictionary>替换switch / case语句。

看看this blogpostthis one

的最后一个示例

答案 7 :(得分:-1)

public String getName() {
    if (type == null) {
        return name;
    }
    if (type == BusinessCalendarType.COUNTRY) {
        return country == null ? name : country.getName() + HOLIDAY_CALENDAR;
    } else if (type == BusinessCalendarType.CCP) {
        return ccp == null ? name : ccp.getName() + " CCP" + HOLIDAY_CALENDAR;
    } else if (type == BusinessCalendarType.EXCHANGE) {
        return exchange == null ? name : exchange.getName() + HOLIDAY_CALENDAR;
    } else if (type == BusinessCalendarType.TENANT)  {
        return tenant == null ? name : tenant.getName() + HOLIDAY_CALENDAR;
    } else {
        return name;
    }
}

这对我有用