Поиск по сайту:

Что такое цикломатическая сложность? Измерение качества кода


Цикломатическая сложность — это метрика кода, которую можно просмотреть во многих интегрированных средах разработки, таких как Visual Studio. Хотя это и не точная наука, она позволяет получить общее представление о сложности функций, классов и пространств имен, что может быть полезно при поиске кода для рефакторинга.

Что такое цикломатическая сложность?

Цикломатическая сложность в основном измеряет количество ветвлений вашего кода. Каждый раз, когда появляется оператор if или другой управляющий блок, например цикл, цикломатическая сложность возрастает, поскольку граф все больше и больше будет походить на дерево.

Если вы представите свой код как серию действий (функций, вызовов методов, присвоений переменных), связанных потоком управления, вы получите абстрактный граф, который можно использовать для лучшего понимания сложности. Для распространенных потоков управления, таких как операторы if и циклы for, графики выглядят следующим образом:

Формула для этого проста; возьмите количество ребер в графе (стрелки, соединяющие все) и вычтите количество узлов в графе (сами действия).

Complexity = Edges -- Nodes + 2

Например, этот код имеет цикломатическую сложность, равную единице, поскольку в нем нет ветвей, и он просто снова и снова вызывает WriteLine. Поскольку это совершенно линейный код, количество узлов компенсирует количество ребер, что дает цикломатическую сложность, равную единице.

public void TestFunction()
{
    Console.WriteLine("Test");
    Console.WriteLine("Test");
    Console.WriteLine("Test");
    Console.WriteLine("Test");
    Console.WriteLine("Test");
}

Для более сложного кода с ветвями сложность будет выше. Этот код, содержащий оператор switch , имеет сложность 6, потому что существует много разных путей, по которым может идти код. Каждый case в операторе switch усложняет задачу, поскольку может привести к разным результатам при разных входных данных.

public void TestFunction(string arg)
{
    switch(arg)
    {
        case "one":
            Console.WriteLine("Test");
            break;
        case "two":
            Console.WriteLine("Test");
            break;
        case "three":
            Console.WriteLine("Test");
            break;
        case "four":
            Console.WriteLine("Test");
            break;
        case "five":
            Console.WriteLine("Test");
            break;
    }
 
    Console.WriteLine("Test");
}

Цикломатическая сложность рассчитывается только в рамках функции. Если функция вызывает другую функцию с высокой цикломатической сложностью, она считается только одним узлом и ничего не добавляет к вызывающей стороне, несмотря на то, что технически усложняет программу в общем смысле.

Полезна ли цикломатическая сложность?

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

По большей части сложность от 6 до 8, вероятно, хороша, если сам код хорошо отформатирован. Все, что от 8 до 15, сомнительно, а все, что больше 15, вероятно, не очень хорошо. Все, что больше 25, почти наверняка является проблемой, если не доказано обратное.

Хотя высокая цикломатическая сложность любой данной функции не является концом света, она может указывать на более серьезную проблему. Функции высокой сложности сложнее поддерживать, и они подвержены большему количеству ошибок, так как есть больше вещей, которые могут пойти не так. А более сложные функции напрямую приводят к более сложным модульным тестам, что может затруднить поддержку кода в долгосрочной перспективе из-за сложности тестирования.

Visual Studio и другие IDE вычисляют совокупную сложность целых классов и пространств имен, что может быть полезно для отслеживания наиболее сложных классов. Вы можете сортировать по наибольшей сложности и детализировать отдельные функции.

Часто проверка кода может учитывать цикломатическую сложность, даже помечая проблемные функции, которые могут потребовать ручной проверки. Это может сделать его очень полезным инструментом для поддержания чистой и упорядоченной кодовой базы.

Ищем плохой код

Многие IDE, такие как Visual Studio, будут иметь встроенные инструменты для расчета цикломатической сложности и других показателей кода для всей вашей кодовой базы.

Чтобы сделать это в Visual Studio, щелкните Анализ > Вычислить метрики кода > Для решения.

Откроется панель «Метрики кода», на которой будет показана разбивка вашего решения. Вы можете отсортировать по сложности в порядке убывания, чтобы просмотреть наиболее проблемные пространства имен.

Наряду со сложностью Visual Studio также представляет «индекс ремонтопригодности», который оценивает метод от 0 до 100 и выше, легкость его обслуживания, а также «связь классов», в котором указано, на сколько классов ссылается эта функция или класс.

Здесь Visual Studio указала на мой метод из 400 строк, который набрал колоссальные 72 балла по шкале сложности, а также 14/100 по индексу ремонтопригодности (представлен в виде желтого знака опасности треугольника) и ссылается на 65 различных классов.

Вы можете быть отправлены прямо в пять стадий горя в результате. «Но это действительно длинная сопрограмма, в которой есть куча задач!» Я говорю себе, пытаясь отрицать, что код, который я написал, математически плох, до такой степени, что Visual Studio выдает предупреждение. Сложность 72, безусловно, нуждается в очистке.

В этом случае исправить было просто — у сопрограммы есть куча задач, поэтому я разбиваю эти задачи на более мелкие сопрограммы и заменяю основной метод вызовами подпрограмм. Общий код не изменился, как и общая сложность самого класса, но теперь основная функция не является чудовищем из 400 строк.




Все права защищены. © Linux-Console.net • 2019-2024