Jump to content

Цикломатическая сложность

Цикломатическая сложность — это программная метрика , используемая для обозначения сложности программы . Это количественная мера количества линейно независимых путей через исходный код программы . Он был разработан Томасом Дж. Маккейбом-старшим в 1976 году.

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

Одна из стратегий тестирования , названная Маккейбом, который первым ее предложил, тестированием базового пути , заключается в проверке каждого линейно независимого пути в программе. В этом случае количество тестовых случаев будет равно цикломатической сложности программы. [1]

Описание [ править ]

Определение [ править ]

См. подпись
График потока управления простой программы. Программа начинает выполнение с красного узла, затем входит в цикл (группа из трех узлов непосредственно под красным узлом). При выходе из цикла используется условный оператор (группа под циклом), и программа завершается в синем узле. Этот граф имеет девять ребер, восемь узлов и одну компоненту связности , поэтому цикломатическая сложность программы равна 9 − 8 + 2×1 = 3 .

Существует несколько способов определения цикломатической сложности раздела исходного кода . Одним из распространенных способов является количество линейно независимых путей внутри него. Набор путей линейно независимо, если множество ребер любого пути в не является объединением множеств ребер путей в некотором подмножестве . Если бы исходный код не содержал операторов потока управления (условий или точек принятия решения), сложность была бы равна 1, поскольку в коде был бы только один путь. Если бы в коде был один оператор IF с одним условием, в коде было бы два пути: один, где оператор IF имеет значение ИСТИНА, и другой, где он имеет значение ЛОЖЬ. Здесь сложность будет равна 2. Два вложенных IF с одним условием или один IF с двумя условиями дадут сложность 3.

Другой способ определить цикломатическую сложность программы — посмотреть на ее граф потока управления , ориентированный граф , содержащий базовые блоки программы, с ребром между двумя базовыми блоками, если управление может передаваться от первого ко второму. Тогда сложность M определяется как [2]

где

Та же функция, представленная с использованием альтернативной формулировки, в которой каждая точка выхода соединяется обратно с точкой входа. Этот граф имеет 10 ребер, восемь узлов и одну связную компоненту , что также приводит к цикломатической сложности 3 при использовании альтернативной формулировки ( 10 − 8 + 1 = 3 ).

Альтернативная формулировка этого, как первоначально предлагалось, заключается в использовании графа, в котором каждая точка выхода соединена обратно с точкой входа. В этом случае граф сильно связен . Здесь цикломатическая сложность программы равна циклому числу ее графа (также известному как первое число Бетти ), которое определяется как [2]

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

Для отдельной программы (или подпрограммы, или метода) P всегда равно 1; более простая формула для одной подпрограммы: [3]

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

Маккейб показал, что цикломатическая сложность структурированной программы только с одной точкой входа и одной точкой выхода равна количеству точек принятия решения («если» или условных циклов), содержащихся в этой программе, плюс одна. Это справедливо только для точек принятия решения, учитываемых на самых низких инструкциях машинного уровня. [4] Решения, включающие составные предикаты, подобные тем, которые встречаются в языках высокого уровня, таких как IF cond1 AND cond2 THEN ... следует рассчитывать с точки зрения задействованных переменных-предикатов. В этом примере следует посчитать две точки принятия решения, поскольку на уровне машины это эквивалентно IF cond1 THEN IF cond2 THEN .... [2] [5]

Цикломатическая сложность может быть расширена до программы с несколькими точками выхода. В данном случае оно равно

где — количество точек принятия решения в программе, а s — количество точек выхода. [5] [6]

Алгебраическая топология [ править ]

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

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

Основу пространства циклов легко построить, сначала зафиксировав охватывающий лес графа, а затем рассмотрев циклы, образованные одним ребром, не находящимся в лесу, и путь в лесу, соединяющий конечные точки этого ребра. Эти циклы составляют основу пространства циклов. Цикломатическое число также равно количеству ребер, не входящих в максимальный остовный лес графа. Поскольку количество ребер в максимальном остовном лесу графа равно числу вершин минус количество компонент, формула определяет цикломатическое число. [7]

Цикломатическая сложность также может быть определена как относительное число Бетти , размер относительной группы гомологии :

который читается как «ранг первой группы гомологий графа G относительно конечных узлов t ». Это технический способ сказать «количество линейно независимых путей в графе потока от входа до выхода», где:

  • «линейно независимый» соответствует гомологии, а возврат не учитывается дважды;
  • «пути» соответствуют первой гомологии (путь — это одномерный объект); и
  • «Относительный» означает, что путь должен начинаться и заканчиваться в точке входа (или выхода).

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

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

Интерпретация [ править ]

В своем докладе «Метрики качества программного обеспечения для выявления рисков» [8] для Министерства внутренней безопасности Том Маккейб представил следующую классификацию цикломатической сложности:

  • 1–10: Простая процедура, небольшой риск
  • 11–20: более сложный, умеренный риск.
  • 21–50: Сложный, высокий риск
  • > 50: непроверяемый код, очень высокий риск.

Приложения [ править ]

Ограничение сложности во время разработки [ править ]

Одним из оригинальных приложений Маккейба было ограничение сложности процедур во время разработки программ. Он рекомендовал программистам подсчитывать сложность модулей, которые они разрабатывают, и разбивать их на более мелкие модули всякий раз, когда цикломатическая сложность модуля превышает 10. [2] Эта практика была принята в методологии структурированного тестирования NIST , которая отметила, что с момента первоначальной публикации Маккейба цифра 10 получила существенные подтверждающие доказательства. Однако он также отметил, что в некоторых обстоятельствах может быть целесообразным ослабить ограничение и разрешить модули со сложностью до 15. Поскольку методология признавала, что иногда возникают причины для выхода за пределы согласованного предела, она сформулировала свою рекомендацию как «Для каждого модуля либо ограничьте цикломатическую сложность [согласованным пределом], либо предоставьте письменное объяснение того, почему предел был превышен». [9]

программы « структурированности Измерение »

Раздел VI статьи МакКейба 1976 года посвящен определению того, как выглядят графы потока управления (CFG) неструктурированных программ с точки зрения их подграфов, которые определил МакКейб. (Подробнее см. в теореме о структурированной программе .) Маккейб завершил этот раздел, предложив числовую меру того, насколько близка к идеалу структурированного программирования данная программа, то есть ее «структурированность». Маккейб назвал разработанную им для этой цели меру существенной сложностью . [2]

Чтобы вычислить эту меру, исходная конфигурация CFG итеративно сокращается путем выявления подграфов, имеющих одну точку входа и одну точку выхода, которые затем заменяются одним узлом. Это сокращение соответствует тому, что сделал бы человек, если бы извлек подпрограмму из более крупного фрагмента кода. (В настоящее время такой процесс подпадает под общий термин « рефакторинг» .) Метод редукции Маккейба позже в некоторых учебниках был назван конденсацией , поскольку он рассматривался как обобщение конденсации на компоненты, используемые в теории графов . [10] Если программа структурирована, то процесс сокращения/конденсации Маккейба сводит ее к одному узлу CFG. Напротив, если программа не структурирована, итерационный процесс определит несократимую часть. Существенная мера сложности, определенная Маккейбом, — это просто цикломатическая сложность этого неприводимого графа, поэтому она будет равна ровно 1 для всех структурированных программ, но больше единицы для неструктурированных программ. [9] : 80 

для тестирования Последствия программного обеспечения

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

Это полезно из-за двух свойств цикломатической сложности M для конкретного модуля:

  • M — верхняя граница количества тестовых случаев, необходимых для достижения полного покрытия ветвей .
  • M — нижняя граница количества путей через граф потока управления (CFG). Предполагая, что каждый тестовый пример использует один путь, количество случаев, необходимых для достижения покрытия пути, равно количеству путей, которые фактически можно пройти. Но некоторые пути могут оказаться невозможными, поэтому, хотя количество путей через CFG явно является верхней границей количества тестовых случаев, необходимых для покрытия пути, это последнее число ( возможных путей) иногда меньше M .

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

Например, рассмотрим программу, состоящую из двух последовательных операторов if-then-else.

if (c1())
    f1();
else
    f2();

if (c2())
    f3();
else
    f4();
График потока управления исходного кода выше; красный кружок — точка входа в функцию, а синий кружок — точка выхода. Выход соединен со входом, чтобы сделать граф сильно связным.

В этом примере двух тестовых случаев достаточно для достижения полного покрытия ветвей, а для полного покрытия путей необходимы четыре. Цикломатическая сложность программы равна 3 (поскольку сильно связный граф программы содержит 9 ребер, 7 узлов и 1 связную компоненту) ( 9 − 7 + 1 ).

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

К сожалению, не всегда практично проверять все возможные пути реализации программы. Учитывая приведенный выше пример, каждый раз, когда добавляется дополнительный оператор if-then-else, количество возможных путей увеличивается в 2 раза. По мере того, как программа растет таким образом, она быстро достигает точки, в которой тестирование всех путей становится непрактично.

Одна из распространенных стратегий тестирования, поддерживаемая, например, методологией структурированного тестирования NIST, заключается в использовании цикломатической сложности модуля для определения количества тестов белого ящика , необходимых для получения достаточного покрытия модуля. Практически во всех случаях по такой методологии модуль должен иметь как минимум столько тестов, сколько его цикломатическая сложность. В большинстве случаев этого количества тестов достаточно для проверки всех соответствующих путей функции. [9]

В качестве примера функции, для точного тестирования которой требуется нечто большее, чем простое покрытие ветвей, рассмотрим приведенную выше функцию. Однако предположим, что во избежание возникновения ошибки любой код, вызывающий либо f1() или f3() должен также позвонить другому. [а] Предполагая, что результаты c1() и c2() независимы, функция, представленная выше, содержит ошибку. Покрытие ветвей позволяет протестировать метод всего с помощью двух тестов, например следующих тестовых случаев:

  • c1() возвращает истину и c2() возвращает истину
  • c1() возвращает ложь и c2() возвращает ложь

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

  • c1() возвращает истину и c2() возвращает ложь
  • c1() возвращает ложь и c2() возвращает истину

Любой из этих тестов выявит ошибку.

Соотношение с количеством дефектов [ править ]

Во многих исследованиях изучалась корреляция между числом цикломатической сложности Маккейба и частотой дефектов, возникающих в функции или методе. [11] Некоторые исследования [12] найти положительную корреляцию между цикломатической сложностью и дефектами; функции и методы, которые имеют наибольшую сложность, как правило, также содержат больше всего дефектов. Однако корреляция между цикломатической сложностью и размером программы (обычно измеряемым в строках кода ) была продемонстрирована много раз. Лес Хаттон заявил [13] эта сложность обладает той же предсказательной способностью, что и строки кода. Исследования, в которых контролировался размер программы (т. е. сравнение модулей разной сложности, но одинакового размера), как правило, менее убедительны: многие не обнаруживают значимой корреляции, тогда как другие обнаруживают корреляцию. Некоторые исследователи ставят под сомнение достоверность методов, использованных в исследованиях, и не обнаруживают никакой корреляции. [14] Хотя это соотношение, вероятно, существует, его нелегко использовать на практике. [15] Поскольку размер программы не является контролируемой характеристикой коммерческого программного обеспечения, полезность числа МакКейба подвергается сомнению. [11] Суть этого наблюдения состоит в том, что более крупные программы имеют тенденцию быть более сложными и иметь больше дефектов. что снижение цикломатической сложности кода Не доказано, уменьшает количество ошибок или ошибок в этом коде. Однако международные стандарты безопасности, такие как ISO 26262 , требуют руководящих принципов кодирования, обеспечивающих низкую сложность кода. [16]

См. также [ править ]

Примечания [ править ]

  1. ^ Это довольно распространенный тип состояния; рассмотреть возможность того, что f1 выделяет некоторый ресурс, который f3 релизы.

Ссылки [ править ]

  1. ^ Эй Джей Соби. «Тестирование базового пути» .
  2. ^ Перейти обратно: а б с д и Маккейб (декабрь 1976 г.). «Мера сложности». Транзакции IEEE по разработке программного обеспечения . СЭ-2 (4): 308–320. дои : 10.1109/tse.1976.233837 . S2CID   9116234 .
  3. ^ Филип А. Лаплант (25 апреля 2007 г.). Что должен знать каждый инженер о программной инженерии . ЦРК Пресс. п. 176. ИСБН  978-1-4200-0674-2 .
  4. ^ Фрикер, Себастьян (апрель 2018 г.). «Что такое цикломатическая сложность?» . Фроглогик ГмбХ . Проверено 27 октября 2018 г. Чтобы вычислить графовое представление кода, мы можем просто дизассемблировать его ассемблерный код и создать граф, следуя правилам: ...
  5. ^ Перейти обратно: а б Дж. Белзер; А. Кент; А.Г. Хольцман; Дж. Г. Уильямс (1992). Энциклопедия компьютерных наук и технологий . ЦРК Пресс. стр. 367–368.
  6. ^ Харрисон (октябрь 1984 г.). «Применение меры сложности Маккейба к программам с множественным выходом». Программное обеспечение: практика и опыт . 14 (10): 1004–1007. дои : 10.1002/спе.4380141009 . S2CID   62422337 .
  7. ^ Дистель, Рейнхард (2000). Теория графов . Аспирантура по математике 173 (2-е изд.). Нью-Йорк: Спрингер. ISBN  978-0-387-98976-1 .
  8. ^ Томас Маккейб младший (2008). «Метрики качества программного обеспечения для выявления рисков» . Архивировано из оригинала 29 марта 2022 г.
  9. ^ Перейти обратно: а б с Артур Х. Уотсон; Томас Дж. Маккейб (1996). «Структурированное тестирование: методология тестирования с использованием метрики цикломатической сложности» (PDF) . Специальная публикация NIST 500-235.
  10. ^ Пол К. Йоргенсен (2002). Тестирование программного обеспечения: подход мастера, второе издание (2-е изд.). ЦРК Пресс. стр. 150–153. ISBN  978-0-8493-0809-3 .
  11. ^ Перейти обратно: а б Норман Э. Фентон; Мартин Нил (1999). «Критика моделей прогнозирования дефектов программного обеспечения» (PDF) . Транзакции IEEE по разработке программного обеспечения . 25 (3): 675–689. CiteSeerX   10.1.1.548.2998 . дои : 10.1109/32.815326 .
  12. ^ Шредер, Марк (1999). «Практическое руководство по объектно-ориентированным метрикам». ИТ-специалист . 1 (6): 30–36. дои : 10.1109/6294.806902 . S2CID   14945518 .
  13. ^ Лес Хаттон (2008). «Роль эмпиризма в повышении надежности будущего программного обеспечения» . версия 1.1.
  14. ^ Кан (2003). Метрики и модели в инженерии качества программного обеспечения . Аддисон-Уэсли. стр. 316–317. ISBN  978-0-201-72915-3 .
  15. ^ Г.С. Черф (1992). «Исследование характеристик сопровождения и поддержки коммерческого программного обеспечения». Журнал качества программного обеспечения . 1 (3): 147–158. дои : 10.1007/bf01720922 . ISSN   1573-1367 . S2CID   37274091 .
  16. ^ ISO 26262-3:2011(ru) Транспорт дорожный. Функциональная безопасность. Часть 3. Фаза концепции . Международная организация по стандартизации.

Внешние ссылки [ править ]

Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 34560414b6f785ad1234da436c117083__1714564680
URL1:https://arc.ask3.ru/arc/aa/34/83/34560414b6f785ad1234da436c117083.html
Заголовок, (Title) документа по адресу, URL1:
Cyclomatic complexity - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)