Thursday, May 27, 2010

Метрики кода

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

К настоящему времени разработано множество метрик, которые позволяют оценить код с самых разных сторон. Например:
  • по размеру – различные версии метрики «Число строк кода», «Число методов в классе», «Число классов в системе» и т.д.
  • по сложности - оценка архитектуры и алгоритмов программы (цикломатическая сложность, связность кода, глубина наследования и др.).
  • по сложности поддержки - показывают трудоемкость процесса поддержки и развития кода (метрика Холстеда).
Метрик много, и я не буду рассматривать здесь их все. Остановлюсь только на наиболее, на мой взгляд, полезных из них.

Сплоченность (cohesion) – показывает насколько тесно связана («сфокусирована») функциональность модуля. Как правило, для оценки сплоченности используются не точные числовые значения, а относительные показатели «сильная» (“high”) и «слабая» (“low”). Модули, обладающие сильной сплоченностью более предпочтительны, т.к. сильная сплоченность связана со следующими положительными качествами кода: прочность, надежность, простота повторного использования. В то же время слабая сплоченность говорит о том, что код наверняка трудно тестировать, поддерживать и повторно использовать.

Связность (coupling) – показывает насколько сильно один модуль зависит от других. Под зависимостью здесь подразумевается использование в одном модуле, типов определенных в другом модуле, для описания параметров методов, локальных переменных, возвращаемых значений и т.д. Слабая связность является признаком хорошего дизайна, т.к. означает простоту повторного использования кода. Модули с сильной связностью наоборот демонстрируют все признаки плохой архитектуры: жесткость, хрупкость, неподвижность и вязкость.

Пример расчета связности для классов.

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

Число строк кода (Lines of Code) – общий смысл того что показывает эта метрика понятен без всяких комментариев. Однако, существует много вариаций на тему. Вот, например, Visual Studio считает только исполняемые строки и основывается при этом на IL, а не на исходном коде. Для этой метрики нет рекомендуемых значений, которых обязательно нужно придерживаться. Однако если для метода или класса число строк слишком велико, то, возможно, они взвалили на себя слишком много, и их стоит отрефакторить. Всем известное правило: «простота – залог успеха», работает и для кода. Правда, понимать его нужно следующим образом: меньше кода значит меньше ошибок и проще поддержка.
Пример расчета числа строк кода.

Цикломатическая сложность (Cyclomatic сomplexity) – показывает сложность структуры кода. Вычисляется путем определения числа уникальных путей выполнения программы (подсчитывается количество операторов ветвления и циклов). Также как и с числом строк кода здесь, чем проще, тем лучше. Чем меньше путей выполнения, тем меньше надо тестов чтобы их покрыть, тем проще поддержка.
Пример расчета цикломатической сложности.

Глубина наследования (Depth of Inheritance) – Показывает сколько классов цепочке наследования отделяют данный класс от корня иерархии. Более предпочтительными являются не глубокие, а широкие иерархии типов, т.к. наследование существенно повышает связность в системе, а чем это плохо мы только что разобрали.
Пример расчета глубины наследования.

Инструменты анализа кода
Visual Studio 2008. Анализ метрик имеется только в самой дорогой Team edition. Позволяет вычислять всего 5 основных метрик и отслеживать их в режиме реального времени.

Visual Studio 2010. Как и в предыдущей версии студии, анализ метрик есть только в самых дорогих редакциях Premium и Ultimate. Количество доступных метрик, по сравнению с предыдущей версией, не изменилось.

NDepend. На сегодняшний день, наверное самый функциональный инструмент. Умеет анализировать 86 метрик. Полностью интегрируется с Visual Studio.

Reflector.CodeMetrics. Бесплатное дополнение к Reflector’у. Позволяет считать некоторые метрики (например, цикломатическую сложность) и сохранять результаты в файл. Не особо удобно, но лучше чем ничего.

FxCop – отличная утилита для статического анализа кода. Про метрики ничего не знает, но имеет API для плагинов. И некоторые умельцы пишут плагины для метрик. Вот, например плагин для цикломатической сложности.

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

Ссылки:
1.       Software metric
2.       Cohesion
3.       Coupling

1 comment:

  1. Хочу обратить ваше внимание на инструмент статического анализа Sonar http://www.sonarsource.org/
    Он был написан изначально для Java, но с помощью плагинов легко адаптируется с другими платформами.
    В нём на порядок больше метрик, отличная визуализация проблем, и, что самое главное, он хранит историю метрик и позволяет отслеживать «технический долг».

    ReplyDelete