如何降低此 c# 方法的圈复杂度?

问题描述

我目前正在为我的 c# 类做一个项目。我们的老师给了我们一些我们必须遵守的代码度量限制,其中之一是圈复杂度。现在他下面方法的复杂度是5,但它必须是4。有什么办法可以改进吗?

我正在谈论的方法

private bool MethodName()
    {
        int counter = 0;

        for (int k = 0; k < 8; k++)
        {
            for (int j = 0; j < 3; j++)
            {
                if (class1.GetBoard()[array1[k,j,0],array1[k,1]] == player.WhichPlayer()) counter++;
            }

            if (counter == 3) return true;
            else counter = 0;
        }
        return false;
    }

解决方法

我可以包装条件以减少它。例如

private bool MethodName()
    {
        for (int k = 0; k < 8; k++)
        {
            bool b = true;
            for (int j = 0; j < 3; j++)
            {
                b &= class1.GetBoard()[array1[k,j,0],array1[k,1]] == player.WhichPlayer();
            }

            if (b) return true;
        }
        return false;
    }
,

对于 OP(似乎刚刚开始编程):

很高兴你得到了一个降低方法圈复杂度的任务,知道它是什么以及如何将它保持在低水平作为一般做法是很好的。

但是,尽量不要对这些指标过于狂热。让代码尽可能简单更有价值,易于推理和快速理解,并且在分析应用程序并了解最重要的位置后才担心指标。

对于更有经验的编码人员:

这个简单的问题让我想起了 1968 年 very famous discussion 和 ACM 周期中的其他人之间的Dijkstra。虽然我倾向于在这件事上与他保持一致,但这是一个非常合理的answer from Frank Rubin

弗兰克基本上主张“优雅”可以多次来自代码清晰度,而不是任何其他实践指标。当时的讨论是关于当时流行的语言过度使用 goto 语句。今天,讨论围绕圈复杂度、简洁性、oop 或其他内容展开。

我认为最重要的是:

  • 了解您的工具
  • 代码清晰
  • 尝试在第一次通过时编写高效的代码,但不要想太多
  • 分析您的代码并决定在何处花费更多时间

回到问题

问题中提出的实现在我的 Visual Studio Analyzer 中获得了以下分数:

循环。复合:5;可维护性:67

@Boris 提供的片段得到了这个:

循环。复合:4;可维护性:68

虽然圈复杂度有所提升,但可维护性指标基本保持不变。就我个人而言,我认为大多数情况下后一个指标更有价值。

只是为了好玩,让我们看看类似于 Frank Rubin 提出的使用可怕的 goto 语句的解决方案是什么样的:

private bool MethodName() {
  for (int k = 0; k < 8; k++) {
    for (int j = 0; j < 3; j++) {
      if (watheverTestCondition(k,j) is false) goto reject;
    }
    // condition is true for all items in this row
    return true; 
    // if condition is false for any item,go straight to this line
    reject:;
  }
  return false;
}

老实说,我认为这是最清晰、最简单和最高效的实现。我一般推荐 goto 作为代码功能吗? 。在这种特定情况下,它是否完美而顺利? 是的。那么指标呢?

循环。复合:4;可维护性:70


奖金

仅仅因为如果我不说我就睡不着,这就是你在现实生活中如何实现这一点

obj.Any(row => row.All(watheverTestCondition));

循环。复合:1;可维护性:80