假设我有下面的原始方法。
public String someMethod(String str) {
String returnStr;
if("BLAH".equals(str)) {
returnStr="ok";
} else if ("BLING".equals(str)) {
returnStr="not ok";
} else if ("BONG".equals(str)) {
returnStr="ok";
}
return returnStr;
}
转换为以下真的能降低CC吗?
Map<String, String> validator = new HashMap<String,String>();
validator.put("BLAH","ok");
validator.put("BLING","not ok");
validator.put("BONG","ok");
public String someMethod(String str) {
return validator.get(str);
}
是的,在您的情况下。简单地说,圈复杂度是从起点到达代码段末尾的许多线性独立方式。因此,任何条件运算符都会增加代码的CC。
(如果OP的问题在某种程度上与testing
标签有关(然而,减少CC并不能减少单元测试的数量,因为必须编写单元测试才能覆盖您的代码:CC只给您测试数量的下限。为了获得良好的覆盖率,单元测试应该覆盖所有特定的情况,在第二种情况下,您不减少特定情况的数量,只会使代码更可读。
是的,因为圈复杂度定义了控制流图中线性独立路径的数量加一。在第二个示例中,只有一个路径,第一个路径有多个通过if
分支的路径。然而,在这里,圈复杂性似乎并不是一个真正的问题。你可以这样替换你的方法,使其可读性更好:
public String someMethod(String str) {
switch(str) {
case "BLAH":
case "BONG": return "ok";
case "BLING": return "not ok";
default: return null;
}
}
简单回答:是的,在您的案例中使用Hashmap确实降低了Cyclomatic复杂性。
详细答案:根据维基百科的循环复杂度是
它是对程序源代码中线性独立路径数量的定量度量。
有多种方法可以处理其他情况。If-else语句使代码可读性降低,难以理解。这些if-else也很糟糕,因为每次在这些情况下进行添加/删除/修改时,您都需要修改现有的代码文件,而其他业务逻辑保持不变,并且由于这些文件的更改,您需要重新测试它们。这导致了维护问题,以及我们需要确保处理这些案例的所有地方。switch语句也存在同样的问题,尽管它们的可读性稍高。
您使用的方法还减少了执行的不同逻辑路径。另一种替代方法如下。
您可以创建一个接口,比如IPair
。让这个接口定义一个抽象方法public String getValue();
让我们为每种情况定义不同的类,让BlahMatch.java, Bling.java and Bong.java
实现IPair
,在getValue()
方法的实现中返回适当的String
。
public String someMethod(IPair pair) {
return pair.getValue();
}
上述方法的优点是,如果以后有新的对,您仍然可以创建一个新的类并轻松地传递新类的对象,只需要让您的类提供IPair
的实现。