寻求有关结构代码以减少循环复杂度的说明 [英] Seeking clarifications about structuring code to reduce cyclomatic complexity

查看:82
本文介绍了寻求有关结构代码以减少循环复杂度的说明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近,我们公司开始每周对代码中功能的圈复杂度(CC)进行测量,并报告哪些功能已改进或恶化.因此,我们开始更加关注功能的CC.

我已经读过,CC可以非正式地计算为1 +函数中决策点的数量(例如if语句,for循环,select等),或者通过函数的路径数量...

我知道减少CC的最简单方法是重复使用Extract Method重构...

我不确定某些事情,例如以下代码片段的CC是什么?

1)

for (int i = 0; i < 3; i++)
    Console.WriteLine("Hello");

还有

Console.WriteLine("Hello");
Console.WriteLine("Hello");
Console.WriteLine("Hello");

它们都做相同的事情,但是由于for语句,第一个版本的CC是否更高?

2)

if (condition1)
    if (condition2)
        if (condition 3)
            Console.WriteLine("wibble");

还有

if (condition1 && condition2 && condition3)
    Console.WriteLine("wibble");

假设该语言可以进行短路评估,例如C#,那么这两个代码片段的效果相同...但是第一个片段的CC较高,因为它具有3个决策点/if语句?

3)

if (condition1)
{
    Console.WriteLine("one");

    if (condition2)
        Console.WriteLine("one and two");
}

还有

if (condition3)
    Console.WriteLine("fizz");

if (condition4)
    Console.WriteLine("buzz");

这两个代码片段执行不同的操作,但是它们具有相同的CC吗?还是第一个片段中的嵌套if语句具有更高的CC?也就是说,嵌套的if语句在心理上更难以理解,但这反映在CC中吗?

解决方案

  1. 是的.您的第一个示例具有决策点,而第二个示例没有决策点,因此第一个示例具有更高的CC.
  2. 是的,也许您的第一个示例具有多个决策点,因此CC更高. (有关说明,请参见下文.)
  3. 是的,也许是.显然,它们具有相同数量的决策点,但是计算CC的方式不同,这意味着...

...如果您的公司正在以特定方式测量CC,则您需要熟悉该方法(希望他们正在使用工具来执行此操作).对于不同的情况(case语句,布尔运算符等),有不同的计算CC的方法,但是无论使用哪种约定,都应从度量标准中获取相同类型的信息.

更大的问题是其他人提到的问题,即您的公司似乎更关注CC,而不是其背后的代码.一般而言,可以肯定的是,低于5表示很好,低于10表示好的,低于20表示可以,21到50应该是一个警告标志,高于50应该是一个大警告标志,但这只是参考,而不是绝对的规则.您可能应该在CC大于50的过程中检查代码,以确保它不仅是一大堆代码,但也许有特定的原因会以这种方式编写过程,而且这是不可行的(对于任何情况,原因的数量).

如果您使用工具重构代码以减少CC,请确保您了解这些工具在做什么,并且不要将一个问题简单地转移到另一个地方.最终,您希望代码几乎没有缺陷,可以正常工作,并且相对易于维护.如果该代码的CC也很低,则很适合.如果您的代码满足这些条件,并且CC大于10,也许该是时候与您可以管理的一切坐下来,保护您的代码了(也许让他们检查其策略).

Recently our company has started measuring the cyclomatic complexity (CC) of the functions in our code on a weekly basis, and reporting which functions have improved or worsened. So we have started paying a lot more attention to the CC of functions.

I've read that CC could be informally calculated as 1 + the number of decision points in a function (e.g. if statement, for loop, select etc), or also the number of paths through a function...

I understand that the easiest way of reducing CC is to use the Extract Method refactoring repeatedly...

There are somethings I am unsure about, e.g. what is the CC of the following code fragments?

1)

for (int i = 0; i < 3; i++)
    Console.WriteLine("Hello");

And

Console.WriteLine("Hello");
Console.WriteLine("Hello");
Console.WriteLine("Hello");

They both do the same thing, but does the first version have a higher CC because of the for statement?

2)

if (condition1)
    if (condition2)
        if (condition 3)
            Console.WriteLine("wibble");

And

if (condition1 && condition2 && condition3)
    Console.WriteLine("wibble");

Assuming the language does short-circuit evaluation, such as C#, then these two code fragments have the same effect... but is the CC of the first fragment higher because it has 3 decision points/if statements?

3)

if (condition1)
{
    Console.WriteLine("one");

    if (condition2)
        Console.WriteLine("one and two");
}

And

if (condition3)
    Console.WriteLine("fizz");

if (condition4)
    Console.WriteLine("buzz");

These two code fragments do different things, but do they have the same CC? Or does the nested if statement in the first fragment have a higher CC? i.e. nested if statements are mentally more complex to understand, but is that reflected in the CC?

解决方案

  1. Yes. Your first example has a decision point and your second does not, so the first has a higher CC.
  2. Yes-maybe, your first example has multiple decision points and thus a higher CC. (See below for explanation.)
  3. Yes-maybe. Obviously they have the same number of decision points, but there are different ways to calculate CC, which means ...

... if your company is measuring CC in a specific way, then you need to become familiar with that method (hopefully they are using tools to do this). There are different ways to calculate CC for different situations (case statements, Boolean operators, etc.), but you should get the same kind of information from the metric no matter what convention you use.

The bigger problem is what others have mentioned, that your company seems to be focusing more on CC than on the code behind it. In general, sure, below 5 is great, below 10 is good, below 20 is okay, 21 to 50 should be a warning sign, and above 50 should be a big warning sign, but those are guides, not absolute rules. You should probably examine the code in a procedure that has a CC above 50 to ensure it isn't just a huge heap of code, but maybe there is a specific reason why the procedure is written that way, and it's not feasible (for any number of reasons) to refactor it.

If you use tools to refactor your code to reduce CC, make sure you understand what the tools are doing, and that they're not simply shifting one problem to another place. Ultimately, you want your code to have few defects, to work properly, and to be relatively easy to maintain. If that code also has a low CC, good for it. If your code meets these criteria and has a CC above 10, maybe it's time to sit down with whatever management you can and defend your code (and perhaps get them to examine their policy).

这篇关于寻求有关结构代码以减少循环复杂度的说明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆