Analyse der Software-Qualität mit SonarQube

Was ist SonarQube?

SonarQube ist ein Werkzeug, das mittels statischer Code-Analyse technische Qualitätsmerkmale von Software erfasst und diese in einer übersichtlichen Oberfläche darstellt. Neben der Analyse von Java-Quellcode können mittels diverser Plugins auch JavaScript, Groovy, PHP, C# und viele weitere Sprachen analysiert werden. Die offizielle SonarQube Seite listet die verfügbaren Plugins auf. In diesem Artikel beschränke ich mich auf die Analyse von Java-Projekten mittels SonarQube.

SonarQube besteht aus den drei folgenden Komponenten:

  1. Das Analyse-Modul untersucht den Quellcode. Zum Aufruf der Analyse existieren Plugins für Apache Maven und Apache Ant. Zusätzlich existiert ein eigenständiger SonarQube-Runner. Mittels dieser Tools kann die Quellcode-Analyse innerhalb des Builds (beispielsweise in einem CI-System) automatisiert aufgerufen werden.
  2. Die Analyse-Ergebnisse werden in einer Datenbank gespeichert, so dass diese im Nachhinein ausgewertet werden können. Dabei wird neben den jeweils neusten Analyse-Ergebnissen auch eine Historie gespeichert, sodass untersucht werden kann, wie sich die Qualitätsmerkmale im Laufe der Zeit ändern. SonarQube kann mit diversen relationalen Datenbanken betrieben werden.
  3. Eine Webanwendung, mittels der die Analyse-Ergebnisse betrachtet werden können. Die einzelnen Ergebnisse werden zunächst übersichtlich innerhalb eines konfigurierbaren Dashboards angezeigt. Von dieser Übersicht kann man über eine Drill-Down-Funktion weitere Details anzeigen lassen.

SonarQube analysiert den Programm-Code hinsichtlich der folgenden Qualitätsbereiche (Quelle sonarqube.org) :

  • Softwarearchitektur & Softwaredesign
  • Duplikation
  • Unit tests
  • Komplexität
  • Potenzielle Fehler
  • Quellcode-Richtlinien
  • Kommentare

Intern verwendet SonarQube die folgenden Werkzeuge für die Analyse:

  • In SonarQube 4.4 existieren noch Rules, welche die Tools Checkstyle, PMD, Findbugs verwenden. Diese Rules werden von dem Hersteller nach und nach abgelöst durch Regeln, welche mit einer SonarQube eigenen Rules-Engine geprüft werden. (Details: SonarQube Blog)
  • Darüber hinaus werden auch Analyse-Ergebnisse von diversen Tools zur Ermittlung der Testabdeckung eingelesen und in der SonarQube Datenbank gespeichert. Diese können ebenfalls in der Webanwendung betrachtet werden.

SonarQube Webanwendung

Einstiegspunkt in eine Analyse innerhalb der Webanwendung ist das Dashboard. Im linken Bereich werden einige Meta-Informationen wie Anzahl an Klassen, Dateien, Methoden etc. dargestellt. Rechts finden sich die Ergebnisse der Regel-Überprüfungen, direkt darunter Metriken bzgl. der Abhängigkeiten zwischen Dateien.

01_dashboard

In der Ansicht des Dashboards können die Ergebnisse der letzten Analyse mit vorherigen Analysen verglichen werden. So kann schnell erkannt werden, ob sich die Ergebnisse verschlechtern oder verbessern. Auswählbar sind die Änderungen seit der vorherigen Analyse, Unterschiede über die letzten 30 Tage oder Änderungen seit der letzten Version. Die bei der Analyse verwendete Versionsnummer wird bei Maven-Projekten aus dem Version Feld der POM entnommen. Bei anderen Projektarten wird die Versionsnummer bei der Analyse über das Property sonar.projectVersion festgelegt.

In den folgenden Abschnitten werden einige einzelne Analyse-Ergebnisse exemplarisch dargestellt.

Anzeige der Testabdeckung

Im Dashboard werden die Ergebnisse der Testabdeckung angezeigt. Dabei wird unterschieden zwischen Unit- und Integrations-Tests.

02_testabdeckung

Abbildung 1: Anzeige der Testabdeckung eines Projektes

Die Anzeige der Testabdeckung setzt eine korrekte Projekt-Konfiguration voraus. Um bei der Ausführung der Unit- und Integrationstests die Daten zur Testabdeckung aufzeichnen zu können, muss die Java Virtual Maschine entsprechend instrumentiert werden. Hierzu kann z. B. JaCoCo verwendet werden. Eine Beispiel-Konfiguration und Details zum Aufruf der Analyse sind in dem GitHub-Repository sonar-examples von SonarSource  und in der SonarQube Dokumentation (Konfiguration für Unit-Tests, Konfiguration für Integration Tests) zu finden.

Bewertung

Bei dieser Metrik muss stets beachtet werden, dass eine hohe Testabdeckung alleine noch nicht zwangsläufig eine gute Qualität der Software bedeutet. Beispielsweise ist es möglich, „Tests“ zu schreiben, die kein einziges Assert-Statement enthalten. Weiterhin müssen Tests natürlich auch fachlich korrekt sein, was selbstverständlich nicht von einer Software überprüft werden kann.

Anzeige der Regelverletzungen

Die Regelverletzungen werden nach ihrem Schweregrad gruppiert. Nach Auswahl eines Schweregrads werden die verletzten Regeln angezeigt.

Das Bespiel zeigt einige Regeln, welche von SonarQube als Kritisch angesehen werden:

03_regelverletzungen

Nach Auswahl einer Klasse wird diese – zusammen mit den Regelverletzungen – im unteren Bereich dargestellt:

04_regelverletzungen

Praktisch ist die gute Navigierbarkeit innerhalb der Anwendung. So ist es möglich, andere Verletzungen innerhalb der gerade angezeigten Klasse anzusehen. Zur Erhöhung der Übersichtlichkeit kann die Klasse auch in einem separaten Fenster geöffnet werden.

Komplexität

SonarQube ermittelt die zyklomatische Komplexität (Mc-Cabe-Metrik) des untersuchten Projektes. Zur Bestimmung der Metrik wird die Anzahl der folgenden Schlüsselwörter je Methode bzw. je Klasse gezählt:

  • if, for, while, case, catch, throw, return (ausgenommen des letzten return-Statements einer Methode), &&, ||, ?

Es sollte generell eine kleine Zahl und damit geringe Komplexität von Methoden angestrebt werden, da angenommen wird, dass eine Methode umso schwerer von Menschen verstanden werden kann, je höher die Zahl ist.

Bewertung

Die Metrik der zyklomatischen Komplexität ist nicht unumstritten. Ein Switch-Statement mit vielen Case-Anweisungen kann z.B. trotz hoher Komplexitäts-Zahl dennoch übersichtlich sein.

Im Dashboard werden die Durchschnittswerte der Komplexität angezeigt:

05_komplexität

Die Gesamtsumme der Komplexität stellt kein Qualitätsmerkmal dar, sondern gibt einen generellen Hinweis auf die Projektgröße. Die Durchschnittswerte der Komplexität je Methode sind alleine nicht sehr aussagekräftig. So wurde im Beispiel ein Projekt gezeigt, in dem unter anderem viele via Hibernate persistierte Domain-Objekte vorhanden sind, welche zumeist einfache Datenhalte-Objekte sind. Diese reduzieren natürlich die durchschnittliche Komplexität. (Laut Martin Fowler sind solche  „blutarmen“ Domain-Modelle eine Anti-Pattern. Siehe auch AnemicDomainModel)

Mittels Klick auf eine der Komplexitätszahlen kann zu der der Detail-Ansicht navigiert werden, in der weiter durch Packages bis hinunter zu den einzelnen Klassen navigiert werden kann.

Hotspots

Um schnell einen Überblick über die Qualität einer Software zu erhalten, eignet sich der Bereich Hotspot.

Beispiele:

  • Hotspot per nicht abgedeckter Quellcodezeilen
  • Hotspot per Komplexität je Klasse
  • Hotspot per Komplexität je Methode
  • Meist verletzte Ressource
  • etc.

Design

Im Dashboard werden mittels der „Package Design“-Komponente Informationen zu Abhängigkeiten zwischen den Packages und zu zirkulären Abhängigkeiten angezeigt:

08_design

Von dort gelangt man durch Klick auf eine Zahl direkt zur „Dependency Structure Matrix„, in der die Abhängigkeiten der Komponenten (d. h. der Java Packages) dargestellt werden. Mit Hilfe dieser Matrix können zirkuläre Abhängigkeiten im Projekt gefunden werden. Gutes Software-Design vermeidet generell zyklische Abhängigkeiten zwischen einzelnen Packages.

09_dsm_design

Das Diagramm enthält für jedes Package je eine Zeile (mit Beschriftung) und ebenfalls eine korrespondiere Spalte. Innerhalb des Diagramms wird dargestellt, wie viele Klassen eines Packages Klassen aus anderen Packages verwenden. Mögliche zirkuläre Abhängigkeiten können an den rot hinterlegten Zahlen im oberen rechten Bereich der Matrix erkannt werden.

Beispiel

Durch Doppelklick auf eine Zahl (im Beispiel rote „1“ in der Zeile „vorhaben“) werden unterhalb des Diagramms weitere Details der Abhängigkeiten der beiden Packages vorhaben und imp dargestellt:

09_dsm_design_uses

Welche Klassen aus dem Package imp (links) verwenden welche Klassen aus dem Package vorhaben (rechts)

Weitere Details zur Dependency Structure Matrix sind in der SonarQube Dokumentation auf der Seite Cycles – Dependency Structure Matrix enthalten.

Hinweise für den praktischen Einsatz von SonarQube

Definition von projektspezifischen Qualitätsprofilen

Nachdem die SonarQube Analyse eines größeren Projektes mit langer Historie erstmalig ausgeführt wurde, sind häufig sehr viele Metriken diverser Regeln verletzt. In einem großen Projekt können diese Verletzungen nicht unmittelbar durch entsprechende Änderung im Quellcode behoben werden. Dies ist auch nicht in jedem Projekt sinnvoll und notwendig.

Vor der regelmäßigen Verwendung von SonarQube sollten sich die Entwickler des Projektes daher zunächst auf eine Menge von Regeln einigen, die im Projekt eingehalten werden sollen. Dazu kann auch gehören, dass man die Kritikalität einzelner Regeln entsprechend der konkreten Projekt-Notwendigkeiten erhöht oder verringert.

Für die Konfiguration von solchen projektspezifischen Regeln bietet SonarQube den Einsatz von sogenannten „Quality-Profiles“ an. Durch Qualitätsprofile kann festgelegt werden, welche Regeln für die Analyse verwendet werden sollen und mit welcher Kritikalität Regelverletzungen protokoliert werden sollen.

Wird bei der SonarQube-Analyse kein Qualitätsprofil angegeben, verwendet SonarQube per Default das Profil Sonar-Way. Alternativ kann durch Setzen des Properties sonar.profile der Name des gewünschten Profils beim Aufruf der Analyse angegeben werden.

Zur Pflege eines eigenen Profils kann ein bereits vorhandenes Profil kopiert und angepasst werden. Die Anpassung eines Profils wird dabei innerhalb des Bereichs „Rules“ der Anwendung vorgenommen:

10_rules

Bei der Auswahl von Regeln sollte auch geprüft werden, ob im verwendeten Profil deaktivierte Regeln (Filter Activation: Inactive setzten!) existieren, welche im Projekt interessant sein könnten.

Unterdrückung von Validierungen

Zur Unterdrückung von Validierungen bietet SonarQube die folgenden Möglichkeiten:

  • Einfügen des Kommentars //NOSONAR am Zeilenende, wodurch die Analyse für diese Zeile komplett verhindert wird.
  • Annotation einer Methode mittels @SuppressWarnings(„all“), um die Analyse der gesamten Methode zu unterbinden.
  • Eine konkreter Validierungsfehler kann auch mittels der Webanwendung als „falsch positiv“ deklariert werden:

11_falschpositiv

Anzeige von Änderungen

Bei der Anzeige der Regelverletzung können entweder alle Verletzungen angezeigt werden oder nur das Delta zwischen verschiedenen Analyse-Zeitpunkten. Beispielsweise ist die Anzeige der Veränderung seit der Analyse des letzten Release sinnvoll, um rechtzeitig (z. B. noch vor der Auslieferung eines Releases) erkennen zu können, wenn sich die Qualität (hinsichtlich der Metriken) in der aktuellen Version verschlechtert.

Anzeige aller Verletzungen:

12_aenderungen_1

Anzeige der Veränderungen innerhalb der letzten 30 Tage:

13_aenderungen_2

Bei der Anzeige der Regeln werden allerdings nur die Verschlechterungen in der Delta-Anzeige berücksichtigt. Dieser Umstand kann – je nach Persönlichkeit des Entwicklers – unter Umständen auch demotivierend sein.

Umso schöner und motivierender kann daher die Anzeige der Änderung im Dashboard sein:

14_aenderungen_dashboard

Eine Anzeige des Analyseverlaufs über verschiedene Versionen bietet die Seite „Historisch“ (Deutsche Version)  bzw. „Time Machine“ (Englische Version):

15_timemachine

Hinweis: Die Integration-Tests des Projektes wurden ohne Erfassung der Testabdeckung ausgeführt.

Quality Gates und das Build-Breaker Plugin

Mittels Quality Gates können Grenzwerte definiert werden, welche im Projekt nicht überschritten werden dürfen. Durch die Verwendung des Build-Breaker Plugins ist es möglich, den Build fehlschlagen zu lassen, wenn die im Quality Gate definierten Anforderungen nicht erfüllt wurden.

Fazit

Mit SonarQube wird und ein reichhaltiges und mächtiges Werkzeug für die Qualitätsanalyse von Software-Projekten an die Hand gegeben. Richtig konfiguriert und eingesetzt, liefert SonarQube Informationen zu Schwachstellen in Software-Projekten, welche für die daraus geleitete Qualitätsverbesserung eingesetzt werden können.

Bei der Verwendung von SonarQube sollte jedoch immer im Auge behalten werden, welches Ziel mit der Analyse erreicht werden soll. Im Projektteam wird man daher über die verschiedenen Metriken und Regeln diskutieren und sich nach der (hoffentlich eingetretenen) Einigung ein eigenes Qualitätsprofil definieren, welches im Zuge des weiteren Projektverlaufs verwendet wird.

Weiterhin führt die Analyse alleine nicht automatisch zu besserer Qualität. So sind nach der Identifizierung von Schwachstellen im Code selbstverständlich entsprechende Refactoring-Maßnahmen notwendig.

Darüber hinaus sollte das manuelle, durch einen Projektteam-Kollegen durchgeführte Quellcode-Review auch trotz SonarQube weiter durchgeführt werden, um auch Qualität hinsichtlich fachlicher Korrektheit und guter Verständlichkeit (bspw. Benennung von Klassen, Methoden und Variablen) sicherstellen zu können.

Dieser Beitrag wurde unter Software Engineering abgelegt und mit , , , verschlagwortet. Setze ein Lesezeichen auf den Permalink.

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s