NDepend. 82 метрики кода для .NET-приложенийАвтор: Виктор Деревянко Опубликовано: 23.09.2009 Источник: SoftKey.info С необходимостью оценить качество кода проекта сталкиваются многие разработчики и менеджеры проектов. От качества кода напрямую зависят стабильность работы программы и ее успех на рынке. Грамотно ли написан код проекта? Сложно ли будет его в дальнейшем сопровождать и модифицировать? Не снизилось ли качество кода по сравнению с предыдущим релизом? Менеджер проекта должен быть уверен, что код написан качественно и затраты на сопровождение кода не начнут расти экспоненциально во времени. Если в проект пришли новые разработчики, полезно убедиться, что качество кода проекта от этого не снизилось, что ребята грамотные и свое дело знают.
Как проконтролировать качество кода? Контролировать нечто абстрактное невозможно. Чтобы контролировать качество нужно уметь его измерять. Нужна мера. Такой мерой могут послужить метрики кода.
Метрик кода придумано великое множество - от тривиально простых (среднее число строк в функции, количество комментариев в коде) до достаточно сложных (метрики Харрисона, Мейджела, Пивоварского, Чепина). Общая черта большинства метрик - они напрямую связаны с хорошими правилами программирования. Например, правило - тело функции должно целиком помещаться на экран. Чем короче метод, тем проще разобраться, как он работает, проще его модифицировать, отладить и протестировать. Этому правилу соответствуют метрики "количество строк в функции" и "количество инструкций в блоке кода".
Другое правило - не следует делать функции с очень большим количеством возможных логических цепочек в потоке управления. Соберите в одной функции множество циклических и условных конструкций - и запросто получите сотню возможных вариантов выполнения всего лишь одной функции. Для каждого варианта нужно предусматривать отдельный тест. И что делать: писать для одной функции сотню тестов? Метрика Cyclomatic Complexity" отслеживает число логических цепочек в блоке кода. Методы с низким значением Cyclomatic Complexity отлаживать и модифицировать быстрее, а покрывать на 100% тестами - проще.
Метрики придуманы чуть ли не для каждой потенциальной проблемы в коде. Вдумчивый анализ метрик программы позволяет разработчику выявить и исключить массу потенциальных проблем. Метрики дают превосходный способ определить, какие части кода нуждаются в рефакторинге, оценить сложность кода, проверить уровень покрытия кода тестами. С их помощью появляется возможность взглянуть на код незнакомого приложения "сверху", получить, так сказать, общую картину приложения. Метрики позволяют контролировать сложность структуры приложения и отслеживать динамику развития кода.
Конечно, рассчитывать значения даже простейших метрик вручную - задача весьма трудоемкая. Но вручную никто ничего не считает - для этих целей есть специальные программы. Для .NET-приложений лидером в этой области является NDepend.
NDepend поддерживает метрики, связанные:
- с организацией кода (количество классов или пространств имен, количество методов в классе);
- с качеством кода (сложность, процент комментариев, количество параметров, уровень сцепленности методов, связность сборок);
- со структурой кода (какие типы чаще всего используются, глубина наследования);
- с покрытием кода тестами (процент покрытия, количество покрытых строк кода, покрытие ветвей).
Всего 82 различные метрики.
NDepend во многом уникальная программа. Рекордное количество метрик. Мощный и крайне нетривиальный интерфейс визуализации структуры кода приложения. Уникальный язык Code Query Language (CQL), позволяющий работать с кодом приложения как с базой данных. Возможность проводить статический анализ кода и находить в нем ошибки и потенциальные проблемы (подобно FxCop, StyleCop и CodeIt.Right). Возможность отслеживать динамику развития кода и степень покрытия кода тестами. Интеграция со множеством сторонних программных продуктов, популярных в среде .NET-разработчиков (NAnt, CruiseControl.NET, Reflector, Visual Studio). Интересных возможностей - море.
Интерфейс
У NDepend несколько вариантов интерфейса: графический интерфейс, командная строка, а также плагины для интеграции с Visual Studio 2005/2008 и популярной утилитой Reflector. Графический интерфейс реализован в Visual NDepend.
 | | Стартовая страница NDepend | На первый взгляд интерфейс Visual NDepend 2.12.1 имеет привычный вид, очень напоминающий Visual Studio. И порядок работы привычен. Создать новый проект. Добавить в него один или несколько солюшенов Visual Studio и/или скомпилированных сборок (NDepend умеет анализировать и то и другое). Запустить процесс анализа. Просмотреть отчет.
Интересных момента, на мой взгляд, здесь два. Во-первых, двойной вариант интерфейса. Поддерживается классический интерфейс с главным меню и современный ленточный (Ribbon) интерфейс. Переключатель между интерфейсами - в настройках приложения.
Во-вторых, способ визуализации результатов анализа. Красиво, но сам черт ногу сломит. Графики, текст, рисунки. И все это тщательно перемешано.
Впрочем, интерфейс кажется сложным лишь поначалу. Дело в том, что для демонстрации результатов анализа используется сразу несколько различных окон:
- браузер классов;
- окно для подачи и просмотра результатов CQL-запросов;
- графический визуализатор метрики кода;
- матрица и граф зависимостей компонентов кода;
- список "стандартных" CQL-запросов, структурированный по категориям;
- окно с результатами статического анализа.
NDepend поддерживает 9 вариантов размещения всех этих окон на экране. Каким бы ни был у вас монитор - огромным или крохотным, - подходящий вариант расположения окон подобрать можно.
 | | Результаты анализа | Каждый из элементов интерфейса предоставляет массу интересной информации. Например, графический визуализатор метрики кода позволяет визуально сравнивать значения метрики различных блоков кода. Скажем, если выбрать метрику "количество строк в коде", то весь код проекта будет показан в виде ячеистой сетки. Крупные ячейки соответствуют блокам кода с большим количеством строк, маленькие - с меньшим. Весьма наглядно.
 | | Результаты анализа. Категория "дизайн" | NDepend не позволяет просматривать дизассемблированный код. Однако навигация по коду поддерживается - достаточно щелкнуть по названию метода или класса, чтобы перейти к соответствующему исходному коду в Visual Studio или Reflector.
Окно с результатами статического анализа содержит информацию о выявленных нарушениях и потенциальных проблемах в коде. Результаты сгруппированы по категориям - все очень напоминает FxCop и CodeIt.Right. Однако NDepend позволяет просмотреть текст запроса, с помощью которого была выявлена проблема. Текст запроса можно скопировать, отредактировать и добавить в группу запросов новый модифицированный запрос. Другими словами, набор правил статического анализа можно самостоятельно пополнять.
Язык CQL
CQL, несомненно, является изюминкой NDepend. Код приложения представляется своеобразной базой данных. NDepend позволяет делать "SQL-подобные" CQL-запросы к этой базе. Пример запроса: "SELECT METHODS WHERE IsPublic AND NbLinesOfCode > 30" - в каких открытых методах содержится более 30 непустых строк кода? Не составляет труда написать запросы типа:
- какие методы были изменены с момента прошлого релиза?
- какие классы реализуют заданный интерфейс?
- какие методы создают объекты заданного класса?
- какие методы входят в десятку самых сложных?
и т. п.
 | | Результаты анализа: методы, нуждающиеся в рефакторинге | Наличие CQL дает возможность самостоятельно прописать ограничения, которым должен удовлетворять код программы. Соблюдение этих правил NDepend будет отслеживать автоматически и сообщать в отчете обо всех выявленных нарушениях. Например - методы не должны содержать более 20 строк: "WARN IF Count > 0 IN SELECT METHODS WHERE NbLinesOfCode > 20".
Подобные правила можно прописывать в виде атрибутов, прямо в коде приложений C# и VB.NET. Таким способом, например, можно задать хитрое ограничение: если метод вызывает один метод класса, то он обязан вызвать еще и другой метод этого же класса (открыл объект - не забудь его закрыть). Другой интересный вариант использования - с помощью атрибутов можно явно, прямо в процессе программирования, помечать методы, которые обязательно должны быть покрыты тестами на 100%.
Любопытно, что CQL позволяет различать классы с неизменным состояниям и классы с состоянием, которое может меняться. Классы с неизменным состоянием - это один из эффективных способов избежать неожиданных сторонних эффектов в программе. Многие считают, что за подобными классами - будущее программирования, и активно их используют. С помощью CQL поиск классов с изменяемым состоянием можно автоматизировать.
Зависимости в коде
Компоненты кода удобно использовать в виде небольших и понятных кусков. Если цикл зависимостей включает N компонентов, то все эти компоненты реализуют один большой суперкомпонент. Преимущество мелких компонентов теряется. Любой из них может быть поврежден путем внесения изменений в другие компоненты. Невозможно полноценно протестировать один компонент, не протестировав другие. И наконец, чтобы повторно использовать компонент в коде, потребуется использовать и все остальные компоненты. Так что отслеживание и минимизация зависимостей в коде - задача важнейшая.
В NDepend имеется две возможности визуализации зависимостей - граф и матрица. Граф показывает общую схему зависимостей - зависимые компоненты соединены стрелочками. Матрица зависимостей показывает детали. Матрица позволяет посмотреть точное количество зависимостей между любыми двумя классами, методами, полями, пространствами имен и т. д. А также легко сгенерировать и выполнить уточняющие CQL-запросы, например: какие типы неявно использует выбранный тип? в каких классах вызывается указанный метод? И так далее.
 | | Матрица зависимостей | Сгенерированные матрицы и графы можно экспортировать в виде картинок.
Покрытие тестами
Автоматизация тестирования - это хорошая практика, позволяющая поднять качество кода. Информация о том, какая часть кода охвачена тестами, - крайне полезна. NDepend собирает информацию о покрытии кода тестами, полученную от NCover и Visual Studio Team System 2005/2008. На основе этих данных NDepend строит некоторые метрики PercentageCoverage, NbLinesOfCodeCovered и т. п. Язык CQL позволяет написать CQL-ограничение, проверяющее, что набор классов охвачен тестами на 100%. NDepend будет сигнализировать в отчетах о выявленных нарушениях этого ограничения.
Версии
На сайте NDepend доступна демоверсия приложения. Она имеет ряд серьезных ограничений. Нет возможности переходить из NDepend к исходным кодам приложения. Очень неудобно работать с матрицей зависимостей - не более 10 последовательных изменений, нельзя экспортировать матрицу в виде картинки, нельзя посмотреть непрямые зависимости. Не работает функция сравнения билдов. И так далее.
Сам NDepend позволяет работать только с .NET-приложениями. Однако разработчики NDepend выпустили еще две аналогичные программы - CppDepend и XDepend, позволяющие анализировать код приложений C++ и Java.
Конкуренты
В Visual Studio 2008 Team Suite есть функция Code Metrics, позволяющая генерировать пять метрик кода. CodeIt.Right Enterprise Edition поддерживает 15 метрик. Кроме этого, существуют соответствующие плагины для Reflector, бесплатная утилита Source Monitor (которая, кстати, способна генерировать метрики сразу для нескольких языков, включая C++, Delphi и HTML) и другие программы.
Выводы
Отличная программа с нетривиальным набором возможностей. Мощный интерфейс. Уникальный набор функций - 82 метрики кода, детальный анализ зависимостей в коде, сравнение билдов. Тесная интеграция с популярными средствами разработки - Visual Studio, Reflector, CruiseControl, .NET, NCover и т. п. Поддержка специального языка CQL, позволяющего работать с кодом программы как с базой данных. NDepend способен просто завалить вас самой разнообразной информацией о коде вашего приложения. Конечно, этой информацией еще нужно суметь воспользоваться. Patrick Smacchia, разработчик NDepend, ведет блог, в котором рассматривает вопросы грамотного использования программы и использования результатов анализа. Почитайте - блог интересный.
|