考虑以下三个函数,它们都以相同的方式运行,使用不同的代码来实现相同的事情(示例是用JavaScript编写的,我对应用于JavaScript的答案特别感兴趣,但这个问题可能真的适用于具有类似结构的任何语言):
// Random number from 0-9
var x = Math.floor(Math.random() * 10);
// JSHint reports a cyclomatic complexity of 3
function a() {
if (x === 0) {
return "First";
} else if (x === 1 || x === 2) {
return "Second";
}
return "Third";
}
// JSHint reports a cyclomatic complexity of 4
function b() {
switch (x) {
case 0:
return "First";
case 1:
case 2:
return "Second";
default:
return "Third";
}
}
// JSHint reports a cyclomatic complexity of 1
function c() {
return x === 0 ? "First" : x === 1 || x === 2 ? "Second" : "Third";
}
// All three functions return the same value
console.log(a(), b(), c());
JSComplexity工具报告所有三个函数的复杂度均为4,这意味着||
运算符被视为独立分支,并且是直接case
语句。 JSHint似乎并不关心||
运算符,但它确实以相同的方式处理直接case
语句。它似乎让条件运算符完全错误。
在计算圈复杂度时,应将直通case
语句和逻辑“或”运算符视为独立分支?三元条件怎么样(我相信这更简单,在这种情况下JSHint显然是错误的)?上述所有三个函数是否应具有相同的圈复杂度?
答案 0 :(得分:7)
圈复杂度是通过代码的线性独立路径的数量。虽然坠落case
是空洞的,但我相信这是一条不同的道路。所以问题是||
是否引入了新的分支?
我只是在这里大声思考,但我认为因为JavaScript对条件执行短路评估,我们确实从分离中获得了两个分支。例如,您的a
函数等同于:
function a() {
if (x === 0) {
return "First";
} else if (x === 1) {
return "Second";
} else if (x === 2) {
return "Second";
} else {
return "Third";
}
}
...有4个分支,即使其中两个执行相同的功能。 (即边缘上的线性独立性,而不是顶点。)但是,如果JS没有进行短路评估,我倾向于考虑x === 1 || x === 2
只调用一个分支。
所以,为了回答你的问题,我认为你的所有三个函数应该具有相同的圈复杂性:4。