NDepend: Tool zur statischen Code-Analyse

NDepend ist ein Tool für die statische Codeanalyse. Mit NDepend können Entwickler und Architekten Code-Strukturen analysieren, Code-Regeln definieren und deren Einhaltung prüfen, Code-Reviews und Refactorings durchführen. NDepend ist vollständig in Visual Studio integriert, lässt sich aber auch als Stand-Alone Applikation ausführen. Dies ist vor allem dann von Vorteil wenn auf dem entsprechenden Rechner keine Entwicklungsumgebung installiert ist (z.B. auf einem Buildserver). Das Tool lässt sich darüber hinaus in den Build-Prozess integrieren was kontinuierliche Analysen des Quellcodes ermöglicht. Hier mal einige Features:

  • Auswertung div. Softwaremetriken
  • Visualisierung von Abhängigkeiten (Abhängigkeitsgraph und Abhängigkeitsmatrix)
  • Unterstützung von Code-Regeln
  • Visual Studio Integration
  • Build-Prozess Integration
  • Umfangreiche Reporting-Möglichkeiten

In dem folgenden Beitrag wird nun ein Beispielprojekt mit NDepend analysiert und die daraus resultierenden Ergebnisse erläutert. Darüber hinaus werden einige Features von NDepend näher beschrieben.

Installation und Analyse eines Projekts

Die Installation von NDepend gestaltet sich am einfachsten als Visual-Studio-Plug-in. So können Projekte direkt aus Visual Studio heraus analysiert werden. Der Installer für Visual Studio (NDepend.VisualStudioExtension.Installer.exe) sieht wie folgt aus:

NDepend Visual Studio Installer

NDepend Visual Studio Installer

Daneben gibt es die Stand-Alone Applikation (VisualNDepend.exe) von NDepend, welche wie folgt aussieht (über diese ist es auch möglich die Visual Studio Erweiterung zu installieren):

NDepend Stand-Alone Applikation

NDepend Stand-Alone Applikation

NDepend selbst erfordert keine Entwicklungsumgebung und keine Änderungen am Quelltext der eigenen Anwendung, um Analysen durchzuführen. Laut Hersteller untersucht das Tool 10.000 Zeilen C#- oder VB.NET-Code pro Sekunde. Es führt alle Analysen asynchron aus und der Speicherbedarf liegt laut Hersteller zwischen 50 und 100 MByte. Über den Menüpunkt „Analyze VS solutions and VS projects“ kann eine Visual Studio Solution für die Analyse geladen werden:

Visual Studio Solution analysieren

Visual Studio Solution analysieren

Mit einem Klick auf „Analyze .NET Assemblies“ wird die Analyse gestartet. Nach der Analyse eines Projekts werden die Ergebnisse in einem übersichtlichen Dashboard angezeigt. Für das folgende Beispiel habe ich die PrismMahAppsSample-Solution verwendet. Das Ergebnis der Analyse sieht dabei wie folgt aus:

NDepend Dashboard

NDepend Dashboard

So sieht man auf einen Blick den aktuellen Zustand des Projekts. Kommen wir nun zur Auswertung der Analyse.

Code-Metriken

NDepend unterstützt insgesamt 82 verschiedene Code-Metriken, die in unterschiedliche Kategorien wie Anwendungen, Assemblies, Methoden und Felder fallen. Dazu gehören Klassiker wie die Anzahl von Code- oder Kommentarzeilen. Auch die Anzahl von Typen, Methoden oder Feldern berechnet NDepend auf Knopfdruck.

Bei Code-Metriken handelt es sich um Maßzahlen, die einen ersten Überblick über den Quellcode vermitteln sollen. Die Codemetrikergebnisse sollen ein Verständnis dafür wecken, welche Typen und/oder Methoden überarbeitet oder gründlicher getestet werden sollten. Entwicklerteams können potenzielle Risiken erkennen, den aktuellen Zustand eines Projekts feststellen und den Fortschritt bzw. die Qualität bei der Softwareentwicklung verfolgen. Einfache Metriken zeigen die Größe des Quellcodes in Zeilen (LOC), komplexere Metriken versuchen die Verständlichkeit des Quellcodes zu beurteilen. Daraus lassen sich dann Qualitätsmerkmale wie zum Beispiel Wartbarkeit, Erweiterbarkeit oder Verständlichkeit ableiten.

Eine Liste der unterstützten Code-Metriken und weitere Informationen zu Code-Metriken finden sich in der Online-Hilfe zu NDepend: http://www.ndepend.com/docs/code-metrics

Lines of Code (LOC)

Die Lines of Code (LOC) sind eine Maßzahl, um die Größe eines Computerprogramms oder seines Wachstums zu beschreiben. Die Lines of Code (LOC) sind im einfachsten Fall die Anzahl der Zeilen des Quelltextes aus denen das Programm besteht. Die Darstellung innerhalb von NDepend erfolgt zeitbasiert (sog. Trend-Charts), sodass der Nutzer verschiedene Analysen im Verlauf erkennt. So sieht man, wie sich ein Projekt hinsichtlich der Lines of Code, der Testabdeckung und anderer Faktoren entwickelt.

Cyclomatic Complexity (CC)

Die zyklomatische Komplexität (cyclomatic complexity) ist eine Software-Metrik, mit der die Komplexität eines Software-Moduls (Funktion, Prozedur oder allgemein ein Stück Sourcecode) gemessen werden kann. Dabei werden die Anzahl der Entscheidungen, die innerhalb einer Methoden getroffen werden können berücksichtigt. NDepend wertet dabei die folgende Ausdrücke:

if | while | for | foreach | case | default | continue | goto | && | || | catch | ternary operator ?: | ??

Die folgenden Ausdrücke werden dabei nicht berücksichtigt:

else | do | switch | try | using | throw | finally | return | object creation | method call | field access

Die zyklomatische Komplexität wird für die gefundenen Methoden definiert. Für eine Klasse berechnet sich die zyklomatische Komplexität aus der Summe der einzelnen Methoden der jeweiligen Klasse (anonyme Methoden werden dabei nicht berücksichtigt).

Empfehlung: Methoden mit einer zyklomatischen Komplexität größer als 15 sind schwer zu verstehen und zu warten. Methoden mit einer zyklomatischen Komplexität größer als 30 werden als extrem komplex eingeschätzt und sollten in kleinere Methoden aufgeteilt werden (ausgenommen automatischer generierter Quellcode).

Innerhalb des Dashboards ist die Angabe über die zyklomatische Komplexität unter dem Punkt „Method Complexity“ zu finden:

Zyklomatische Komplexität

Zyklomatische Komplexität

Hier wird ein Mittelwert für die Komplexität des gesamten Projekts angegeben. Es gibt natürlich auch die Möglichkeit mehr ins Detail zu gehen, z.B. kann man sich die komplexesten Klassen/Methoden anzeigen lassen. Diese Details erreicht man über den Menüpunkt „METRIC -> Most Complex -> Method“ (unter dem Menüpunkt „METRIC“ gibt es noch diverse andere Auswertungen):

NDepend_CC_02

Danach erhält man eine Übersicht über die einzelnen Klassen:

Zyklomatische Komplexität pro Klasse/Methode

Zyklomatische Komplexität pro Klasse

Das Ganze wird zusätzlich noch in einer Treemap visualisiert. Beim Treemapping wird eine Baumstruktur durch geschachtelte Quadrate visualisiert. Diese Treemap ist dabei wie folgt strukturiert:

  • .NET-Assembly enthält Namespaces
  • Namespaces enthalten Typen
  • Typen enthalten Methoden und Felder

Dabei repräsentiert jedes Quadrat eine Methode der Klasse und je größer die Fläche des Quadrats desto höher ist die zyklomatische Komplexität. Zusätzlich werden die Quadrate (je nach Komplexität) in den Ampelfarben (grün, gelb und rot) eingefärbt. Die Schwellwerte für die Farben können individuell festgelegt werden. Das sieht dann wie folgt aus:

NDepend Treemap

NDepend Treemap

Mit Hilfe der Treemap können auf den ersten Blick mögliche „Brandherde“ identifiziert und genauer analysiert werden. Darüber hinaus erhält man eine groben Überblick über die Code-Struktur. Gerade bei größeren Projekten ist dies ungemein hilfreich.

Weitere Informationen zur Visualisierung von Code-Metriken finden sich in der Online-Hilfe: http://www.ndepend.com/docs/treemap-visualization-of-code-metrics

Visualisierung von Abhängigkeiten

Neben den Code-Metriken stellt NDepend einige Analysen und Visualisierungen bereit, um die Architektur einer Implementierung zu bewerten. Je länger eine Anwendung in der Entwicklung ist und je mehr Änderungen, Bugfixes und neue Features implementiert werden, desto größer ist die Gefahr, dass sich grundlegende Eigenschaften ändern, die für die Applikation festgelegt bzw. definiert wurden. Dazu gehören beispielsweise die Interaktion von Schichten, Schnittstellen und Events, Vererbungstiefen oder Abhängigkeiten zwischen verschiedenen Klassen. Dabei zeigt sich NDepend äußerst flexibel was die Visualisierung von Abhängigkeiten angeht. Abhängigkeiten können entweder als Graph oder Matrix dargestellt werden.

Abhängigkeitsgraph

Der Abhängigkeitsgraph eignet sich bestens für kleinere Projekte, da er sehr intuitiv ist. Bei größeren Projekten mit komplexen Abhängigkeiten wird er aber schnell unübersichtlich. Für das gewählte Beispielprojekt sieht der Abhängigkeitsgraph wie folgt aus:

Abhängigkeitsgraph

Abhängigkeitsgraph

Abhängigkeitsmatrix

Die Abhängigkeitsmatrix bietet einen besseren Überblick und wirkt „aufgeräumter“. Hier die Abhängigkeitsmatrix für das Beispielprojekt:

Abhängigkeitsmatrix

Abhängigkeitsmatrix

Die Darstellung als Matrix ist nützlich, um direkte und indirekte Abhängigkeiten aufzufinden. Die blauen Zellen symbolisieren, dass die Assembly innerhalb der Spalte die entsprechende Assembly aus der Zeile verwendet. Die jeweilige Zahl gibt die Anzahl der Verwendungen an. So nutzt die Assembly „PrismMahAppsSample.Shell“ 15 Typen aus der Assembly „PrismMahAppsSample.Infrastructure“. Bei den grünen Zellen ist das Abhängigkeitsverhältnis genau umgekehrt (Assembly aus der Zeile nutzt Assembly aus der Spalte). Mit einem Klick auf eine Zelle werden die Abhängigkeiten der beiden Assemblies in dem intuitiveren Abhängigkeitsgraphen angezeigt. Dies ist vor allem beim Refactoring hilfreich um Abhängigkeiten besser auflösen zu können. Die Art der angezeigten Abhängigkeiten kann auch eingestellt werden:

Code-Regeln

Ein weiteres sehr nützliches Feature von NDepend sind Code-Regeln. Mit Hilfe von Code-Regeln lassen sich definierte Eigenschaften von Quelltext überprüfen. Von Haus aus bringt NDepend über 200 solcher Regeln mit, die in verschiedene Kategorien wie Design, Architektur und Namenskonventionen eingeteilt sind:

Code-Regeln Kategorien

Code-Regeln Kategorien

Diese Einteilung lässt sich aber beliebig anpassen und darüber hinaus können eigene Code-Regeln definiert werden. Die Code-Regeln können flexibel gestaltet werden und jeder Entwickler/Architekt kann selbst entscheiden welche Regeln auf welches Projekt angewendet werden sollen. Code-Regeln werden in einer NDepend spezifischen Sprache namens CQLinq definiert (weitere Infos: http://www.ndepend.com/docs/cqlinq-syntax). Wie der Name bereits vermuten lässt basiert das Ganze auf LINQ, was die Einarbeitung erheblich vereinfacht. Das Erstellen eigener Code-Regeln und die Anpassung der ebenfalls in CQLinq implementierten, mitgelieferten Regeln bringt eine hohe Flexibilität. Das Editieren der Code-Regeln erfolgt über den „Queries and Rules Explorer“:

Queries and Rules Explorer

Queries and Rules Explorer

Über den „Queries and Rules Explorer“ lassen sich die Code-Regeln auch einzelnen ausführen. Das Ergebnis wird dann direkt unter der jeweiligen Abfrage angezeigt:

Query and Rules Edit

Query and Rules Edit

Das oben gezeigte Beispiel zeigt eine Abfrage zum Ermitteln der 100 meist verwendeten Typen. Im oberen Fenster lässt sich die Abfrage editieren und darunter werden die Ergebnisse angezeigt.

Hier eine Auflistung der NDepend Standard-Regeln: http://www.ndepend.com/default-rules/webframe.html

Reporting

Von den Analyse-Ergebnissen erstellt NDepend umfangreiche HTML-Reports. Hier mal einige Beispiel-Reports: http://www.ndepend.com/sample-reports/

Diese Reports lassen sich einfach an die eigenen Bedürfnisse anpassen. Hier mal der Link zur Online-Dokumentation: http://www.ndepend.com/docs/customize-ndepend-report

Fazit

NDepend ist ein flexibles und mächtiges Werkzeug zur Code-Analyse und Unterstützung von Code-Reviews bzw. Refactorings. Durch die Build-Server Integration können auch kontinuierliche Code-Analysen durchgeführt werden. Damit ist es möglich Daten über die gesamte Projektlaufzeit zu sammeln und über das Build-Comparison-Tool zu vergleichen (http://www.ndepend.com/docs/reporting-code-diff). Durch die zur Verfügung gestellten Trend-Analysen kann die Code-Qualität kontinuierlich überwacht und verbessert werden. Wird NDepend konsequent im Projekt eingesetzt, können Fehler und Missstände frühzeitig erkannt und entsprechende Gegenmaßnahmen definiert werden.

Literaturverzeichnis und Weblinks

Abk.Quelle
[1]NDepend
NDepend
[2]NDepend unterstützte Code-Metriken
http://www.ndepend.com/docs/code-metrics
[3]NDepend Visualisierung von Code-Metriken
http://www.ndepend.com/docs/treemap-visualization-of-code-metrics
[4]McCabe-Metrik
https://de.wikipedia.org/wiki/McCabe-Metrik
[5]NDepend Standard-Regeln
http://www.ndepend.com/default-rules/webframe.html
[6]NDepend CQLinq Syntax
http://www.ndepend.com/docs/cqlinq-syntax
Fork me on GitHub