Показаны сообщения с ярлыком MI. Показать все сообщения
Показаны сообщения с ярлыком MI. Показать все сообщения

вторник, 12 февраля 2019 г.

Comments in Loop

Качество продукта начинается с красивых метрик кода. О том, что комментарии к коду только повышают его эффективность, уже говорилось в нескольких моих статьях ("Easy white-box testing", "Качество кода одним числом", "Документор кода или псевдокод"). Хотелось бы их подкрепить результатами исследований. Надеюсь, чарты сильнее убедят ваших программистов вставлять пояснения в код.

Для исследования были взяты две процедуры (с комментариями в цикле cmt_in loop и идентичная без комментариев cmt_no_loop) на PL/SQL Oracle:
  PROCEDURE cmts_in_loop
  IS
    t1 timestamp;
    t2 timestamp;
    l  varchar2(50);
  BEGIN
    t1 := SYSTIMESTAMP;
    FOR i IN 1..1000000 LOOP
      -- 1-st comment line in loop
      l := 'one command line in loop with comments';
      -- 2-nd comment line in loop
    END LOOP;
    t2 := SYSTIMESTAMP;
    dbms_output.put_line('timestamp for mln-loop with 2 comments: ' || to_char(t2 - t1, 'MI:SS.FF5'));
  END;
/
  PROCEDURE cmts_no_in_loop
  IS
    t2 timestamp;
    t3 timestamp;
    l  varchar2(50);
  BEGIN
    t2 := SYSTIMESTAMP;
    FOR i IN 1..1000000 LOOP
      l := 'one command line in loop without comments';
    END LOOP;
    t3 := SYSTIMESTAMP;
    dbms_output.put_line('timestamp for mln-loop without comments: ' || to_char(t3 - t2, 'MI:SS.FF5'));
  END;
/


Визуализируем и вычислим метрики кода в специализированном продукте ClearSQL:
Flowchart - cmts_in_loop
Flowchart - cmts_no_loop
По диаграммам Flowchart видно, что в обеих процедурах одинаковое количество узлов и рёбер, то есть наличие или отсутствие комментариев не влияет на цикломатическую сложность.

Измерение метрик кода дали следующие цифры:
 
Различные цифры в разрезе процедур подсвечены мной красным цветом. За счёт наличия строк-комментариев в первой процедуре вырос Maintainability Index - важная величина кода, которая чем выше, тем лучше код (подробные исследования функции смотрите в "Качество кода одним числом").
Да, идентичная программа с комментариями стоит дороже при изготовлении и поддержке, так как вместе с правкой значимых строк необходимо актуализировать и их примечания. Но это только по меркам компании Conquest Software Solutions, которая "с потолка" взяла формулу и коэффициенты для исчисления Technical Dept.
Описание Technical Dept
А теперь ударный аргумент - время на исполнение цикла.
Дельта выполнений первой и второй процедур 26 раз
Собрав результаты от пары дюжин выполнений, на график была выведена разница времени исполнения цикла с комментариями (cmt_in_loop) и времени выполнения аналогичного цикла, но без строк комментариев (cmt_no_loop). Да, по этому небольшому расхождению слегка заметно, что комментарии затягивают цикл. Но эта гипотеза была разрушена уже на второй сотне экспериментов:
Дельта выполнений первой и второй процедур 201 раз
То есть циклы без комментированных строк крутились дольше! Казалось бы - нонсенс, что увеличение строк в цикле убыстряет его ход, но видимо даже компилятору полезнее иметь код с пояснениями, а не только новичку программисту, правящему легаси.

Так что, решающим аргументом для добавления разъяснений в код стоит рассматривать следующее:
- комментарии не загружают текст, а наоборот помогают читать его;
- блок-схемы процедур "с" и "без" комментариев идентичны;
- комментарии никак не влияют на цикломатическую сложность;
- за счёт строк комментариев легко и быстро увеличить MI, то есть улучшить качество;
- комментарии даже в цикле не замедляют исполнение, а ускоряют его.

О том, сколько строк рабочих и вспомогательных оптимально (3/1) должно быть в коде, читайте в статье "Качество кода одним числом". Метрики кода могут показать общее количество и пропорцию строк, а настраиваемые правила для автоматической проверки выявят места с недоработками. В ClearSQL это называется Code Review Rule Editor, с помощью которого можно добавить пользовательские правила и проверять их в том же автоматическом режиме наряду со встроенными (~200штук).
О том, как проще добавлять пояснения в код, читайте в "Документор кода или псевдокод".

среда, 20 июня 2018 г.

Качество кода одним числом

Maintainability Index – величина качества кода

Качество продукта, согласно ISO-9126, состоит из 6 частей (см. Рис.1 "ISO-9126").
Рис.1 "ISO-9126"
Из этих же шести пунктов (см. Рис.1 "ISO-9126") строится и качество кода, которое можно измерить для любого языка программирования. К сожалению, идеального кода не существует и добиться невозможно, как и КПД-100%.
Одна из простейших метрик – количество параметров, которое рекомендуют не более 7: 5 входящих, 2 на выход. Особое место занимают глобальные переменные, наличие которых усложняет код.
Более сложно качество кода вычисляется по формулам, только одна из которых "цикломатическая сложность" пока принята институтом стандартов. Когда научному миру удастся доказать полезность и значимость остальных формул, тестировщики смогут официально ориентироваться на эти лимиты.
Формула расчёта Maintainability Index была выведена достаточно давно Доном Колеманом, Паулем Оманом и Джеком Хегмейстером. Она имеет несколько вариаций для различных языков программирования. Фактически, польза индекса "ремонтопригодности" не только в оценке готового кода, но по этой величине вполне можно спрогнозировать устойчивость кода с учётом будущих исправлений.
Согласно формулам (см. Рис.2 "Две формулы подсчёта количества багов в юните", где TNOpr – общее количество операторов, TNOpd – общее количество операндов, DNOpr – количество уникальных операторов, DNOpd  – количество уникальных операндов) Мариуса Халстеда, если код состоит хотя бы из одного оператора и операнда, то величина багов в этом коде уже не нулевая.
Рис.2 "Две формулы подсчёта количества багов в юните"
Если оценить обе формулы (см. Рис.2 "Две формулы подсчёта количества багов в юните") через их графики, то очевидно, что количество багов в новом и исправленном коде будет нулевым только в "пустой" подпрограмме.
 
Рис.3 "График и формула подсчёта новых багов"
На рисунке 3 "График и формула подсчёта новых багов" верхняя формула для расчёта прогнозируемых багов минимизирована по количеству операторов (1 шт) и операндов (2 шт). Количество багов смотрим по оси Y, количество операторов и операндов (только целые числа) смотрим по оси X. Поскольку рабочей подпрограммы без операторов и операндов не существует, то по графику убеждаемся, что количество багов резко уходит в бесконечность только при нулевых значениях операторов и операндов [0..1], количество багов растёт плавно (y>0 при x>1). 
 
 Рис.4 "График и формула подсчёта недавних багов"
Минимизировав вторую формулу (см. Рис.2 "Две формулы подсчёта количества багов в юните") для расчёта недавних багов и приняв один оператор на пару операторов, получаем по-сути аналогичный график (см. Рис.4 "График и формула подсчёта недавних багов"), когда количество багов равномерно растёт по оси Y и не может быть отрицательным, так как в рабочем коде должен быть хотя бы один оператор и операнд, то есть значения по оси X рассматриваются только целочисленные, начиная с 1.
Итак, мы убедились, что в любом коде всегда есть баги. А об их серьёзности можно судить по величине Maintainability Index (MI).

Из чего же складывается величина качества кода?
Максимальная формула учитывает значения Сложности Халстеда, Цикломатической Сложности, значимые Строки кода и объём Комментариев:
MI = 171 - 5.2 * ln(HV) - 0.23 * CC - 16.2 * ln (LOC) + 50 * sin(sqrt(2.4 * COM)), где HV – сложность Халстеда, CC – цикломатическая сложность, LOC – количество строк кода, COM – объём комментариев в коде.
Укороченная формула не учитывает объём комментариев:
MI = 171 - 5.2 * ln(HV) - 0.23 * CC - 16.2 * ln (LOC)
Компилируемые языки программирования "не отвлекаются" на комментарии, поэтому для них (например, Си) вполне очевидно использование укороченной формулы. А языки-интерпретаторы (например, SQL) корректнее оценивать по полной формуле, так как комментарии внутри цикла в некоторых языках могут замедлять исполнение программы, поскольку на вычленение незначимых строк тоже нужно время.
Пределы индекса принято рассматривать по следующей таблице (см. Рис.5 "Лимиты Maintainability Index"):
- подпрограмма требует немедленного исправления, если MI упал меньше 65;
- подпрограмму желательно исправить, если MI больше или равен 65, но меньше 85;
- подпрограмма не нуждается в исправлении, если MI равен или больше 85.
Исходя из формулы абсолютное максимальное значение Maintainability Index равно 221 (171-0-0-0+50), но оно не достижимо ни при каком содержимом сорсника.
Рис.5 "Лимиты Maintainability Index"
Об истории лимитов MI можно почитать в статье.

Итак, чем больше индекс, тем лучше код. Рассмотрим способы повышения индекса важности кода.
Более скорый способ увеличения индекса исходя из формулы первой модели "MI = 171 - 5.2 * ln(HV) - 0.23 * CC - 16.2 * ln (LOC) + 50 * sin(sqrt(2.4 * COM))" возможен за счёт увеличения объёма комментариев, так как индекс в формуле – наибольшее положительное число "50". Объём комментариев зависит от функции синуса, которая колеблется в пределах [-1..1]. Но поскольку объём комментариев можно исчислять двумя способами – как процент или долю, а значение синуса может быть и отрицательным, то необходимо выяснить оптимальные пределы комментариев. Для этого рассмотрим график функции "y(x)= 50 * sin(sqrt(2.4 * x))" на отрезках [0..100] (при исчислении комментариев в процентах) и [0..1] (при исчислении комментариев в долях от общего кода).
Рис.6 "График комментариев в процентах"
На графике (см. Рис.6 "График комментариев в процентах"), построенном по формуле "y(x)= 50 * sin(sqrt(2.4 * x))", по оси X имеем процентное соотношение комментариев к строкам кода, а по оси Y – величину для расчёта Maintainability Index. 1-2% или 25-26% или 83-84% комментариев дадут желаемый максимум (y=50), 0% или 4% или 17% или 37% или 66% комментариев абсолютно не влияют на Maintainability Index (y=0), 9% или 50-51% комментариев самым сильным образом (y=-50) отрицательно влияют на индекс ремонтопригодности. При этом MI может стать и отрицательной величиной. 
Рис.7 "График комментариев в долях"
На графике (см. Рис.7 "График комментариев в долях"), построенном по формуле "y(x)= 50 * sin(sqrt(2.4 * x))", по оси X имеем долевое соотношение комментариев к строкам кода, а по оси Y – величину для расчёта Maintainability Index. График показывает, что 3-4 комментированные строки кода из 10 рассматриваемых (или каждая третья) максимально помогают увеличить MI, то есть являются самым полезным соотношением.
Итак, если MI упал ниже 65, то по-быстрому его поднять можно вставкой комментариев в каждую третью строку.
Примечания:
- полезность/качество комментариев не рассчитывается формулой, поэтому не стоит забывать, что просто закомментированный код – это не полезные примечания;
- при добавлении комментариев соответственно увеличится и общее количество строк кода.

Шаг второй по повышению индекса устойчивости подпрограммы – снизить количество строк кода, потому что в формуле "MI = 171 - 5.2 * ln(HV) - 0.23 * CC - 16.2 * ln (LOC)" наибольший отрицательный индекс "16.2" у величины строк. На графике (см. Рис.8 "График и формула строк кода") видно, например, что 4500 строк уменьшат индекс на 136 пунктов из 171 возможного по формуле. Количество строк в подпрограмме определяется по спецсимволам текста, поэтому парсер обмануть не получится обычным размещением команд в одну строку файла. Единственный вариант – оптимизация кода за счёт объединения и выноса идентичных блоков кода в самостоятельные функции, которые будут рассматриваться как отдельные подпрограммы.
Примечания:
- не забывайте, что при этом увеличится количество параметров и скорее всего даже глобальных;
- блок-схемы, flowchart или UML диаграммы помогают вычленить повторяющиеся блоки хода подпрограммы.
 
 Рис.8 "График и формула строк кода"
Если пойти от обратного и принять в формуле MI(<=65) максимальные значения HV(=1000), CC(=10) и комментариев (sin[X]=1), то в одном юните желательно иметь не более 1500 строк (см. Рис.9 "График максимального количества строк кода и формула с учётом комментариев").
 Рис.9 "График максимального количества строк кода и формула с учётом комментариев"
То есть по формуле Maintainability Index с учётом комментариев мы вывели лимит для оптимального количества строк в подпрограмме: LOC<1500 mi="">=65.
Для формулы второй модели (без учёта комментариев) смотрите рисунок 10 "График максимального количества строк кода и формула без учёта комментариев".
 Рис.10 "График максимального количества строк кода и формула без учёта комментариев"
График по оси Y показывает MI, а LOC по оси X. Из чего следует, что в юните без комментариев для стабильно-устойчивого кода нужно иметь менее 50 строк (см. Рис.11 "Увеличенный график максимального количества строк кода для формулы без учёта комментариев").
 
 Рис.11 "Увеличенный график максимального количества строк кода для формулы без учёта комментариев"
Об иных подробностях строк кода читайте в статье "Source lines of code".

Третий шаг по повышению MI – это снижение сложности Халстеда из части "5.2 * ln(HV)". Максимальная величина Халстеда – 1000. Исходя из этого на графике (см. Рис.12 "График и формула Halstead Volume в рамках MI") видно, что сложность Халстеда максимально может уменьшить индекс ремонтопригодности на 36 пунктов.
 
 Рис.12 "График и формула Halstead Volume в рамках MI"
Все величины Халстеда рассчитываются по операторам и операндам. Напомню, что в выражении "a+b" оператором является плюс, а операндами – переменные "a" и "b". Длина программы по Халстеду – это сумма всех операторов и всех операндов. Словарь юнита он определил как сумму уникальных операторов и операндов. А помножив длину программы на логарифм словаря, Халстед получил объём подпрограммы (или ещё эту величину называют сложностью Халстеда):
HV = ( TNOpr + TNOpd ) * log2 ( DNOpr + DNOpd ),
где TNOpr – общее количество операторов, TNOpd – общее количество операндов, DNOpr – количество уникальных операторов, DNOpd  – количество уникальных операндов. Более подробно о величинах Халстеда читайте в статье "Halstead complexity measures".
Если принять, что на один оператор приходится два операнда, то график функции HV будет приблизительно, как на рисунке 13 "График и функция сложности Халстеда".
 Рис.13 "График и функция сложности Халстеда"
По оси Y смотрим значение HV, а по оси X выбираем количество операторов. Максимальному значению HV=1000 соответствует 45 операторов, и соответственно около 90 операндов (~ два операнда на один оператор).
Для увеличения MI до 65 и выше надо уменьшать HV, то есть количество операторов и операндов. В коде (см. пример на рисунке 14 "Пример сложных и простых вычислений") можно множество простых операций объединить в одну сложную. Это как в начальной школе по арифметике при имеющемся решении задачи в три-четыре действия выполнить расчёт одним действием.
 Рис.14 "Пример сложных и простых вычислений"
На скриншоте из ClearSQL (см. Рис.15 "Пример упрощения кода по HV, MI") показана разница в значениях HV для сложной "hv_1" и простой "hv_2" подпрограмм.
 Рис.15 "Пример упрощения кода по HV, MI"
Уменьшая количество операторов и операндов в коде снижается сложность Халстеда (HV), и как следствие увеличивается (улучшается) индекс ремонтопригодности (MI).

Четвёртый шаг по улучшению MI – снижение цикломатической сложности.
Томас Дж.Маккейб вывел формулу цикломатической сложности юнита как разность рёбер (edges) и узлов (junctions) с добавлением удвоенного количества компонент связности (coherences):
CC = EdgesJunctions + 2*Coherences
Максимальное значение величины Маккейба утверждено Американским Национальным Институтом Стандартов и Технологий (NIST), равно 10, но последнее время расширяют до 15. Нам тестировщикам это значение говорит о необходимом количестве юнит-тестов. Более подробно о цикломатической сложности читайте в статье "Cyclomatic complexity". Цикломатическая сложность снижает индекс ремонтопригодности максимально на 2-3 пункта, поэтому её рассматриваем в последнюю очередь. График (см. Рис.16 "График и формула цикломатической сложности в рамках MI") показывает часть "0.23 * CC" из формулы MI.
 
 Рис.16 "График и формула цикломатической сложности в рамках MI"
По оси X берём целочисленное значение Cyclomatic Complexity (max=10 or 15), по оси Y видим объём снижения (коэффициент – отрицательная величина "-0.23") MI.
Для улучшения MI нужно уменьшать CC, то есть "выпрямлять" ход программы. Но учтите, что иногда сложные условия (композиция нескольких AND и OR) рассчитывается как одно, то есть уменьшается количество узлов и рёбер, следовательно и само значение CC будет меньше.
Рис.17 "Пример кода цикломатической сложности"
В примере (см. Рис.17 "Пример кода цикломатической сложности") процедура threeinone имеет одно сложное условие (CC=4 или CC=2), а процедура oneinthree – три простых условия (СС=4 всегда).

Итак, для оценки качества кода достаточно вычислить только одну величину – Maintainability Index. В слабом юните исправления следует применять по очереди к комментариям кода, количеству строк, операторов и операндов, узлов и связей хода программы. Элементарных знаний математического анализа и школьного курса информатики достаточно специалисту, решившему тестировать код на любом языке программирования, при этом не углубляясь в синтаксис языка.

Полезные ссылки:
* Качественный анализ программного модуля на основе метрик кода
* Don M. Coleman, Dan Ash, Bruce Lowther, Paul W. Oman. Using Metrics to Evaluate Software System Maintainability. IEEE Computer 27(8), 1994, pp. 44-49.
* Paul Omand and Jack Hagemeister. “Metrics for assessing a software system’s maintainability”. Proceedings International Conference on Software Mainatenance (ICSM), 1992, pp 337-344.
* Paul W. Oman, Jack R. Hagemeister: Construction and testing of polynomials predicting software maintainability. Journal of Systems and Software 24(3), 1994, pp. 251-266.
* The Maintainability Index was introduced at the International Conference on Software Maintenance in 1992
* To date, MI is included in Visual Studio (since 2007), in the recent (2012) JSComplexity and Radon metrics reporters for Javascript and Python, and in older metric tool suites such as verifysoft.
* Think Twice Before Using the Maintainability Index
* P. Oman
* J. Hagemeister


понедельник, 18 июня 2018 г.

Easy "white-box" testing

(Смотрите запись https://vimeo.com/226001966  или читайте текст ниже)

Расскажу о лёгкости тестирования "белым ящиком".
Многие уверены, что проверкой кода должен и может заниматься только высокий профессионал, имеющий опыт написания сложных программ и досконально знающий язык программирования. Но вскоре вы поймёте, что эту работу вполне можно дать вчерашнему школьнику со знаниями Информатики и Мат-Анализа.
Надеюсь, вам известно, что основными причинами серьёзных багов являются элементарные опечатки, недоправки копи-пастов и даже отсутствие кода, поэтому предлагаю проводить тестирование «белого ящика» при помощи утилит аудиторов кода:
* даже юниоры убедятся, что проверка сорсника – это не сложно;
* определим полезные визуализаторы и метрики кода;
* в процессе будут подсказки по выбору и использованию утилит.

Неколько примечаний:
- примеры кода написаны на языке PL/SQL Oracle;
- Все умозаключения по применению основаны на собственном опыте;
- Дабы избежать маркетинговых проблем и не поощрять вашу лень при интернет-поиске, никаких конкретных названий продуктов упомянуто не будет. А также советов, как у программиста взять код для теста, это «интимный» вопрос. Даже профи-аудитору код дают после утряски юридических вопросов. Предположим, что сорсник хотя бы на чтение уже в нашем распоряжении;
- Под юнитом/сорсником/подпрограммой/кодом будем иметь ввиду обычный текстовый файл с листингом программы.


Как работают утилиты, которыми пользуются аудиторы кода:
- Сначала Парсер разбивает текст на строки: значимые (сами команды) и вспомогательные (комментарии, пустые строки);
- Потом Лексер по значимым строкам определяет структуру кода: подпрограммы, команды, параметры и тому подобное;
- Визуализатор генерит диаграммы;
- Анализатор высчитывает метрики кода и по этим данным формирует предупреждения о нарушенных правилах кодирования. Списком таких «нарушений» удобно пользоваться при проведении code review, но не всегда утилиты статического анализа имеют подробные расшифровки и рекомендации по устранению ошибок. Поэтому при подборе утилит обращайте внимание на то, есть ли возможность создать свои правила проверки кода и устанавливать иные лимиты на метрики.


Приведу несколько примеров помощи тестировщику от визуализаторов кода.
Самый простой визуализатор, как ни странно, - комментарии. Их игнорируют программисты, оправдываясь правильно-названными компонентами кода, хотя, не все считают обязательным удалять закомментированные строки кода. А поскольку они не являются полезными комментами, то от них надо избавляться, благо есть система контроля версий. При наличии полезных комментов не так опасно потерять СКВ или баг-трекинговую систему (историю задачи можно восстановить по комментариям).
Если к правильным комментариям добавить специальные теги, то получится документор кода или псевдокод. Когда же чистая выборка документора совпадает с текстом аналитика хотя бы по логичности распределения команд в коде, тестировщик может автоматически закрывать чек-лист про покрытие кодом спецификации задачи. А поскольку некоторые утилиты по комментам псевдокода строят блок-схемы, то сравнение с UML диаграммой аналитика даст объём тех-задания, не покрытого кодом, моментально.
Ясное дело, наличие комментов зависит только от программиста, который не очень-то любит писать обычные тексты, но его можно легко уговорить на ведение комментов, если составлять их как план подпрограммы из текста аналитика, а потом к ним дописывать код. Они помогут следующему кодеру разобраться в программе.
При тестрировании через комментарии, юниору не нужны знания синтаксиса языка, и даже более того – по ним можно изучать программирование.
К слову сказать, крупные компании ведут комментарии кода в обязательном порядке и по своим правилам/шаблонам. Когда же StartUp-у захочется сертифицироваться, то код уже придётся документировать.


Вторая группа визуализаторов, полезных тестировщику, показывает ход программы. Это: блок-схемы, Flowchart, UML диаграммы по готовому листингу.
Мощнейшая утилита из портфеля аудитора! По нарисованному коду, даже без знаний синтаксиса языка, сразу видна масса багов или тем на рефакторинг:
- количество блоков всегда можно подсчитать, и в некоторых утилитах выставить лимит. Если диаграмма большая, то сорсник длинный. А «лапша» всегда была поводом для оптимизации кода;
- находите дубликаты блоков через поиск текста в блоках и подсветку путей, чтобы проверить их на проблемы после копи-паста (недоредактированный код), либо оформить внутреннюю задачу для рефакторинга по выносу повторений в отдельную функцию (повторяющиеся блоки - причина будущих опечаток и недоправок, а унифицированные функции ускоряют правки и переделки);
- сворачиваемость блоков и подсветка определённых путей ("Да", "Нет", "Исключение") более чётко покажут недостаточно обработанные условия и отсутствие кода. А когда фича не дописана, то тестировщику нет смысла тратить время на проверку пустот (сразу возвращайте на доработку);
- мёртвый код ищется два месяца «чёрным ящиком», а при использовании flowchart определяется за пару минут путём сравнения с диаграммой или текстом от аналитика;
- кликабельность из блоков в строки кода помогает обнаружить замедления, которые бывают от наличия комментариев или обращений к базе внутри цикла (обычно в схеме flowchart не показывается текст комментариев, поэтому их наличие придётся выявлять в самом коде, а визуализацию циклов легче определить по диаграмме);
- глазастые заметят в примере переменные без присвоенного значения или неочищенные в конце (проблем от некорректного обращения с переменными множество - от переполнения буфера и до некорректного расчёта и передачи в другие модули).
Утилиту для построения блок-схем чаще других можно найти в среде разработки программиста. Также много аналогов в свободном доступе.


Третья группа визуализаторов – демонстрирует вызовы одних подпрограмм другими и показывает связи объектов данных с кодом. Их называют обычно Call Tree, References&Dependencies диаграммы (направления стрелок показывают вызовы объектов) и CRUD матрица (Create/Read/Update/Delete операции над данными из подпрограмм).
Сорсники и таблицы всего проекта попадают без повторений в диаграмму. Поэтому простым поиском по имени выявляйте лишние и недостающие обращения к объектам. Например, в диаграмме о кадрах может быть лишней процедура "tech_proc_2", а в матрице бухгалтерии или финансового отдела часто можно обнаружить нехватку процедур или таблиц с ордерами прихода/расхода (если существует корпаративные стандарты наименований объектов).
Для генерации диаграмм и матриц берите чистый исходный код, не прошедший обфускацию или компиляцию, потому что замена имён не даст нужного результата.
Пользуйтесь детализацией связей, подсветкой вызовов и сменой уровней связей при поиске зацикленных процедур (в примере процедура "tech_proc_2" должна быть проверена на все вызовы процедурами "emp_proc_1" и "emp_proc_3", так как при определённых условиях вполне может случится зацикливание), а также шагов, приводящих к мутации данных (в примере показан триггер "emp_trg" и процедура "emp_proc_3", влияющие на данные в таблице "emp_tbl", а поскольку процедура через несколько шагов может быть выполнена из триггера, то вполне вероятно совместное обращение к одним и тем же данным).
Если формат выходной диаграммы SVG, XML или VDX, то более вероятно воспользоваться всеми полезностями (поиск по диаграмме, подсветка путей, кликабельность из диаграммы в код, сворачиваемость блоков диаграмм).


А теперь немного о метриках кода, то есть о качестве в цифрах. Если визуализаторы более полезны на начальном этапе разработки, то на метрики кода влияют каждые изменения подпрограммы. К сожалению, идеального кода не существует и добиться невозможно, как и КПД-100%. Чем же мы, тестировщики, в состоянии помочь кодеру?
Самая простая метрика - количество строк в сорснике до компиляции. С этим файлом работает программист в среде разработки – правит, отлаживает, компилирует. А большой объём файла совсем не на руку ни компилятору, ни системе контроля версий, ни тем более среде разработки.
Хороший редактор раскрашивает синтаксис, показывает начало-конец цикла и иными способами помогает кодеру, а все эти примочки требуют ресурсов. В один прекрасный день вчерашний код не откроется в среде разработки – и конец всем фиксам.
В СКВ дешевле хранить некоторые маленькие файлы, нежели один и тот же большой дописывать, потому что место на сервере слишком быстро закончится.
Слияние изменений (merge) выполнять в СКВ на мелких отдельных файлах проще, и конфликты случаются реже - как в коде, так и между сотрудниками.
Вторая простая для подсчёта величина – количество параметров (и особенно глобальных), которое рекомендуют не более 7 (5 входящих, 2 на выход). Цифра пришла из чистой психологии - единовременно человек запоминает не более 7 объектов. Для работы с бОльшим количеством параметров придётся взводить хинты-подсказки, требующие ресурсов и времени.


С 70-х годов XX века благодаря T.J.McCabe, Maurice Halstead, и чуть позже Don M Coleman и Paul Oman с Jack Hagemeister стало возможным измерить качество кода и спрогнозировать его развитие. Величины, выведенные этими людьми, стали носить их имена.
Thomas J.McCabe вывел формулу цикломатической сложности юнита как разность рёбер и узлов с добавлением удвоенного количества компонент связности.
При грубой оценке граф цикломатической сложности совпадает с диаграммой flowchart, где стрелки выполняют роль рёбер (на рисунке - зелёные), овалы и многоугольники считаются узлами (на рисунке - красные звёздочки), а целый законченный блок – компонент связности (на рисунке - серым цветом ограничены два графа для примеров кода).
Не для всех случаев граф цикломатической сложности идентичен flowchart, потому что если используется сложное условие (через OR/AND), то каждое из них может считаться узлом (в примере граф для процедуры "threeinone" станет идентичен графу для процедуры "oneinthree").
Максимальное значение величины McCabe утверждено Американским Национальным Институтом Стандартов и Технологий (NAST), равно 10, но последнее время расширяют до 15.
Нам тестировщикам это значение говорит о необходимом количестве юнит-тестов.


Все величины Мариуса Халстеда рассчитываются по операторам и операндам, и поэтому утилита должна быть версионно-зависимой для языка программирования, а лучше встроенной в среду разработки.
Что есть операторы и операнды помним, да? В выражении «a+b»: "+" – оператор, "a" и "b" – операнды.
Не удивляйтесь, если подсчитанные строки в листинге не совпадают с длиной программы по Халстеду, потому что длина программы – это сумма всех операторов и всех операндов.
Словарь юнита он определил как сумму уникальных операторов и операндов.
А помножив длину программы на логарифм словаря, Халстед получил объём подпрограммы (или ещё эту величину называют "сложностью Халстеда"). Она максимально не должна превышать 1000 (лимит не утверждён никаким стандартом).
Если же исследовать функцию сложности, приняв уникальными все операнды и операторы, то в самом сложном юните должно быть примерно – 45 операторов и 90 операндов, как это видно на графике. Фактически - это невообразимая программка.


Maintainability Index перевожу для себя не как ремонтопригодность, а как «важность и устойчивость», потому что он  прогнозирует развитие подпрограммы  (сколько ещё можно править или расширять юнит).
Индекс значимости подпрограммы, выведенный Доном Колеманом и Паулем Оманом, дополненный Джеком Хейгмейстером, зависит от всех составляющих листинг: операторов и операндов, блоков и их связей, значимых  и вспомогательных строк кода.
Предел индекса никакими институтами пока не утверждён, но для стабильно-устойчивых подпрограмм рекомендуется писать код так, чтобы индекс был более 85. Когда индекс падает ниже 65, то ваш юнит совсем плох.
Если поисследовать функцию, рассчитывающую индекс, то при максимальных величинах Халстеда, МакКейба и комментов в одном юните - не стоит делать более 1500 строк. Это видно на среднем графике.
Формула имеет две модели: с учётом комментариев (обе строки формулы:" MI = 171 - 5.2*ln(HV) - 0.23*CC - 16.2*ln(LOC) + 50*sin(sqrt(2.4*COM)) ") и без учёта комментариев (только первая строка: " MI = 171 - 5.2*ln(HV) - 0.23*CC - 16.2*ln(LOC) "). Поскольку величина комментариев зависит от функции синуса, то при отношении объёма комментов к строкам кода в процентах, синусоида сложно извивается на отрезке от 0 до 100 (левый график показывает несколько вариантов подбора - максимумы). Если же брать долевое исчисление комментов - от 0 до 1 (правый график), то 3/10 комментированных строк дадут максимум полезности. Юнит должен быть легко-читаемым. И даже цифры подтверждают, что нет смысла экономить за счёт комментариев: "+50 всегда лучше трёх минусов для стремящихся к 85 и выше".


В таблице-шпаргалке перечислены формулы для исчисления качества кода. Особым шрифтом выделены две формулы для прогноза количества багов (вывел Халстед).


При использовании аудита кода, как части среды разработки, никаких дополнительных вложений от вас не потребуется: ни в обучение, ни в покупку, ни в дальнейшую поддержку утилит, как это приходится делать с юнит-тестами.
Если результаты юнит-тестов дают понимание о том, «каков код здесь и сейчас», то аудит говорит о перспективах развития подпрограммы.
Code Audit - для комплексного тестирования всего проекта, Unit testing – для точечного.
Одно другим подменить невозможно, но совместное использование только улучшит качество конечного продукта.
Мечтающие взлететь в bug-bounty, воспользуйтесь тем, что завалялось у вашего программиста, а именно утилитами аудиторов кода, вшитые в среду разработки.

Делайте аудит кода, находите сразу причины сложных багов, давайте подсказки программистам, где именно и что рефакторить для улучшения качества кода. Или научите их делать аудит кода самостоятельно, регулярно, автоматически через шедулеры, и в тестировщиках отпадёт необходимость.