【问题标题】:Cyclomatic complexity of logically similar code逻辑相似代码的圈复杂度
【发布时间】:2013-03-18 14:34:22
【问题描述】:

考虑以下三个函数,它们都以相同的方式运行,使用不同的代码来实现相同的事情(示例是用 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 在这种情况下显然是错误的)?上述三个函数是否应该具有相同的圈复杂度?

【问题讨论】:

  • 仅供参考,JSHint 现在报告所有这三个函数的复杂度为 4。

标签: javascript cyclomatic-complexity


【解决方案1】:

圈复杂度是通过代码的线性独立路径的数量。虽然失败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。

【讨论】:

  • +1,谢谢,我同意这一点——所有三个函数的复杂度都应该是 4。JSHint 中肯定需要一些错误修复。不过,在接受这个答案之前,我会稍等片刻,如果有其他意见,我会鼓励进一步的回答!
猜你喜欢
  • 1970-01-01
  • 2011-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-14
  • 1970-01-01
相关资源
最近更新 更多