Перейти к содержанию

Когнитивная сложность (CognitiveComplexity)

Тип Поддерживаются
языки
Важность Включена
по умолчанию
Время на
исправление (мин)
Теги
Дефект кода BSL
OS
Критичный Да 15 brainoverload

Параметры

Имя Тип Описание Значение
по умолчанию
complexityThreshold Целое Допустимая когнитивная сложность метода 15
checkModuleBody Булево Проверять тело модуля true

Описание диагностики

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

Подсчет Когнитивной сложности

Ниже приведены правила анализа кода, условия повышения когнитивной сложности.

Каждый следующий блок увеличивает сложность на 1

// Цикл `Для каждого`
Для каждого Элемент Из Коллекция Цикл                // +1
КонецЦикла;

// Цикл `Для`
Для Ит = Начало По Конец Цикл                        // +1
КонецЦикла;

// Цикл `Пока`
Пока Условие Цикл                                    // +1
КонецЦикла;


// Условие
Если Условие Тогда                                   // +1

// Альтернативная ветвь условия
ИначеЕсли Условие2 Тогда                             // +1

// Ветвь по-умолчанию
Иначе
КонецЕсли;

// Тернарный оператор
Значение = ?(Условие, ЗначениеИстина, ЗначениеЛожь); // +1

Попытка
// Обработка исключения
Исключение                                           // +1
КонецПопытки;

// Переход на метку
Перейти ~Метка;                                      // +1

// Бинарные логические операции

Пока Условие ИЛИ Условие2 Цикл                       // +2
КонецЦикла;

Если Условие И Условие2 Тогда                        // +2

ИначеЕсли Условие2                                   // +1
        ИЛИ Условие3 И Условие4 Тогда                // +2

КонецЕсли;

Значение = ?(Условие ИЛИ Условие2 ИЛИ НЕ Условие3,   // +3
                ЗначениеИстина, ЗначениеЛожь); 

Значение = Одно ИЛИ Второе;                          // +1

Значение = А <> B;                                   // +1

За каждый уровень вложенности, следующие блоки получают дополнительную единицу сложности

// Цикл `Для каждого`
Для каждого Элемент Из Коллекция Цикл
КонецЦикла;

// Цикл `Для`
Для Ит = Начало По Конец Цикл
КонецЦикла;

// Цикл `Пока`
Пока Условие Цикл
КонецЦикла;


// Условие
Если Условие Тогда
КонецЕсли;

// Тернарный оператор
Значение = ?(Условие, ЗначениеИстина, ЗначениеЛожь);

Попытка
// Обработка исключения
Исключение
КонецПопытки;

~Метка:

Альтернативные ветки, бинарные операции и переход на метку не увеличивают когнитивную сложность при вложении

Примеры

Ниже на примерах кода произведен рассчет когнитивной сложности методов.

Функция Пример1(ТипКласса)
    Если ТипКласса.Неизвестен() Тогда                                                  // +1, условие, вложенности нет
        Возврат Символы.НеизвестныйСимвол;
    КонецЕсли;

    НеизвестностьНайдена = Ложь;
    СписокСимволов = ТипКласса.ПолучитьСимвол().Потомки.Поиск("имя");
    Для Каждого Символ Из СписокСимволов Цикл                                          // +1, цикл, вложенности нет
        Если Символ.ИмеетТип(Символы.Странное)                                         // +2, условие вложенное в цикл, вложенность 1
            И НЕ Символы.Экспортный() Тогда                                            // +1, логическая операция, вложенность не учитывается

            Если МожноПереопределить(Символ) Тогда                                     // +3, вложенное условие, вложенность 2
                Переопределяемость = ПроверитьПереопределяемость(Символ, ТипКласса);
                Если Переопределяемость = Неопределено Тогда                           // +4, вложенное условие, вложенность 3
                    Если НЕ НеизвестностьНайдена Тогда                                 // +5, вложенное условие, вложенность 4
                        НеизвестностьНайдена = Истина;
                    КонецЕсли;
                ИначеЕсли Переопределяемость Тогда                                     // +1, альтернативная ветвь условия, вложенность не учитывается
                    Возврат Символ;
                КонецЕсли;
            Иначе                                                                      // +1, ветвь по-умолчанию, вложенность не учитывается
                Продолжить;
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;

    Если НеизвестностьНайдена Тогда                                                   // +1, вложенности нет
        Возврат Символы.НеизвестныйСимвол;
    КонецЕсли;

    Возврат Неопределено;
КонецФункции
Функция Пример2(Документ)
    НачатьТранзакцию();
    НадоПровести = ?(Документ.Проведен, ЛОЖЬ,                                                        // +1, тернарный оператор
                                        ?(Документ.ПометкаУдаления, ЛОЖЬ, ИСТИНА));                  // +2, вложенный тернарный оператор, вложенность 1
    Попытка                                                                                          // +0, попытка, повышает уровень вложенности
        ДокументОбъект = Документ.ПолучитьОбъект();
        Если ДокументОбъект.Проведен Тогда                                                           // +2, вложенное условие, вложенность 1
            Для Каждого СтрокаТабличнойЧасти Из ДокументОбъект.ТабличнаяЧасть Цикл                   // +3, вложенный цикл, вложенность 2
                Если СтрокаТабличнойЧасти.Колонка1 = 7                                               // +4, вложенное условие, вложенность 3
                        ИЛИ СтрокаТабличнойЧасти.Колонка2 = 7 Тогда                                  // +1, логическая операция, вложенность не учитывается
                    Продолжить;
                КонецЕсли;
                Если СтрокаТабличнойЧасти.Колонка4 > 1 Тогда                                         // +4, вложенное условие, вложенность 3
                    Прервать;
                Иначе                                                                                // +1, ветвь по-умолчанию, вложенность не учитывается
                    Если СтрокаТабличнойЧасти.Колонка1 + СтрокаТабличнойЧасти.Колонка2 = 2 Тогда     // +5, вложенное условие, вложенность 4
                        СтрокаТабличнойЧасти.Колонка10 = СтрокаТабличнойЧасти.Колонка1 * 2;
                    КонецЕсли;
                КонецЕсли;
            КонецЦикла;
        Иначе                                                                                        // +1, ветвь по-умолчанию, вложенность не учитывается
            НадоПровести = ДокументОбъект.Дата > ТекущаяДата();                                      // +1, логическая операция, вложенность не учитывается
            Перейти ~Метка;                                                                          // +1, переход на метку, вложенность не учитывается
        КонецЕсли;

        Если НадоПровести Тогда                                                                      // +2, вложенное условие, вложенность 1
            ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
        ИначеЕсли НЕ НадоПровести Тогда                                                              // +1, альтернативная ветвь, вложенность не учитывается
            ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);
        Иначе                                                                                        // +1, ветвь по-умолчанию, вложенность не учитывается
            ВызватьИсключение "Как так-то?";
        КонецЕсли;
    Исключение                                                                                       // +1, обработка исключения
        ПовторнаяЗапись = ЛОЖЬ;
        Попытка                                                                                      // +0, попытка, повышает уровень вложенности
            Если ДокументОбъект.Проведен Тогда                                                       // +3, вложенное условие, вложенность 2
                ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);
            КонецЕсли;
        Исключение                                                                                   // +2, обработка исключения, вложенность 1
            ПовторнаяЗапись = ИСТИНА;
        КонецПопытки;
        Если Не ПовторнаяЗапись Тогда                                                                // +2, вложенное условие, вложенность 1
            Пока ТранзакцияАктина() Цикл                                                             // +3, вложенный цикл, вложенность 2
                ОтменитьТранзакцию();
            КонецЦикла;
        КонецЕсли;
        ВызватьИсключение "Ошибка"
    КонецПопытки;

    ~Метка:
    Возврат Неопределено;
КонецФункции

Источники

Сниппеты

Экранирование кода

// BSLLS:CognitiveComplexity-off
// BSLLS:CognitiveComplexity-on

Параметр конфигурационного файла

"CognitiveComplexity": {
    "complexityThreshold": 15,
    "checkModuleBody": true
}