Формирование метрик кода программной системы

Звездин С. В.

Формирование метрик кода программной системы

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

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

Цели и задачи измерений

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

Первая проблема, проблема оценки объема системы, возникает при необходимости сравнения программной системы с другими подобными ей системами: "какая из систем больше?".

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

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

Правильная система метрик может стать незаменимым помощником при решении обеих проблем. Она позволяет ответить на такие вопросы: насколько система объемна (размер)? насколько система связна (одна из метрик качества)? насколько систему трудно поддерживать и развивать? каковы наиболее критичные точки в программной системе?

Рассмотрим подходы решения этих вопросов.

Метрики кода

Любая система метрик программного обеспечения строится на элементарном наборе метрик - базисе. Такие элементарные метрики начали появляться еще в 70-е годы, когда компьютеры постепенно начали проникать в оборонную промышленность. Это время можно ознаменовать как эпоху решения все более и более сложных математических задач с применением ЭВМ. При решении подобных задач, сложность алгоритмов непременно росла. С ростом сложности кода стало расти и общее количество ошибок в программе. В связи с этим появилось направление, которое начало заниматься анализом существующего кода. Так возникли метрики. Если говорить об объектно-ориентированной парадигме, то элементарными метриками кода могут быть такие метрики, как общее количество строк кода (включая комментарии, пустые строки и т. д.), общее количество классов, общее количество методов в классе и др.

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

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

Классификации метрик кода

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

1. Размер, объем программной системы. Такие метрики обычно оценивают объем программной системы для сравнения с другими системами.

2.Сложность программной системы. Эти метрики обычно характеризуют сложность дизайна и кода программной системы. Отрицательные показатели метрик данной группы обычно говорят о том. что нужно пересмотреть отдельные части программной системы.

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

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

Метрика "Количество строк исходного кода" (lines of code, LOC) определяет общее количество строк исходного кода программной системы. Вычисляется как количество строк эффективного кода программной системы. При вычислении данной метрики не учитываются комментарии и сигнатуры пространств имен (namespace), классов, методов, свойств. Кроме того, не учитываются пустые строки и инструкции импорта пространств имен. В дополнение к этим условиям наиболее оптимальным представляется подход, при котором перед подсчетом метрики производится форматирование исходного кода по заданным правилам. К таким правилам могут относиться правила оформления блоков условного

перехода, ветвлений, циклов. Применение таких правил перед подсчетом метрик позволяет избежать искажения значения метрики в зависимости от стиля написания кода.

Результатом вычисления данной метрики является сырая оценка объема системы. Тем не менее эта оценка не может использоваться как объективное значение объема системы в силу того, что один и тот же функционал системы может быть реализован множеством способов, при которых количество строк кода, а следовательно, и метрика LOC будут сильно отличаться друг от друга. Однако несмотря на данное ограничение метрика LOC может использоваться как базисная совместно с другими метриками кода для получения объективной оценки объема системы и других показателей.

Метрика "Количество классов в пространстве имен" (classes in namespace. CTN) определяет структурную декомпозицию системы с точки зрения распределения классов по пространствам имен. Также CIN определяет объем пространств имен, что может характеризовать программную систему с точки зрения декомпозиции функциональных подсистем. При вычислении данной метрики берутся в расчет классы со всеми модификаторами видимости (public, private и др.), структуры и перечисления. Метрика может вычисляться в двух режимах - на основании анализа исходного кода системы или на основании результирующего выходного исполняемого файла. Результаты вычислений в данных случаях могут отличаться. Такой эффект может наблюдаться из-за того, что некоторые среды разработки могут автоматически генерировать классы в момент сборки системы на основании данных от различных декларативных языков программирования. Примером такой среды может быть Visual Studio 2005/2008. При разработке веб-приложений на базе ASP.NET в рамках Visual Studio создаются декларативные описания веб-страниц, которые при компиляции приложения трансформируются в автогенери-руемые классы. Однако наиболее правильным представляется подход, при котором такие классы не учитываются, так как данный код не разрабатывается программистом, а значения метрики могут изменяться в зависимости от реализации компилятора. При этом в момент анализа метрики могут появляться лишние шумы, которые препятствуют объективному пониманию системы.

Результатом вычисления данной метрики, как и метрики LOC является сырая оценка объема системы и структурной декомпозиции функцио-

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

Метрика "Количество методов в классе"

(methods of class. МОС) определяет степень функциональной нагрузки класса. При вычислении метрики подсчитывают количество операций (методов) со всеми модификаторами видимости (public, private и др.). Такая оценка дает понимание того, насколько объект наполнен операциями. Слишком высокие значения метрики сигнализируют о том, что класс чересчур большой и необходимо произвести структурную декомпозицию. При этом одним из способов трансформации кода могут выступать фабрики классов и другие инстанциирующие шаблоны проектирования для обеспечения функциональной целостности маленьких классов.

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

Метрика «Цикломатическая сложность» (cyclomatic complexity. СС) позволяет определить степень сложности любой структурной единицы программной системы (метод, класс, сборка, проект). На основании значения данной метрики можно выбрать участки кода, наиболее подверженные риску возникновения ошибок. Метрику полезно анализировать как на ранних стадиях проекта, так и в момент, когда проект достаточно зрелый. Метрика СС основывается на оценке сложности потока управления программы (control flow graph) и вычисляется на основе ориентированного графа, где вычислительные операторы или выражения представляются в виде узлов, а передача

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

С = е-п +р,

где е—число ребер; п - число узлов; р - число соединенных компонент графа управляющей логики.

Для общего понимания семантики данной метрики ее можно рассматривать как количество ветвлений, которые может проходить программа, увеличенное на единицу. Так. например, в программе без ветвлений значение метрики СС равно единице; в программе с одним условным оператором - двум, и т. д.

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

Метрика "Связность классов". Метрика связность классов или объектов (coupling between objects, СВО) позволяет определить степень связности системы. Повышенные значения данной метрики могут говорить о чрезмерной связности системы, которая появляется из-за слабой модульной инкапсуляции. Такое свойство программной системы может привести к трудностям при повторном использовании кода. Данная метрика представляется практическим показателем, на который можно ориентироваться при построении и переработке архитектуры программной системы. Обычно связность классов - один из показателей, за который борются архитекторы программного обеспечения при разработке архитектуры. Основные способы уменьшения связности объектов - более строгая инкапсуляция логики в объекты, пересмотрение работы алгоритмов с концептуальной точки зрения и структурная декомпозиция. При этом для создания объектов в таком случае появляются фабрики объектов, которые позволяют избежать лишней связности в момент создания экземпляров классов.

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

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

Метрика "Количество вызовов oпepaции', (number of operations calls, NOC) позволяет определить количественный показатель связности системы в виде вызовов методов. Метрика подсчитывает только вызовы тех операций, которые определены пользователем. Кроме того, вызов одной и той же операции в рамках одного метода увеличивает значение метрики лишь на единицу. Так, если метод ml() вызывает метод т( ) три раза в ходе своего выполнения, то значение метрики NOC будет равно единице; если же метод т( ) вызывается по одному разу из методов ml(), m2( ) и m3( ), то значение метрики будет равняться трем.

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

Таким образом, прямой результат вычисления метрики NOC имеет сомнительное практическое значение для оценки системы. Использование сырых показателей этой метрики может ввести в заблуждение и обусловить неверное решение. Однако данная метрика в совокупности с суммарным значением метрики "Количество методов в классе (МОС)" может дать объективную оценку связности системы. Такой показатель наравне с показателем цикломатической сложности может быть очень полезен для оценки системы с точки зрения ее дальнейшего развития и обслуживания.

Метрика "Глубина нacлeлoвaния,, Метрика "Средняя глубина наследования" (average hierarchy height, АНН) вычисляется как среднее значение глубины наследования для всех классов системы, определенных пользователем. При этом не учитываются классы, стоящие не на самом нижнем уровне иерархии наследования. Вычисление данной метрики позволяет оценить сложность системы несколько в ином разрезе. Высокие значения метрики АНН могут сигнализировать о том, что архитекторы программной

системы слишком увлеклись ООП-приемами, которые могут негативно сказываться на ее дальнейшем развитии.

Несмотря на то что наследование как один из приемов ООП - нужная вешь. оно существенно повышает связность системы, при этом такая связность может быть не полностью отражена остальными метрикам, оценивающими систему с точки зрения связности. Часто при построении программного кода можно избежать применения наследования и заменить его равноценными приемами. Например, вместо этого можно использовать такие подходы, как Dependency Injection и 1оС-контейнеры. При получении равнозначной реализации применение указанных паттернов может снизить реальный показатель связности системы, а значит снизить риски, связанные с ее сопровождением. Этот аспект разработки программной системы позволяет контролировать метрика АНН.

Результат вычисления данной метрики, как правило, используется в сыром виде в практических задачах построения архитектуры и рефак-торинга. Полученные показатели метрики также можно применить в более сложных комплексных метриках. Однако использование таких метрик на базе АНН иногда затруднительно, так как они слишком сложны для быстрого анализа. Кроме того, наряду с данной метрикой иногда вычисляют метрику среднего числа классов-наследников (average number of derived classes. ANDC). Однако эта метрика дает оценку с той же позиции, что и АНН. лишь с незначительным отклонением, поэтому для вычислений в первом приближении ее можно опустить.

Связанная система метрик. Как видно из описания большинства метрик, они носят субъективный характер и в определенных условиях могут дезинформировать аналитика о количественном показателе того или иного аспекта программной системы. Это стало основной причиной резкого спада популяризации метрик.

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

В данной статье рассматривается система метрик, которая объективно отражает объем различных частей системы, а также поверхностно затрагивает аспект сложности системы.

Для того чтобы построить связанную систему метрик, расположим метрики объема сверху вниз (см. рис. 1). Кроме того, для оценки сложности к этой системе добавляются метрики сложности.

АНН 0.12

СВО 0,42

Ж

т

47.81 245,54

мое

28.27

1242

LOC

0,15

35123

сс

5498

Рис. I. Связанная система метрик

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

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

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

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

СПИСОК ЛИТЕРАТУРЫ

1. Alpert S. R., Brown K„ Woolf B.. The Design Patterns Smalltalk Companion. Addison Wesley. 1998.

2. Briand L. C., Daly J., Wust J. A Unified Framework for Cohesion Measurement in Object-Oriented Systems. Empirical Software Engineering // International Journal. 1998. Vol3,№2.