为什么这个功能12的圆柱复杂性?

时间:2015-04-23 20:38:59

标签: c# complexity-theory cyclomatic-complexity

我有一个(C#)函数,它检查四组条件并返回一个bool。如果其中任何一个为真,则返回true。我确信我可以简化逻辑,但我希望它具有相当的可读性。

Visual Studio中的CodeMaid扩展并告诉我该函数的cylomatic复杂度为12. I looked it up并且cylomatic复杂度为

  

通过源代码的独立路径数

我不明白为什么会这样。我可以用两种方式来考虑它,或者说圈复杂度应该是2,因为它总是经过相同的路径但是可以返回{{1或true。或者可以理解它是否是16,因为最后四个布尔值false一起可以是真或假,2 * 2 * 2 * 2 = 16。

有人可以告诉我为什么它的12?甚至可能会显示一个图表,以便我可以看到不同的路径?

or

提前致谢。

修改

我把它改成了这个。为复选框条件分配局部变量并没有任何效果,但是从" YES" /" NO"中创建布尔值。把复杂性提高到14,我想我明白了。

public bool FitsCheckBoxCriteria(TaskClass tasks)
{
    // note: bool == true/false comparisons mean you don't have to cast 'bool?' as bool


    // if neither checkboxes are checked, show everything
    bool showEverything = NoShutDownRequiredCheckBox.IsChecked == false &&
                          ActiveRequiredCheckBox.IsChecked == false; 

    // if both are checked, only show active non-shutdown tasks
    bool showActiveNonShutdown = ActiveRequiredCheckBox.IsChecked == true &&
                                 tasks.Active == "YES" &&
                                 NoShutDownRequiredCheckBox.IsChecked == true &&
                                 tasks.ShutdownRequired == "NO";

    // if active is checked but shudown isn't, display all active
    bool showActive = ActiveRequiredCheckBox.IsChecked == true &&
                      tasks.Active == "YES" &&
                      NoShutDownRequiredCheckBox.IsChecked == false;

    // if non-shutdown is checked but active isn't, display all non-shutdown tasks
    bool showNonShutdown = NoShutDownRequiredCheckBox.IsChecked == true &&
                           tasks.ShutdownRequired == "NO" &&
                           ActiveRequiredCheckBox.IsChecked == false;

    return showEverything || showActiveNonShutdown || showActive || showNonShutdown;
}

3 个答案:

答案 0 :(得分:3)

这只是一个猜测,但我认为分配是每个+2(if = true / else = false),然后在return语句中为每个可能的退出条件+1。所以它可能会放松到像:

bool showEverything = false;
if (...) { showEverything = true; } +1
else { showEverything = false; } +1

bool showActiveNonShutdown = ... +2 if/else
bool showActive = ... +2 if/else
bool showNonShutdown = ... +2 if/else

if (showEverything) {...} +1
else if (showActiveNonShutdown) {...} +1
else if (showActive) {...} +1
else if (showNonShutdown) {...} +1
else {false}

答案 1 :(得分:3)

关键在于“独立路径”。

我将重写你的代码以缩短它,以便我们讨论它。

public bool FitsCheckBoxCriteria(TaskClass tasks)
{
    bool E1 = A1 && A2; 

    bool E2 = B1 && B2 && B3 && B4;

    bool E3 = C1 && C2 && C3;

    bool E4 = D1 && D2 && D3;

    return E1 || E2 || E3 || E4;
}

Cyclomatic复杂性是独立路径的数量。这不是返回值的总可能数量(2)。

&&运算符和||操作员是短路操作;如果A1为假,则不评估 A2 。同样,如果E1为真,则不评估E2。

如果用&替换所有&& s;和所有|| s |在上面的代码中,圈复杂度为1,因为代码中只有一条路径。 (虽然这不会使代码变得更好)。

实际上,有72条可能的路径......

  1. 评估A1,B1,C1,D1,E1 ;其他人则没有。
  2. A1, A2 ,B1,C1,D1,E1被评估;其他人则没有。
  3. A1,B1, B2 ,C1,D1,E1被评估;其他人则没有。
  4. 评估A1,A2,B1,B2,C1,D1,E1;其他人不是。 等......
  5. 但路径4不包含任何尚未在先前路径上的新代码。这就是“独立路径”的定义 - 每条路径都必须包含新代码。

    因此,在此示例中,您可以手动计算代码,如下所示:

    1 +此代码中的短路运算符数(11)= 12.

    {{3}}

答案 2 :(得分:2)

C#使用短路评估,这意味着如果有x && y表达式y仅在必要时进行评估,更准确地说,如果x为真。这意味着result = x && y;有两个独立的执行路径:(1)如果x为false,则仅评估x并且result获取false值(不评估y })但是(2)如果x为真,则y也会被评估,而result会得到y的评估结果。这意味着每个&&||运算符都会增加圈复杂度,在第一个示例中,有8&&&和3 ||运算符因此该方法的圈复杂度为12。