java 降低 Switch 语句的圈复杂度 - Sonar
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/40607780/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Reduce Cyclomatic Complexity of Switch Statement - Sonar
提问by Amar Magar
I want to reduce cyclomatic complexity of my switch case my code is :
我想降低我的 switch case 的圈复杂度,我的代码是:
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. Based on type I will call their respective method.
这段代码块的复杂度是 16,想把它减少到 10。国家、中央控制点、交换和租户是我的不同对象。根据类型,我将调用它们各自的方法。
回答by halil
I believe it is a Sonar
warning. I think Sonar
warnings are not must-do-rules, but just guides. Your code block is READABLE
and MAINTAINABLE
as it is. 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:
我相信这是一个Sonar
警告。我认为Sonar
警告不是必须做的规则,而只是指南。您的代码块READABLE
,并MAINTAINABLE
因为它是。已经很简单了,但是如果你真的想改变它,你可以试试下面这两种方法,看看复杂度是否变低了:
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:
您所有的对象都具有相同的方法,因此您可以在其中添加一个Interface
withgetName()
方法并更改您的方法签名,例如:
getCalendarName(YourInterface yourObject){
return yourObject == null ? name : yourObject.getName() + HOLIDAY_CALENDAR;
}
回答by Loic M.
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. A refactoring would certainly make more sense, in order to have for example one base implementation (abstract or not), and 4 other inherited classes.
请注意,在您的具体示例中,我假设您有 1 个类收集(至少)4 个非常相似的行为。重构肯定会更有意义,例如为了拥有一个基本实现(无论是否抽象)和 4 个其他继承类。
回答by mayank agrawal
As per my knowledge, do not use return statement in switch statement. Apply that logic after the switch statement using a variable. Create a method for checking the null value and call that method from switch then you will able to reduce the Cyclomatic Complexity
据我所知,不要在 switch 语句中使用 return 语句。使用变量在 switch 语句之后应用该逻辑。创建一个用于检查空值的方法并从 switch 调用该方法,然后您将能够降低圈复杂度
回答by Paul Jansen
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
. 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?
这意味着,如果日历类型为COUNTRY
,则与日历相关联的国家/地区可能是null
。这是您应该通过设计防止的事情,因为我看不出这可能是有效情况的原因。为什么你会有一个没有国家的国家日历?
So make sure that there is a non-null object associated with the calender as soon as you assign a type
to it. In this way your cases will be like
因此,一旦您将 a 分配type
给它,请确保有一个与日历关联的非空对象。这样你的情况就会像
case COUNTRY:
return country.getName() + HOLIDAY_CALENDAR;
which lowers your cyclomatic complexity to 5.
这将您的圈复杂度降低到 5。
回答by Ammar Hasan
You can replace a switch/case statement with Dictionary>.
您可以用 Dictionary> 替换 switch/case 语句。
Take a look at the last example of this blogpostor this one
回答by sandeshch
You can remove all the null comparisons and check it prior to switch case. In that case complexity will reduce by 4 or may be more.
您可以删除所有空比较并在 switch case 之前检查它。在这种情况下,复杂性将减少 4 或更多。
回答by Luk
If your objects: country, cpp, exchange and tenant share the same interface e.g. 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 移动到单独的方法会很好,因为它看起来像女巫会在许多不同的地方使用。
回答by Amar Magar
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
这对我有用