Consider the following three functions, which all behave in an identical manner, using different code to achieve the same thing (examples are written in JavaScript, and I'm particularly interested in answers as applied to JavaScript, but this question could really apply to any language with similar constructs):
// 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());
The JSComplexity tool reports all three functions to have a complexity of 4, which means the ||
operators are treated as independant branches, as are fall-through case
statements. JSHint doesn't seem to care about the ||
operator, but it does handle fall-through case
statements in the same way. It seems to get the conditional operator completely wrong.
When calculating cyclomatic complexity, should fall-through case
statements and logical "or" operators be treated as independent branches? What about ternary conditionals (I believe this is simpler, and JSHint is clearly wrong in this case)? Should all three functions above have the same cyclomatic complexity?