Разработка показателей индекса ремонтопригодности

Разработка метрик индекса поддерживаемости для приложений на языке COBOL

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

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

Получите полную картину метрик COBOL.

SMART TS XL ранжирует каждую программу на COBOL по сложности, количеству зависимостей и глубине зависимостей JCL одновременно.

Подробнее

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

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

Почему измерение удобства сопровождения кода важнее для COBOL, чем для современных языков программирования.

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

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

Пробел в знаниях. Большая часть кода COBOL содержит бизнес-логику, которая никогда не была формально задокументирована. Пакетные задания, написанные десятилетия назад, содержат правила, которые никто не помнит. Разработчики, которые могут свободно читать код и точно оценивать стоимость изменений, уходят на пенсию. Оставшиеся разработчики лишь частично знакомы с отдельными частями портфеля проектов. Без количественных показателей оценка стоимости изменений полностью зависит от того, какого разработчика вы спросите, а изменчивость этих оценок достаточно высока, чтобы сделать планирование проекта ненадежным.

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

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

Формула MI и ее компоненты, специфичные для COBOL.

Наиболее часто используемая формула для расчета индекса ремонтопригодности:

MI = 171 - 5.2 × ln(Halstead Volume) - 0.23 × (Cyclomatic Complexity) - 16.2 × ln(Lines of Code)

Ограниченный вариант шкалы, используемый большинством коммерческих инструментов Microsoft, отображает это в виде шкалы от 0 до 100:

MI (bounded) = max(0, (171 - 5.2 × ln(HV) - 0.23 × CC - 16.2 × ln(LOC)) × 100 / 171)

Каждый компонент имеет свои специфические особенности, связанные с COBOL.

Строки кода в COBOL

Исходные файлы COBOL содержат четыре раздела: IDENTIFICATION, ENVIRONMENT, DATA и PROCEDURE. Раздел IDENTIFICATION идентифицирует программу. Раздел ENVIRONMENT описывает среду выполнения. Раздел DATA определяет структуры данных. Только раздел PROCEDURE содержит исполняемые операторы.

Вопрос измерения: следует ли учитывать все строки кода (LOC) во всех четырех разделах или только операторы PROCEDURE DIVISION?

В целях управления информацией подсчет всех строк (включая объявления данных) значительно увеличивает количество строк кода без соответствующего увеличения сложности выполнения. Программа на COBOL с 400 строками DATA DIVISION, определяющими структуру записей, и 100 строками PROCEDURE DIVISION имеет иные характеристики сопровождения, чем программа со 100 строками DATA DIVISION и 400 строками PROCEDURE DIVISION, но в исходном виде количество строк кода обрабатывает их одинаково.

Рекомендация: для расчета MI в COBOL используйте количество операторов PROCEDURE DIVISION (исключая пустые строки, строки комментариев и заголовки разделов/абзацев), а не общее количество строк исходного кода. Это позволит получить значения LOC, более точно соответствующие сложности исполняемого файла.

Проблема с членами COPY: операторы COPY включают внешние члены исходного кода на этапе компиляции. Оператор COPY, который разворачивается в 200 строк определений данных, добавляет одну строку в исходный файл, но 200 строк в скомпилированную программу. Некоторые инструменты подсчитывают логические строки (после развертывания COPY); другие подсчитывают физические строки исходного кода. Разница может составлять порядок величины для программ с интенсивным использованием COPY.

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

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

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

Конструкция COBOLВлияние цикломатической сложности
IF ... END-IF+1 за IF
IF ... ELSE ... END-IF+1 за каждое условие IF (ELSE не добавляет другой путь)
EVALUATE ... WHEN+1 за каждый пункт "КОГДА"
PERFORM UNTIL condition+1 за условие UNIL
PERFORM VARYING ... WITH TEST BEFORE/AFTER+1 за РАЗЛИЧНЫЙ
AT END пункт о ЧТЕНИИ+1
ON EXCEPTION / NOT ON EXCEPTION+1 за каждый обработчик исключений
ON OVERFLOW / NOT ON OVERFLOW+1 за каждый обработчик переполнения
ON SIZE ERROR+1 за каждый размер обработчика ошибок

Слепое пятно 88-го уровня: имена условий 88-го уровня в COBOL создают логические условия, которые появляются в операторах IF и EVALUATE, но определены в разделе DATA. Программа с двадцатью условиями 88-го уровня, каждое из которых используется в нескольких структурах принятия решений, имеет значительно большую поведенческую сложность, чем предполагает количество операторов в разделе PROCEDURE. Цикломатическая сложность подсчитывает точки принятия решений, но не может отразить семантические связи между именами 88-го уровня и логикой, которая их проверяет.

ВЫПОЛНИТЬ С ПОМОЩЬЮ неявной сложности: PERFORM SECTION-A THRU SECTION-Z Выполняется обработка всех абзацев между РАЗДЕЛОМ A и РАЗДЕЛОМ Z. Количество абзацев и структуры принятия решений внутри них являются частью эффективной сложности оператора PERFORM, но CC, рассчитанный на уровне оператора, обрабатывает PERFORM THRU как единый путь, независимо от того, что находится между ними.

Том Халстеда по COBOL

Объем Халстеда — это показатель размера и сложности программы, основанный на количестве операторов и операндов. В COBOL:

Операторы — это глаголы и ключевые слова COBOL: MOVE, ADD, SUBTRACT, MULTIPLY, DIVIDE, COMPUTE, IF, PERFORM, READ, WRITE, OPEN, CLOSE, CALL, GO TO, EVALUATE, WHEN и так далее.

Операнды — это имена данных, литералы и фигуративные константы: элементы данных, определенные в разделе DATA DIVISION, числовые и строковые литералы, а также фигуративные константы COBOL (ПРОБЕЛЫ, НУЛИ, ВЫСОКИЕ ЗНАЧЕНИЯ, НИЗКИЕ ЗНАЧЕНИЯ).

Фактор многословия: COBOL значительно многословнее современных языков программирования для эквивалентной логики. Выражение Java. total = quantity * unitPrice * (1 - discount) Это одна строка с четырьмя операторами и четырьмя операндами. Эквивалент в COBOL:

кобол

       COMPUTE WS-TOTAL = WS-QUANTITY * WS-UNIT-PRICE
                        * (1 - WS-DISCOUNT)

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

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

В чём заключаются недостатки стандартной системы MI для COBOL: четыре «слепых пятна».

Даже при правильном расчете стандартная формула MI не учитывает четыре аспекта поддерживаемости COBOL, которые оказывают существенное влияние на реальные затраты на изменения.

1. СКОПИРОВАТЬ Соединение элементов

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

Дополнительный показатель: количество зависимостей между членами класса COPY, число уникальных операторов COPY в подразделении данных программы. Для программ с высокой степенью связанности операторов COPY перед внесением каких-либо изменений необходимо провести анализ влияния, чтобы понять, какие другие программы используют те же определения копибука.

2. Фан-ин (вызов по счету)

Подпрограмма COBOL, вызываемая 150 другими программами, представляет собой объект высокого риска для изменений независимо от её показателя MI. Подпрограмму, легко поддерживаемую другими программами (MI = 85) и вызываемую 150 другими программами, сложнее безопасно изменить, чем подпрограмму с низкой степенью поддержки (MI = 45), которая не вызывается ни одной программой. Формула MI не учитывает, насколько широко используется программа.

Дополнительный показатель: Fan-In — количество различных программ, которые вызывают данную программу посредством CALL или динамической диспетчеризации. Fan-in является основным фактором риска изменений для подпрограмм независимо от их внутренней сложности.

3. Глубина зависимостей JCL

Программа на COBOL, вызываемая заданием JCL, имеющим пятнадцать зависимых заданий, которые выполняются после неё и зависят от её результатов, несёт операционный риск, полностью выходящий за рамки MI. Программа с MI = 55, работающая автономно, менее рискованна для модификации, чем программа с MI = 80, находящаяся в центре сложной цепочки зависимостей пакетной обработки.

Дополнительный показатель: глубина зависимостей JCL, глубина цепочки зависимостей в сети заданий JCL. Программы с высокой глубиной зависимостей JCL требуют более широкого охвата тестирования любых изменений, независимо от их внутреннего показателя MI.

4. Инфляция мертвого кода

«Мертвые» абзацы и разделы, COBOL-код, который определен, но никогда не вызывается ни одним путем выполнения, увеличивают количество строк кода и объем Халстеда, не внося вклада в нагрузку на сопровождение работающего кода. Программа с 600 строками мертвого кода и 200 строками работающего кода имеет индекс целевого назначения (MI), который наказывает ее за мертвый код, даже если мертвый код не имеет отношения к стоимости изменений.

Дополнительный показатель: процент неиспользуемого кода, доля операторов PROCEDURE DIVISION, недоступных из любого пути выполнения в производственной среде. Высокий процент неиспользуемого кода указывает на то, что рассчитанные с помощью MI значения LOC и Halstead Volume значительно завышены.

Полный набор метрик COBOL

Ни один отдельный показатель не отражает в полной мере удобство сопровождения кода COBOL. Следующий набор показателей, используемый вместе, дает полную картину:

МетрикаЧто он измеряетПримечание, специфичное для COBOLОсновное использование
Индекс ремонтопригодностиОбщая простота обслуживания (композит)Примените к заявлениям ОТДЕЛА ПРОЦЕДУР; проверьте обработку КОПИЙ.Базовый показатель качества; рейтинг портфеля
Цикломатическая сложностьКоличество независимых путей выполненияВключите в текст пункты: ОЦЕНКА ПРИ ВЫПОЛНЕНИИ, ВЫПОЛНЕНИЕ ДО, В КОНЦЕ, ПРИ ИСКЛЮЧЕНИИ.Изменение трудозатрат по каждой программе; оценка количества тестовых случаев.
Холстед ТомВычислительная нагрузка (операторы + операнды)Ожидайте более высоких значений, чем у аналогичных программ на современных языках программирования.Часть MI; сравнение программ в рамках портфеля COBOL.
СКОПИРОВАТЬ Количество участниковВзаимосвязь зависимостей посредством общих определенийДля программ, в которых участвует более 15 членов COPY, перед внесением каких-либо изменений необходимо провести анализ воздействия.Изменение классификации рисков
Вступление (вызванный)Сколько программ называют эту программу именно так?Основной фактор риска изменений для подпрограммПоследовательность миграции; пороговое значение для авторизации изменений
Мертвый код %Недостижимый процент кодов процедурУвеличьте значение LOC/HV, если оно не исключено; исключите из области применения преобразования.Сокращение масштабов работ при модернизации
Глубина зависимостей JCLГлубина цепочки пакетных заданий на нисходящем этапеНевозможно вычислить только на основе исходного кода COBOL; требуется анализ с помощью JCL.Риск операционных изменений; область тестирования
Вложенная глубина PERFORMМаксимальный уровень вложенности вызовов PERFORMГлубокая вложенность указывает на структурную сложность, не отраженную в CC.Приоритет рефакторинга

Калибровка пороговых значений для COBOL

Стандартные пороговые значения MI получены из кодовых баз современных языков и не применяются напрямую к COBOL. В таблице ниже сравниваются стандартные пороговые значения с эквивалентами, подходящими для COBOL, и объясняется обоснование корректировок.

Диапазон оценкиСтандартная интерпретацияИнтерпретация COBOLобоснование
85-100Легко обслуживаетсяВысокая степень поддерживаемости (стабильность).Лучшие программы на COBOL имеют следующие показатели: чистая структура, подходящий размер.
65-84Умеренно поддерживаемыйДовольно легко обслуживается, проверьте соединение COPY и подключение вентилятора.Стандартный пороговый уровень сохраняется, но дополнительные показатели здесь имеют большее значение.
50-64Плохо, требуется рефакторинг.Маргинальный, оценивать в контекстеМногие хорошо структурированные программы на COBOL получают здесь высокие оценки исключительно за счет многословности; используйте CC и fan-in, чтобы отличить реальные проблемы от синтаксических ошибок.
25-49Очень плохоПлохое состояние, вероятно, высокий уровень CC и/или чрезмерный уровень LOC.Программы в этом диапазоне достоверно указывают на структурные проблемы, а не только на многословность кода COBOL.
0-24Критическая, масштабная рефакторизацияКрайне важный, первоочередной вопрос для устранения недостатков или вывода из эксплуатации.Соответствует стандартной интерпретации.

Основные рекомендации по калибровке: Перед установкой пороговых значений для отдельных программ выполните проверку множественной идентификации (MI) для всего вашего портфеля COBOL. Рассчитайте медиану и межквартильный размах портфеля. Установите пороговое значение «требуемого внимания» на уровне 25-го процентиля вашего собственного портфеля, программ, находящихся в нижнем квартиле вашей конкретной кодовой базы, а не программ, которые получили оценку ниже порогового значения, полученного для программ на Java. Этот подход является самокалибрующимся и учитывает систематический эффект многословности COBOL.

Использование управленческой информации для принятия решений по модернизации

Показатели MI становятся наиболее ценными, когда они помогают принимать конкретные оперативные решения. Вот основные области их применения.

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

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

Решения о разработке или покупке. При оценке целесообразности долгосрочного поддержания программы на COBOL или ее замены на SaaS-решение или современную альтернативу, показатель MI и история затрат на изменения обеспечивают количественную основу для расчета целесообразности разработки или покупки. Программа с MI = 30, модифицированная пятнадцать раз за последние три года, причем каждая модификация занимает значительно больше времени, чем предполагалось, имеет документально подтвержденные затраты на обслуживание, которые можно сравнить со стоимостью замены.

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

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

Как SMART TS XL Устанавливает и отслеживает метрики поддерживаемости COBOL.

Вычисление MI для одной программы на COBOL — задача несложная. Точное вычисление MI для портфеля из тысяч программ, с учетом расширения COPY, выявления мертвого кода и дополнения MI дополнительными метриками, которые она не учитывает, требует автоматизированного анализа в больших масштабах.

SMART TS XLАвтора статический анализ кода Вычисляет полный набор метрик COBOL, описанных в этом руководстве, одновременно по всему портфелю. MI рассчитывается с использованием количества операторов PROCEDURE DIVISION, а не общего количества строк исходного кода, при этом перед анализом выполняется расширение COPY, чтобы гарантировать правильное присвоение атрибутов общим определениям данных. Цикломатическая сложность учитывает предложения EVALUATE WHEN, условия PERFORM UNTIL и ветви обработчиков исключений, а не только операторы IF. Объем Халстеда вычисляется на основе глаголов COBOL и операндов данных в PROCEDURE DIVISION.

Кардинально, SMART TS XL Дополняет MI показателями, которые отсутствуют в основной формуле. сопоставление зависимостей приложения Программа формирует данные о количестве подключений (fan-in values) и количестве вызовов (call-by counts) для каждой программы в портфеле, выявляя программы высокого риска независимо от их оценки MI. Расширение JCL Эта возможность обеспечивает детальный анализ зависимостей JCL для каждой программы, связывая анализ управленческой информации на уровне COBOL с контекстом операционных рисков, который может быть выявлен только с помощью анализа JCL.

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

Функция корпоративного поиска позволяет запрашивать полный набор метрик: находите все программы с MI ниже 40 и fan-in выше 20, отсортированные по глубине зависимостей JCL, а также наиболее приоритетные цели по устранению проблем в портфеле, одним запросом по миллионам строк кода COBOL. Этот доступный для запросов набор метрик является основой для приложений приоритезации обслуживания, последовательности миграции и авторизации изменений, описанных выше.

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

Метрики, соответствующие языку

Индекс поддерживаемости (Maintainability Index, MI) — это действенный и ценный показатель для портфелей COBOL-программ, но только при условии понимания того, как синтаксические характеристики COBOL взаимодействуют с его компонентами. Применение общих пороговых значений к программам COBOL приводит к вводящим в заблуждение результатам. Дополнение MI метриками, которые он не учитывает (например, связь COPY, входящие зависимости, глубина зависимостей JCL, процент мертвого кода), позволяет получить картину, соответствующую тому, с чем разработчики действительно сталкиваются при работе с COBOL-программами.

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