1

以下方法的 CC 将生成为 9

    Public Enum Fruits
        Apple
        Pineapple
        Banana
        PassionFruit
        Orange
        Melon
        Grape
        Mango
    End Enum


  Private Function Fruity(ByVal fruitType As Fruits)

        Select Case fruitType
            Case Fruits.Orange, Fruits.Banana
            Case Fruits.Melon
            Case Fruits.Mango
            Case Fruits.Pineapple
            Case Fruits.Passionfruit
            Case Fruits.Melon, Fruits.Apple
        End Select
    End Function

但是当用户定义枚举成员值时,Fruity 方法的 CC 增加到 14。

 Public Enum Fruits
        Apple = 1
        Pineapple = 3
        Banana = 4
        Passionfruit = 5
        Orange = 7
        Melon = 9
        Grape = 11
        Mango = 13
    End Enum

现在假设我将 select-case 语句更改如下,然后方法 Fruity 的 CC 更改为 7,但与上述 select-case 相比,可维护性指数略有下降。

 Select Case true
       Case fruitType= Fruits.Orange or fruitType= Fruits.Banana
       Case fruitType=Fruits.Melon
       Case fruitType=Fruits.Mango
       Case fruitType=Fruits.Pineapple
       Case fruitType=Fruits.Passionfruit
       Case fruitType=Fruits.Melon, Fruits.Apple
  End Select

在最后一个场景中,我将参数的数据类型更改为整数并访问一个名为蔬菜的不同枚举,其值为 50。现在,Fruity 方法的 CC 飙升至 52。但如果我将 Potato 的值更改为 0 或 1然后CC保持在15。

  Public Enum Vegetables
   Potato = 50
  End Enum

  Private Function Fruity(ByVal fruitType As Integer)

        Select Case fruitType
            Case Fruits.Orange, Fruits.Banana
            Case Fruits.Melon
            Case Fruits.Mango
            Case Vegetables.Potato
            Case Fruits.Passionfruit
            Case Fruits.Melon, Fruits.Apple
        End Select
    End Function

这些都在 VS 2008 Team 系统版 3.5SP1 中进行了测试。我想知道为什么这4种情况下CC会有波动。

它与下面给出的第二点有关吗?因为如果我在第 4 种情况下删除掉线案例,CC 确实会下降到 9。那么这是 VS 2008 中的错误吗?

Visual Studio 2010 特别说明

使用不适用于 Visual Studio 2008 的 Visual Studio 2010 计算代码指标时可能存在差异。在线文档 ( http://msdn.microsoft.com/en-us/library/ee703787.aspx ) 给出了以下原因:

  1. 该函数包含一个或多个 catch 块。在 Visual Studio 的早期版本中,catch 块不包括在计算中。在 Visual Studio 2010 中,每个 catch 块的复杂性被添加到函数的复杂性中。

  2. 该函数包含一个 switch(VB 中的 Select Case)语句。Visual Studio 2010 和更早版本之间的编译器差异可能会为某些包含失败案例的 switch 语句生成不同的 MSIL 代码。

4

1 回答 1

2

圈复杂度计数是一个相当简单的功能,它只计算从代码生成的 IL 中出现的分支数。每个分支将计数增加 1。

您需要查看该 IL,从 Visual Studio 命令提示符运行ildasm.exe 实用程序。当您比较这些不同片段的 IL 时,就会立即明白为什么复杂性计数会如此变化。

  • 您的第一个版本会生成一个Opcodes.Switch,每个枚举都有一个条目。switch 表中的每个条目都对应一个 Case 语句,并将复杂度计数增加 1
  • 您的下一个版本增加了开关表的大小。它为缺少的枚举值添加条目。这不恰当地增加了复杂性计数,该工具不够聪明,无法识别虚拟条目并且不能轻易做到
  • 您的上一个版本在枚举值中有太多空白。编译器识别出 Opcodes.Switch 不再有效并生成完全不同的代码,现在使用一系列 If/ElseIf 测试。降低复杂性计数。

仅使用圈复杂度作为粗略的指导,它还不够复杂,不足以证明进行剧烈的代码更改是合理的。

于 2013-10-19T06:50:41.753 回答