首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C#代码的完整表达式列表,其中+1表示圈复杂度

C#代码的完整表达式列表,其中+1表示圈复杂度
EN

Stack Overflow用户
提问于 2011-12-05 00:05:06
回答 1查看 530关注 0票数 3

我需要为我的C#项目中的每一种方法构造一个控制流图(带有节点和边的简单流图),以演示计算圈复杂度的图形方法。

我首先使用VS 2010计算圈复杂度,然后构造图以确保结果值与从VS计算出来的值相同。但是,我在这里遇到了一些问题,因为我不确定哪个表达式实际上是考虑圈复杂度的+1。

让我们看一下这里的一个例子:

代码语言:javascript
复制
 public ActionResult Edit(string id, string value)
    {
        string elementId = id;
        // Use to get first 4 characters of the id to indicate which category the element belongs
        string fieldToEdit = elementId.Substring(0, 4);

        // Take everything AFTER the 1st 4 characters, this will be the ID
        int idToEdit = Convert.ToInt32(elementId.Remove(0, 4));

        // The value to be return is simply a string:
        string newValue = value;

        var food = dbEntities.FOODs.Single(i => i.FoodID == idToEdit);

        // Use switch to perform different action according to different field
        switch (fieldToEdit)
        {
            case "name": food.FoodName = newValue; break;
            case "amnt": food.FoodAmount = Convert.ToInt32(newValue); break;
            case "unit": food.FoodUnitID = Convert.ToInt32(newValue); break;
            // ** DateTime format need to be modified in both view and plugin script
            case "sdat": food.StorageDate = Convert.ToDateTime(newValue); break;
            case "edat": food.ExpiryDate = Convert.ToDateTime(newValue); break;
            case "type": food.FoodTypeID = Convert.ToInt32(newValue); break;

            default: throw new Exception("invalid fieldToEdit passed");

        }
        dbEntities.SaveChanges();
        return Content(newValue);
    }

对于这种方法,VS计算了圈复杂度为10。然而,只有7种情况说明,我不明白还有什么其他的表达式对复杂性有影响。

我搜索了许多源,但无法获得所有表达式的完整列表,这些表达式将被计算在内。

有人能帮上忙吗?或者有什么工具可以从C#代码中生成控制流图?

谢谢你提前..。

EN

回答 1

Stack Overflow用户

发布于 2012-01-18 16:32:07

您首先应该做的是尝试使用图表来可视化圈复杂度。在阅读代码时,我设法计算了10。为了更好地理解这一点,请看以下内容:

代码语言:javascript
复制
public void MyMethod()
{
    Console.WriteLine("Hello ShennyL");
}

它的圈复杂度为1,因为这里只有一条可能的路径,即显示消息。

代码语言:javascript
复制
public void AnotherMethod()
{
    if (someCondition)
    {
        Console.WriteLine("Hello Shennly");
    }
}

这一次,我们的圈复杂度为2. +1被添加到if,而,for,foreach。在这种情况下,有两条路径。如果someCondition为真,则将显示消息(第一个可能的路径),如果someCondition为false,则不会显示消息(第二个可能的路径)。

如果您查看Windows窗体中Dispose的实现,它如下所示:

代码语言:javascript
复制
protected override void Dispose(bool disposing)
{
    if (disposing && (components != null))
    {
        components.Dispose();
    }
    base.Dispose(disposing);
}

在这里,圈复杂度为3。在&&的情况下,这两个值必须是真的,这样才能计算里面的表达式。这意味着,如果 disposing都是true,那么 (components != null)都是真,那么您就有了第一条路径。如果disposing为false,则有第二条路径。第三条路径来自于这样一个事实,即components可以为null,因此它将计算为false。因此,你的圈复杂度为3。

switch的情况下,您得到+1,对于出现在其中的每个case (和default),您将得到+1。对于您的方法,您有6个case语句和一个default + switch,使这8个总计。

正如我在一开始所说的,如果您尝试用图形来可视化代码,它可以像这样分解(我正在将我的注释添加到您的代码中,并删除您的注释):

代码语言:javascript
复制
public ActionResult Edit(string id, string value)                   
{                   
    string elementId = id; // First path, cyclomatic complexity is 1

    string fieldToEdit = elementId.Substring(0, 4); // Same path, CC still 1  

    int idToEdit = Convert.ToInt32(elementId.Remove(0, 4)); // Same path, CC still 1

    string newValue = value; // Same path, CC still 1

    var food = dbEntities.FOODs.Single(i => i.FoodID == idToEdit); // Boolean expression inside your lambda. The result can go either way, so CC is 2.

    switch (fieldToEdit) // Switch found, so CC is 3
    {                   
        case "name": food.FoodName = newValue; break; // First case - CC is 4
        case "amnt": food.FoodAmount = Convert.ToInt32(newValue); break; // Second case - CC is 5
        case "unit": food.FoodUnitID = Convert.ToInt32(newValue); break; // Third case - CC is 6
        case "sdat": food.StorageDate = Convert.ToDateTime(newValue); break; // Fourth case - CC is 7
        case "edat": food.ExpiryDate = Convert.ToDateTime(newValue); break; // Fifth case - CC is 8
        case "type": food.FoodTypeID = Convert.ToInt32(newValue); break; // Sixth case - CC is 9

        default: throw new Exception("invalid fieldToEdit passed"); // Defaul found - CC is 10

    }                   
    dbEntities.SaveChanges(); // This belongs to the first path, so CC is not incremented here.                   
    return Content(newValue);                   
}        

我在几点上可能是错的,但基本上这就是计算圈复杂度的想法。您还应该理解,在某些情况下,您不能减少这种情况(如果需要使用开关/情况,则CC会增加)。此外,如果变量的命名很糟糕(就像试图混淆代码一样),圈复杂度可能会返回更低的值,因为它无法理解命名是很糟糕的。命名会增加您的复杂性,如果您在代码中不使用注释,在6个月后,您将很难理解为什么圈复杂度为3,但您只是无法理解正在编写的东西。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8379644

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档