简体   繁体   English

降低 Switch 语句的圈复杂度 - Sonar

[英]Reduce Cyclomatic Complexity of Switch Statement - Sonar

I want to reduce cyclomatic complexity of my switch case my code is :我想降低我的开关盒的圈复杂度,我的代码是:

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;
    }
}

This code blocks complexity is 16 and want to reduce it to 10. country, ccp, exchange and tenant are my diffrent objects.这段代码块的复杂度是 16,想把它减少到 10。国家、中央控制点、交换和租户是我的不同对象。 Based on type I will call their respective method.根据类型,我将调用它们各自的方法。

I believe it is a Sonar warning.我相信这是一个Sonar警告。 I think Sonar warnings are not must-do-rules, but just guides.我认为Sonar警告不是必须做的规则,而只是指南。 Your code block is READABLE and MAINTAINABLE as it is.您的代码块是READABLE和可MAINTAINABLE It is already simple, but if you really want to change it you can try those two approaches below, and see if complexity becomes lower:已经很简单了,但是如果你真的想改变它,你可以试试下面这两种方法,看看复杂度是否变低了:

Note: I don't have compiler with me now so there can be errors, sorry about that in advance.注意:我现在没有编译器,所以可能会出现错误,提前抱歉。

First approach:第一种方法:

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

Then we can just use the map to grab the right element然后我们可以使用地图来抓取正确的元素

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

2nd approach:方法二:

All your objects have same method, so you can add an Interface with getName() method in it and change your method signature like:您所有的对象都具有相同的方法,因此您可以在其中添加一个带有getName()方法的Interface并更改您的方法签名,例如:

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

If your first aim is only to reduce the cyclomatic complexity, you should create methods for each way of getting the name, like following.如果您的首要目标只是降低圈复杂度,您应该为每种获取名称的方式创建方法,如下所示。

 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;
}

Note in your specific example, I suppose that you have 1 class that gather (at least) 4 quite similar behaviours.请注意,在您的具体示例中,我假设您有 1 个类收集(至少)4 个非常相似的行为。 A refactoring would certainly make more sense, in order to have for example one base implementation (abstract or not), and 4 other inherited classes.重构肯定会更有意义,例如为了拥有一个基本实现(无论是否抽象)和 4 个其他继承类。

As per my knowledge, do not use return statement in switch statement.据我所知,不要在 switch 语句中使用 return 语句。 Apply that logic after the switch statement using a variable.使用变量在 switch 语句之后应用该逻辑。 Create a method for checking the null value and call that method from switch then you will able to reduce the Cyclomatic Complexity创建一个用于检查空值的方法并从 switch 调用该方法,然后您将能够降低圈复杂度

I think you can lower the complexity just by making sure that something else is fixed in your code.我认为您可以通过确保在您的代码中修复其他内容来降低复杂性。

Take the case:看案例:

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

This implies that if the calender type is COUNTRY , the country the calender is associated with could be null .这意味着如果日历类型为COUNTRY ,则与日历关联的国家/地区可能为null This is something you should prevent by design because I can't see a reason why this could be a valid situation.这是您应该通过设计防止的事情,因为我看不出这可能是有效情况的原因。 Why would you have a country calender without a country?为什么你会有一个没有国家的国家日历?

So make sure that there is a non-null object associated with the calender as soon as you assign a type to it.因此,一旦为它分配type ,请确保有一个与日历关联的非空对象。 In this way your cases will be like这样你的情况就会像

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

which lowers your cyclomatic complexity to 5.这将您的圈复杂度降低到 5。

You can remove all the null comparisons and check it prior to switch case.您可以删除所有空比较并在 switch case 之前检查它。 In that case complexity will reduce by 4 or may be more.在这种情况下,复杂性将减少 4 或更多。

If your objects: country, cpp, exchange and tenant share the same interface eg ObjectWithGetName you could refactor your code as following:如果您的对象:国家、cpp、交换和租户共享相同的接口,例如 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);
  }

Also I think it will be nice to move switch to separate method since it looks like something witch will be used in many different places.另外我认为将 switch 移动到单独的方法会很好,因为它看起来像女巫会在许多不同的地方使用。

You can replace a switch/case statement with Dictionary>. 您可以使用Dictionary>替换switch / case语句。

Take a look at the last example of this blogpost or this one 看看这篇博文的最后一个例子或者这个 博文

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;
    }
}

this worked for me这对我有用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM