2013-03-18 90 views
3

考虑以下三个函数,它们的行为都是相同的,使用不同的代码实现相同的事情(例子用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

仅供参考,JSHint现在报告所有这三个功能有4. – JLRishe 2017-11-03 20:06:08

回答

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

+0

+1复杂,谢谢,我同意这一点 - 所有这三个函数应该具有相同的复杂度4.在JSHint中肯定有一些错误修复需要。在接受这个答案之前,我会稍微等一下,如果有其他意见,鼓励进一步的答案! – 2013-03-18 15:25:48