gifts2017

Анализ цикломатической сложности кода

Опубликовал Андрей Костенко (Spitfire) в раздел Программирование - Инструментарий

Инструмент для контроля сложности написанного кода для 1С8.
Пригодится разработчикам, которые заботяться о качестве своего продукта, простоте его тестирования и дальнейшей поддержке.

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

Иногда встречаются рекомендации по написанию вроде "старайтесь, что бы тексты ваших методов не превышали размера экрана". Очевидно, что это несерьезное требование, тем более, что в профессиональном мире давно уже существуют метрики на сложность кода. Одна из таких метрик - цикломатическая сложность. Что это и как она рассчитывается - можно почитать в википедии (статья на английском написана лучше).

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

Как использовать данный инструмент:

  1. Открыть обработку в 1С:Предприятии 8.
  2. Вставить фрагмент кода, который вы хотите проанализировать в поле на закладке "Текст"
    или выбрать каталог, в котором лежат искодные коды модулей (в текстовом виде), указав маску выбора фалов
    или выбрать файл с текстом исходного кода.
  3. Нажать на кнопку "Выполнить".
  4. Полученные результаты можно отсортировать по любой из колонок дерева результатов. Для наглядности, отдельные методы в дереве результатов подкрашиваются в цвет, символизирующий его сложность.
  5. На закладке "Настройки" можно поменять цвета, настройки градиента раскрашивания.

Как применять это в реальной жизни?

В комментариях попросили рассказать, как это применять в реальной жизни. Делюсь своими рекомендациями, основанными на  внедрении этого инструмента в нашем коллективе:

  • Оптимум метрики: не стОит вводить. Мы ограничились введением верхнего допустимого значения. Исследования, о которых говорится в википедии в разделе "Применение", рекомендуют ограничивать сложность на уровне 10. В отдельных случая можно допустить поднятие лимита до 15. Сложность более 50 гарантирует вам головную боль при поддержке.
    Учитывая специфику разработки ИС (мало математически строгих алгоритмов - всегда нужны какие-то исключения и допущения), мы подняли допустимую верхнюю границу сложности до 14. В отдельных случаях, допускается превышение до 20 с обязательным комментарием в коде метода, чем вызвана необходимость повышенной сложности.
  • Разработчик, при передаче задачи в тест, самостоятельно замеряет сложность кода который он произвел/модифицировал. При необходимости, некоторые части выносятся в отдельные методы. В ряде случаем это также увеличивает или облегчает повторное использование кода.
  • Для разработчиков, которые систематически превышают максимально допустимую сложность кода, можно применять штрафные санкции.
  • Кстати, не стоит брать типовые конфигурации в качестве ориентира по сложности кода. Самое высокое значение цикломатической сложности, которое я видел, было около 350. Yell И да, это был типовой регламентированный отчет.

Примечания по использованию:

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

Скачать файлы

Наименование Файл Версия Размер Кол. Скачив.
Анализ цикломатической сложности (cyclomatic complexity analys)
.epf 17,27Kb
29.10.13
160
.epf 17,27Kb 160 Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Антон Чарушкин (hulio) 14.12.12 08:33
(0) Автор, объясните хотя бы в двух словах, чем полезна ваша обработка на практике? Какие выводы можно сделать, вычислив ЦСП?
2. Олег Филиппов (comol) 14.12.12 09:35
И какое значение должно быть для нормального кода... может статистику по типовым собирали или ещё что. С чем сравнивать?
3. Ярослав Радкевич (WKBAPKA) 14.12.12 11:59
я тоже не совсем понял как это работает, но за труды +
4. Андрей Костенко (Spitfire) 14.12.12 13:23
(1) hulio, (2) comol, коллеги, по вашим просьбам добавил описание практического применения.
вычисление ЦС дает ответ на вопрос, нужно ли уже разбить код на несколько методов, или еще нет.
5. Олег Филиппов (comol) 14.12.12 13:46
(4) Spitfire, Вот теперь однозначно "+" и мой грейт респект.
6. Андрей Окипний (DMSDeveloper) 14.12.12 14:30
7. Андрей Куришко (boggonzikov) 14.12.12 15:57
Спасибо, респект!
Эх, еще бы такое в снегопат.
8. Евгений Сосна (pumbaE) 14.12.12 16:47
(7) boggonzikov,
Эх, еще бы такое в снегопат.


Типа так можно хоть сейчас, а вот что бы все модули конфигурации перебрало и вывело сводный отчет - тут программировать надо.
9. Андрей Костенко (Spitfire) 14.12.12 16:53
(8) pumbaE, перебрать все модули конфигурации можно через Конфигуратор-Выгрузить файлы конфигурации.
Насчет сводного отчета - конкретизируйте, пожалуйста, как вы это видите. Возможно, я добавлю в саму обработку какие-то более удобные инструменты анализа результатов анализа =)
10. Сергей (ildarovich) 14.12.12 17:33
На мой взгляд, нужно прямо в тексте статьи сказать, что данная метрика является просто суммой количества слов "Тогда" (then), "?(" и "Цикл" (loop) в тексте модуля (не находящихся в комментариях или кавычках). Иначе термин "цикломатическая сложность" заставляет представлять что-то чрезвычайно хитроумное. Ничего плохого в простоте метрики нет. Однако такое более понятное определение поставит ее в ряд с другими простыми метриками типа количества строк, букв, слов, разделителей ";" в одной процедуре (функции) модуля.
zqzq; krv2k; artbear; +3 Ответить 1
11. Андрей Костенко (Spitfire) 14.12.12 17:56
(10) ildarovich, можно хоть весь листинг привести в описании. Зачем?
И потом, обработка действительно считает цикломатическую сложость - количество циклов в графе управления программы. Если бы 1С была другой, например, многопоточной, такой простой реализации не получилось бы.

И мне бы не хотелось, что бы эта метрика оказалась в одном ряду с подсчетом количества слов или строк метода. Почему? Потому что эти метрики на практике бесполезны, и интересуют только любителей больших чисел.
12. Андрей Волин (kser87) 14.12.12 18:06
13. Евгений Сосна (pumbaE) 14.12.12 18:10
ОФФ: Странно, но в рассылке по почте стоит автором tormozit.

(9) Spitfire, мое программировать - это в плане добавить в снегопате обход дерева метаданных и передачу текстов в вашу обработку, т.е. что бы не было необходимости нажимать выгрузить тексты модулей, потом запускать обработку и т.д., а нажал волшебную кнопку и сразу автоматом заработало.

Имхо, для ежедневного использования непригодна, нет признаков игнорировать какой-то модуль; допустим типовая конфигурация, я все равно ничего не буду делать если вдруг ваша обработка покажет n, нет m число (m больше выглядит чем n). Т.е. сказать, а что изменилось за неделю получить такую информацию трудно.

Тот же итоговый отчет необходимо строить только по граничным показателям, если у меня макс. стоит число 15, то зачем мне для одного из вариантов отчета видеть процедуры с 1 или 2?
14. Сергей Старых (tormozit) 14.12.12 18:21
(13) Я тут не причем =)
Однако замечал во многих рассылках о комментариях с инфостарта, что я там как автор указан. Возможно кто первый подписался на комментарии, того рассылка и считает автором?
15. Сергей (ildarovich) 14.12.12 18:22
(12) Если быть занудой, то
количество циклов в графе управления программы
обработка НЕ считает. Собственно, в приведенных Вами ссылках все это уже написано. В частности, и то, что основное назначение метрики - это оценка мощности множества тестов для процедуры или функции. При этом делается ПРЕДПОЛОЖЕНИЕ, что мощность теста определяется необходимостью прогона графа управления по всем возможным путям. На практике при программировании в 1С редко когда применяется (автоматическое) модульное тестирование или юнит-тестирование. Поэтому применение данной метрики - это определенная условность. И доказать, что эта метрика лучше, чем, например, число строк в модуле, невозможно из-за трудностей определения критерия сравнения.
эти метрики на практике бесполезны, и интересуют только любителей больших чисел
- думаю, что это высказывание просто голословно.
16. Андрей Костенко (Spitfire) 14.12.12 19:36
(13) pumbaE, если честно, я не думал о потребности анализировать изменения за определенный период. мы у себя ее используем не так. Я подумаю о внедрении такой функциональности и о внедрении отборов в дерево результатов.
17. Андрей Костенко (Spitfire) 14.12.12 19:58
(15) ildarovich, указанные вами предположения сделаны не мной, а множеством умных людей, занимающимися computer science. Аналогичные предположения делаются, когда производится любое автоматизированное тестирование - регрессионное, юнит, модульное, любое - ведь протестировать все случаи, с которыми придется столкнуться программе, невозомжно и ненужно. Потому каждый сам выбирает себе достаточное множество тестов. А эта метрика, как вы правильно сказали, помогает оценить мощность множества таких тестов. И, кстати, то, что среди разработчиков на 1С автоматическое тестирование применяется реже, чем в других технологиях, не делает нам чести. К счастью, ситуация улучшается, я могу это видеть.

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

К сожалению, эта метрика придумана не мной, потому я не буду здесь ее защищать. Ее полезность изучена и доказана.
эти метрики на практике бесполезны, и интересуют только любителей больших чисел
- думаю, что это высказывание просто голословно.
в таком случае, приведите, пожалуйста, практическую ценность для разработчика числа строк или символов модуля. И объясните, что буду означать изменения этих метрик при добавлении/удалении больших комментариев или запросов.
18. Дмитрий Шмонин (Qsko) 15.12.12 12:54
Очень интересная разработка. Очень порадовала фраза:
Кстати, не стоит брать типовые конфигурации в качестве ориентира по сложности кода. Самое высокое значение цикломатической сложности, которое я видел, было около 350. И да, это был типовой регламентированный отчет.


О чём говорят эти замеры? На сколько я понял, главное, о чём говорит нам числовой показатель - "количество" учитываемых условий/условностей в каком-либо методе. Причём, если следовать рекомендациям, то эти учитываемые условия следует минимизировать, вынося их просчёт в отдельные процедуры и функции.

Забавно, что в типовых конфигурациях самыми "сложными" оказались те, что отвечают за:
1) вывод печатных (ПечатьСчетаФактуры1137 - 39) и регламентированной отчётности (ПроверитьВозможностьВыгрузки - 131),
2) процедуры проведения документов по регистрам.
Хотя мне кажется, что если на одном уровне встречается "Если... Тогда... КонецЕсли", а за ним следует снова "Если... Тогда... КонецЕсли", то это не усложнят код (условия не вложены, на одном уровне), а на числовой показатель влияют: +1 за каждое Если... Тогда... КонецЕсли. Ибо эти проверялки условий - необходимость, которую выносить в отдельные функции вряд ли стоит. Посмотрите функции "ПроверитьВозможностьВыгрузки" в регламентированных отчётах.

По сему такая мысль: а может не надо при следующими друг за другом "Если... Тогда... КонецЕсли" на одном уровне увеличивать счётчик на +1? А вот за вложенность можно увеличивать. Чем больше вложенностей условий, тем запутаннее код. Тоже самое касается и циклов. Но у них другая беда - много циклов гораздо хуже, чем тоже количество "Если...".

Однако, метод есть метод. Он лишь ориентирует на ВОЗМОЖНО проблемные места, а не является показателем проблемности. То есть условие необходимое, но не достаточное.
19. Евгений Сосна (pumbaE) 15.12.12 13:00
(18) Qsko, ну еще в зарплатах модулях очень любят использовать, для возможности группировки.
Если Истина Тогда 
(возможно потому, что у разрабов типовых снегопата нет :) )
20. Анаит Бадалян (LaNaite) 15.12.12 17:34
21. Сергей (ildarovich) 15.12.12 20:31
(17) Привожу практическую ценность для разработчика числа строк или символов модуля на таком примере: Пусть требуется создать таблицу значений для данных табеля. Это можно сделать так:
ТЗ = Новый ТаблицаЗначений;
	ТЗ.Колонки.Добавить("ПервыйЧасов1");
	ТЗ.Колонки.Добавить("ПервыйЧасов2");
	ТЗ.Колонки.Добавить("ПервыйЧасов3");
	ТЗ.Колонки.Добавить("ПервыйЧасов4");
	ТЗ.Колонки.Добавить("ПервыйЧасов5");
	ТЗ.Колонки.Добавить("ПервыйЧасов6");
	ТЗ.Колонки.Добавить("ПервыйЧасов7");
	ТЗ.Колонки.Добавить("ПервыйЧасов8");
	ТЗ.Колонки.Добавить("ПервыйЧасов9");
	ТЗ.Колонки.Добавить("ПервыйЧасов10");
	ТЗ.Колонки.Добавить("ПервыйЧасов11");
	ТЗ.Колонки.Добавить("ПервыйЧасов12");
	ТЗ.Колонки.Добавить("ПервыйЧасов13");
	ТЗ.Колонки.Добавить("ПервыйЧасов14");
	ТЗ.Колонки.Добавить("ПервыйЧасов15");
	ТЗ.Колонки.Добавить("ПервыйЧасов16");
	ТЗ.Колонки.Добавить("ПервыйЧасов17");
	ТЗ.Колонки.Добавить("ПервыйЧасов18");
	ТЗ.Колонки.Добавить("ПервыйЧасов19");
	ТЗ.Колонки.Добавить("ПервыйЧасов20");
	ТЗ.Колонки.Добавить("ПервыйЧасов21");
	ТЗ.Колонки.Добавить("ПервыйЧасов22");
	ТЗ.Колонки.Добавить("ПервыйЧасов23");
	ТЗ.Колонки.Добавить("ПервыйЧасов24");
	ТЗ.Колонки.Добавить("ПервыйЧасов25");
	ТЗ.Колонки.Добавить("ПервыйЧасов26");
	ТЗ.Колонки.Добавить("ПервыйЧасов27");
	ТЗ.Колонки.Добавить("ПервыйЧасов28");
	ТЗ.Колонки.Добавить("ПервыйЧасов29");
	ТЗ.Колонки.Добавить("ПервыйЧасов30");
	ТЗ.Колонки.Добавить("ПервыйЧасов31");
...Показать Скрыть
Так:
ТЗ = НоваяТаблицаЗначений(Сред(СтрЗаменить(",1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31", ",", ",ПервыйЧасов"),2));
Или так:
ТЗ = Новый ТаблицаЗначений;
	Для ё = 1 По 31 Цикл 
		ТЗ.Колонки.Добавить("ПервыйЧасов" + ё)
	КонецЦикла;
Единственная метрика считает предпочтительным варианты 1 или 2, даже не различая их, а какой вариант на самом деле будет лучше? Это как раз и подскажут другие метрики типа числа строк или числа символов. Про комментарии не говорю, очевидно, что строки с комментариями учитываются отдельно (как и в обсуждаемой метрике).
Собственно, мою мысль точнее выскажет заключительная фраза из ОЧЕНЬ ИНТЕРЕСНОЙ СТАТЬИ про метрики кода http://www.viva64.com/ru/a/0045/
Подводя итог, хотелось бы отметить, что ни одной универсальной метрики не существует. Любые контролируемые метрические характеристики программы должны контролироваться либо в зависимости друг от друга, либо в зависимости от конкретной задачи, кроме того, можно применять гибридные меры, однако они так же зависят от более простых метрик и также не могут быть универсальными. Строго говоря, любая метрика - это лишь показатель, который сильно зависит от языка и стиля программирования, поэтому ни одну меру нельзя возводить в абсолют и принимать какие-либо решения, основываясь только на ней.
22. Сергей (ildarovich) 15.12.12 20:54
(21) Могу также добавить, что существует по крайней мере четыре приема, позволяющие намеренно занижать цикломатическую сложность, считаемую Вашей обработкой:
1) "Раскрытие циклов" - повторение одинаковых строк в программе, если число повторений заранее известно;
2) Использование оператора "Выполнить" - кавычки будут экранировать Тогда и Цикл от подсчета;
3) Использование списка (или таблицы) значений и поиска в нем вместо Если ... ИначеЕсли ... ИначеЕсли ... КонецЕсли;
4) Использование рекурсии вместо циклов. При этом вместо условия выхода использовать неполноту вычисления логических выражений (не вполне уверен, но стоит попробовать).

(11) Если привести в статье более понятное определение, то разработчики, желающие разрабатывать код со значением сложности менее 10, будут просто складывать число циклов и условных операторов (считать до 10 не сложно) вместо более "цикломатически-сложной" (шутка) процедуры запуска обработки.

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

P.S.: Думаю, что еще одна область применения алгоритма оценки - это написание на его основе нового "правила проверки" для конфигурации "1С:Автоматизированная проверка конфигураций". Плюс в том, что там уже есть готовые функции "ПолучитьТекстМодуля(ИмяМодуля)", "ПолучитьСтруктуруМодуля(ИмяМодуля)"
zqzq; CratosX; +2 Ответить
23. Александр Никитин (ManyakRus) 17.12.12 12:06
отчет работает :)
показывает что надо, правильно.

Только оно не поможет заставить программистов исправить свой код,
скажут что у меня сложные вычисления поэтому и сложный код..

(у меня доходит до 37 ЦС, у коллеги до 75 ЦС)
24. Андрей Костенко (Spitfire) 17.12.12 16:11
(23) ManyakRus, как показывает практика, задачи класса "заставить людей что-то делать" или "заставить людей что-то делать так, как нужно" решаются другими способами. :) Это отдельная область знаний.
25. Сергей (ildarovich) 02.09.13 23:39
Понадобилось воспользоваться обработкой... Нашел ошибку: считаются лексемы "Тогда", но не считаются "тогда" и тому подобное. Понятно, при подсчете нужно приводить строки к одному регистру. Кстати, непонятно почему не используется встроенная функция СтрЧислоВхождений(<Строка>, <ПодстрокаПоиска>), а написана своя.
26. Андрей Костенко (Spitfire) 29.10.13 12:51
(25) ildarovich, Спасибо за замечание, выложил исправленную версию.
Свой метод подсчета вхождений пришлось писать потому, что СтрЧислоВхождений не умеет искать в режиме "слово целиком", то есть, он посчитает вхождения инструкций в идентификаторы.
ildarovich; +1 Ответить
27. koder (bashhhh) 12.03.15 21:30
Протестируем все свои наработки. Спасибо за отчет!
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа