使用地图真的能降低圈复杂度吗



假设我有下面的原始方法。

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的实现。

最新更新