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

Cha*_*ton 5 c# complexity-theory cyclomatic-complexity

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

Visual Studios中的CodeMaid扩展并告诉我该函数的cylomatic复杂性为12.我查了一下,并且cylomatic复杂性是

通过源代码的独立路径的数量

我不明白为什么它是12.我可以用两种方式来考虑它,要么圈复杂度应该是2,因为它总是通过相同的路径但是可以返回a true或a false.或者可以理解它是否是16,因为最后四个布尔or在一起可能都是真或假,2*2*2*2 = 16.

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

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;
}
Run Code Online (Sandbox Code Playgroud)

提前致谢.

编辑:

我把它改成了这个.为复选框条件分配局部变量没有任何效果,但是从"是"/"否"创建布尔值会使复杂度增加到14,我想我理解.

public bool FitsCheckBoxCriteria(LubeTask tasks)
{
    bool noShutdownReqChecked = (bool)NoShutDownRequiredCheckBox.IsChecked;
    bool activeChecked = (bool)ActiveRequiredCheckBox.IsChecked;

    bool active = tasks.Active == "YES" ? true : false;
    bool shutdownReq = tasks.ShutdownRequired == "YES" ? true : false;

    // if neither checkboxes are checked, show everything
    bool showEverything = !noShutdownReqChecked && !activeChecked;

    // if both are checked, only show activeChecked non-shutdown tasks
    bool showActiveNonShutdown = activeChecked && noShutdownReqChecked && active && !shutdownReq;

    // if activeChecked is checked but shudown isn't, display all activeChecked
    bool showActive = activeChecked && !noShutdownReqChecked && active;

    // if non-shutdown is chceked but activeChecked isn't, display all non-shutdown tasks
    bool showNonShutdown = noShutdownReqChecked && !activeChecked && !shutdownReq;

    return showEverything || showActiveNonShutdown || showActive || showNonShutdown;
}
Run Code Online (Sandbox Code Playgroud)

per*_*ist 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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

如果将所有 && 替换为 &,并将所有 || 替换为 | 在上面的代码中,圈复杂度为 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;其他人则不然。ETC...

但路径 4 不包含先前路径中未包含的任何新代码。这就是“独立路径”的定义——每条路径都必须包含新的代码。

所以在这个例子中,你可以手动统计代码如下:

1 + 该代码中短路运算符的数量 (11) = 12。

维基百科有一个非常深入的解释。