Um Qualität in Software zu erreichen, muss diese auch messbar sein. Doch wie lässt sich das am einfachsten machen? Was viele hier vergessen, ist, dass bereits Visual Studio die Anzeige von Qualitätsmetriken anbietet. In diesem Teil der Blog-Serie soll gezeigt werden, wie man mit Visual Studio Qualitätsmetriken anzeigt, was diese bedeuten und wie man diese auch automatisiert prüfen kann.
Codemetriken
Visual Studio bietet die Möglichkeit, Codemetriken zu berechnen, und das schon seit Version 2008. Was früher nur in der VS Premium Version vorhanden war, gibt es heute schon mit VS 2015 Community. Codemetriken können einfach für eine ganze Solution oder für ausgewählte Projekte berechnet werden. Die Option hierfür findet man unter Analyse –> Calculate Code Metrics.
Visual Studio: Codemetriken berechnen
Das Ergebnis der Berechnung wird dann in einem separaten Fenster ausgegeben. In diesem kann man fünf Qualitätsmetriken sehen: Maintainability Index (MI), Cyclomatic Complexity (CC), Depth of Inheritance (DoI), Class Coupling (CP) und Lines Of Code (LOC). Jeder dieser Metriken wird pro Projekt, Namespace, Klasse und Methode berechnet. Die Ergebnisse können nach Wertebereich zu einer Codemetrik gefiltert werden. Zusätzlich gibt es noch einen Export nach Excel. Nützlich ist auch das direkte Anlegen eines Work Items aus den Ergebnissen heraus. Dabei wird für die selektierte Zeile ein Work Item angelegt, welches das analysierte Projekt, den Scope (Namespace, Klasse, Methode), die Konfiguration (Debug, Release) und die einzelnen Codemetriken automatisch hinterlegt. Dieses Work Item kann dann dazu verwendet werden, um ein Refactoring einzuplanen, welches diese Codemetriken verbessert.
Visual Studio: Ergebnis der Codemetriken
Cyclomatic Complexity
Die Cyclomatic Complexity zeigt, wie viele Ausführungspfade es gibt. Je höher die Anzahl Pfade, desto komplexer das Projekt. Je mehr Pfade es gibt, desto höher ist auch die Anzahl an Tests, die diese Pfade abdecken. Die Anzahl Pfade kann nicht unbedingt verringert werden, aber ausgelagert in andere Methoden oder Klassen. Dadurch gibt es zwar mehr Methoden, jedoch sind diese von der Komplexität einfacher zu verstehen.
Depth of Inheritance
Die Depth of Inheritance gibt an, wie tief die Hierarchie einer abgeleiteten Klasse ist. Dabei ist der Standardwert einer Klasse immer eins. Für den Namespace und das Projekt wird jeweils der maximale Wert über alle Klassen verwendet. Je tiefer die Hierarchie einer Klasse, desto komplexer ist diese, bietet auf der anderen Seite jedoch auch eine bessere Wiederverwertbarkeit. Bei der Berechnung der Depth of Inheritance werden nur Klassen und keine Interfaces betrachtet.
Class Coupling
Class Coupling beschreibt, wie viele andere Klassen innerhalb einer Methode oder Klasse verwendet werden. Anhand der verwendeten Klassen kann man erkennen, ob eine Klasse zu viele Abhängigkeiten besitzt, die aufgelöst werden müssen. Dadurch erkennt man auch, ob eine Klasse zu viel Verantwortung hat, die in mehrere Klassen geteilt werden sollte. Bei der Berechnung von Class Coupling gilt zu beachten, dass es hier bestimmte Ausnahmen gibt, wie z.B. gewisse Value Types (string, int, double), die nicht zur Metrik hinzugenommen werden. Das bedeutet jedoch nicht, dass struct’s nicht zum Class Coupling dazugezählt werden.
Lines Of Code
Die Lines of Code können darauf hindeuten, dass ein Projekt, eine Klasse oder eine Methode zu groß ist und aufgeteilt werden sollte. Wie lang zu lange ist, da scheiden sich die Geister. Ein guter Richtwert ist jedoch 100 LOC pro Methode und 1000 LOC pro Klasse als Maximum. Innerhalb der Codemetriken sind die LOC nicht die wirklichen Zeilen C#-Code, sondern vielmehr die Zeilen IL-Code die beim Kompilieren erzeugt werden. Das hat den Vorteil, das zusätzliche Leerzeilen oder Formatierung über mehrere Zeilen keine Auswirkung auf die LOC haben. Am Ende zählen immer nur die Anzahl an IL-Operationen.
Maintainability Index
Der Maintainability Index wird berechnet aus der Halstead Volume, der Cyclomatic Complexity und den Lines Of Code. Genauer kann hier nachgelesen werden, wie sich diese Metrik berechnet. Die Metrik beschreibt, wie einfach es ist, den Code zu warten. Der Maintainability Index hat einen Wert zwischen 0 und 100, je höher desto besser. Zwischen 20 und 100 ist der Farbindikator grün, zwischen 10 und 19 gelb und zwischen 0 und 9 rot. Als Richtwert sollte der Maintainability Index jedoch nie die 50 unterschreiten.
Wer die Metriken direkt im Code sehen möchte und eine Visual Studio Edition mit CodeLens-Support besitzt, dem wird mit der Extension Microsoft CodeLens Code Health Indicator geholfen. Diese zeigt direkt als CodeLens-Erweiterung die aktuellen Metriken direkt bei der Methode oder Klasse innerhalb des Code-Editors an. Das ist hilfreich, damit man direkt bei der Programmierung erkennt, wann ein Refactoring angebracht ist.
Codeanalyse
Zum kontinuierlichen und auch automatischen Prüfen der Codemetriken, ohne diese immer manuell berechnen und nachschauen zu müssen, gibt es vier Codeanalyseregeln, die genau diese abbilden. Diese Regeln haben eine feste Grenze eingebaut, welche wenn überschritten oder unterschritten, eine Warnung generieren. Die Cyclomatic Complexity darf 25 auf Methodenebene nicht überschreiten. Die Depth of Inheritance darf nicht größer sein als 4. Das Class Coupling darf auf Klassenebene 80 und auf Methodenebene 30 nicht überschreiten. Der Maintainability Index muss größer sein als 19 (grün).
Da Codeanalysis eher reaktiv ist und Probleme erst aufzeigt, wenn sie schon vorhanden sind, sollte natürlich kontinuierlich geprüft werden, wie sich die Qualitätsmetriken entwickeln, um hier proaktiv zu sein. Da die Codemetriken auch während eines automatischen Builds über das Commandline-Tool der Code Metrics berechnet und als XML exportiert werden können, ist es möglich, diese auch während des automatischen Builds zu prüfen. Hier können dann auch eigene Grenzwerte gewählt werden, um früher auf mögliche Probleme hingewiesen zu werden.
Fazit
Wem diese fünf Codemetriken ausreichen, der kann ohne großen Aufwand diese in seinen Qualitätsprozess integrieren. Ein wesentlicher Teil ist dabei, die Metriken proaktiv statt reaktiv zu überprüfen und eventuelle Probleme direkt zu beheben. Gleichzeitig heißt es noch lange nicht, dass wenn diese fünf Codemetriken in Ordnung sind, dann auch die Qualität des kompletten Projekts passt. Dies ist lediglich einer von vielen Indikatoren, wie eine mangelhafte Codequalität im Vorfeld erkannt und verbessert werden kann.