Полные списки выражений для кода C #, который +1 для Cyclomatic Complexity - PullRequest
3 голосов
/ 05 декабря 2011

Мне нужно построить управляющую диаграмму (простой потоковый граф с узлами и ребрами) для каждого метода в моем проекте C #, чтобы продемонстрировать способ расчета цикломатической сложности.

Сначала я подсчитал цикломатическую сложность, используя VS 2010, а затем построил график, чтобы убедиться, что значение результата совпадает со значением, подсчитанным из VS. Однако здесь я столкнулся с некоторой проблемой, поскольку не уверен, какое выражение на самом деле считается +1 для цикломатической сложности.

Давайте рассмотрим один пример здесь:

 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 операторов case, я не понимаю, какие другие выражения способствуют сложности.

Я провел поиск по многим источникам, но не смог получить полных списков всех выражений, которые будут подсчитаны.

Может кто-нибудь помочь с этим? Или есть какой-либо инструмент, который я могу генерировать блок-схему управления из кода C #?

Заранее спасибо ...

1 Ответ

3 голосов
/ 18 января 2012

То, что вы должны сделать в первую очередь, это попытаться визуализировать цикломатическую сложность с помощью графиков.Проходя через ваш код, мне удалось вычислить 10. Чтобы лучше понять это, взгляните на следующее:

public void MyMethod()
{
    Console.WriteLine("Hello ShennyL");
}

Это имеет цикломатическую сложность 1, потому что здесь есть только один возможный путь, и эточтобы отобразить сообщение.

public void AnotherMethod()
{
    if (someCondition)
    {
        Console.WriteLine("Hello Shennly");
    }
}

На этот раз мы имеем цикломатическую сложность 2. +1 добавляется к if, while, for, foreach.В этом случае есть два пути.Если someCondition имеет значение true, сообщение будет отображаться (первый возможный путь), а если someCondition - false, сообщение не будет отображаться (второй возможный путь).

Если вы посмотрите на реализацию Dispose в WindowsФормы выглядят так:

protected override void Dispose(bool disposing)
{
    if (disposing && (components != null))
    {
        components.Dispose();
    }
    base.Dispose(disposing);
}

Здесь у вас цикломатическая сложность 3. В случае && оба значения должны быть истинными, чтобы оценить выражение внутри.Это означает, что если оба disposing истинны и (components != null) истинны, у вас есть первый путь.Если disposing ложно, у вас есть второй путь.Третий путь проистекает из того факта, что components может быть нулевым и, как таковой, он оценивается как ложный.Следовательно, у вас цикломатическая сложность три.

В случае switch вы получаете +1, а за каждый casedefault), который появляется внутри, вы получаете +1.В случае вашего метода у вас есть шесть case операторов и один default плюс switch, что в сумме составляет 8.

Как я сказал в начале, если вы попытаетесь визуализировать свой код вВ терминах графика это можно разбить следующим образом (я добавляю свои комментарии к вашему коду и удаляю ваши комментарии):

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);                   
}        

В некоторых моментах я могу ошибаться, но в основном это идеяРасчет цикломатической сложности.Вы также должны понимать, что есть случаи, когда вы не можете уменьшить это (если вам нужно использовать переключатель / case, CC увеличивается).Кроме того, если ваши переменные имеют ужасное наименование (как если бы вы пытались запутать свой код), цикломатическая сложность может возвращать меньшее значение, потому что она не может понять, что ваше именование ужасно.Присвоение имен может усложнить для вас, и если вы не используете комментарии в своем коде, через 6 месяцев вам будет сложно понять, почему цикломатическая сложность равна 3, но вы просто не можете понять, что пишется.

...