Java-Programmierung mit Stil

Ich bin ein Freund von statischer Codeanalyse.
Ich bestehe auf feste Coding-Guidelines.
Ich möchte nur geilen Code lesen.

Mit diesen drei Leitsätzen gehe ich täglich ans (Programmier-)Werk. Natürlich ist gerade bei älterem Bestandscode mein dritter Punkt eher selten getroffen. Aber: mit Hilfe der ersten beiden Punkte lässt sich auch der letzte sehr gut erfüllen. Durch statische Codeanalyse lassen sich – unter anderem – Coding-Guidelines überprüfen bzw. Verstöße gegen eben jene feststellen. In meinem letzten Beitrag hatte ich bereits einige Tools angesprochen, von denen ich hier Checkstyle für Java vorstellen möchte.

Checkstyle – Java mit Stil

Checkstyle ist ein Werkzeug zur statischen Codeanalyse von Java-Code. Ich habe Checkstyle vor etwa 6 Jahren in Version 5.1 kennengelernt, inzwischen ist es bereits bei 7.4 angelangt. Neben einfachen Dingen wie Namenskonventionen und benötigten Klammern werden auch zyklomatische Komplexität, Verschachtelungstiefe oder auch die formale Korrektheit von Javadoc-Kommentaren überprüft.

Einstieg

Um loszulegen, installiert ihr euch das Checkstyle-Plugin einfach über den Eclipse-Marketplace. Im ersten Schritt müsst ihr die Checks für euch definieren und anpassen, die ihr verwenden wollt. So könnt ihr eure Coding-Guidelines in Checkstyle abbilden und automatisch überprüfen lassen. Zur Konfiguration habt ihr zwei Möglichkeiten, entweder passt ihr die Checks direkt im XML-Dokument mit einem Editor eurer Wahl an (links) oder ihr verwendet das Einstellungsmenü von Eclipse (rechts).

Konfiguration von Checkstyle

Eine ausführliche Liste der verfügbaren Checks und wie ihr diese genau konfiguriert, findet ihr auf der offiziellen Checkstyle-Seite (weiter unten gebe ich noch ein paar Tipps in Bezug auf verschiedene Konfigurationen). Jetzt fehlt nur noch ein Schritt, bis Checkstyle läuft: Ihr müsst es aktivieren. Dazu führt ihr einen Rechtsklick auf euer Projekt aus, wählt “Checkstyle” und dann “Activate Checkstyle”.

Aktivieren von Checkstyle

Damit werden nun alle Klassen eures Projektes überprüft. Auch die, die neu hinzukommen. Ihr erkennt das am besten daran, dass verschiedene Zeilen in eurer aktuellen Klasse gelb hinterlegt werden bzw. unten bei den Problemen jede Menge neue Warnungen auftauchen (außer wenn euer Code clean ist, natürlich). Zudem sehr ihr so kleine Lupen-Symbole links bei den Zeilennummern. Wenn ihr da mit der Maus drübergeht, werden euch die Verstöße angezeigt.

Checkstyle-Warnungen im Code

Nun könnt ihr Stück für Stück die einzelnen Probleme angehen – oder die Checks anpassen, falls euch Dinge auffallen, die ihr vergessen habt oder mit denen ihr nicht zufrieden seid. Natürlich seid ihr da nicht auf euch allein gestellt, auch hier greift euch Checkstyle unter die Arme. Mit Command + 1 (Strg + 1 unter Windows/Linux) bietet euch Eclipse über das Quick-Fix Menü an, diverse Checkstyle-Warnungen automatisch zu beheben. Alternativ könnt ihr auch auf die Datei links im Package-Explorer einen Rechtsklick ausführen und “Apply Checkstyle Fixes” auswählen. Dann werden alle Warnungen in der Datei behoben, die automatisch behoben werden können.
Achtung: Checkstyle macht da manchmal kurzen Prozess und entfernt diverse Codestücke, die – je nach Konfiguration – seiner Meinung nach nicht benötigt werden oder nicht erlaubt sind.

Weitere Möglichkeiten, um Checkstyle auszuführen

Checkstyle läuft allerdings nicht nur als Eclipse-Plugin, sondern kann auch als Ant-Task laufen oder über die Kommandozeile ausgeführt werden.

Dieser Befehl prüft YourClass.java mit den Regeln aus YOUR_CONFIG_FILE.xml und schreibt den Output im XML-Format in die Datei checkstyle_errors.xml. Diese XML-Datei kann dann beispielsweise von einem Jenkins-Buildserver interpretiert oder anderweitig von euch verwendet werden. Wenn ihr auf eurem Jenkins-Server die XML-Datei mit den Warnungen aller eurer Klassen auswertet, könnt ihr eine 0-Warnungen-Strategie anstreben. Das bedeutet, dass nach einem Durchlauf von Checkstyle keine Warnungen auftreten dürfen, da sonst der Build fehlschlägt. So lässt sich eine Erosion der Software bzgl. der Checkstyle-Regeln verhindern.

Alternativ kann auch vor jedem Commit überprüft werden, ob die jeweilige(n) Datei(en) “sauber” sind: sind sie das nicht, so wird der Commit zurückgewiesen. Allerdings kann es so passieren, dass eure Entwickler weniger oft (oder gar nicht mehr) ihren Code einchecken. Nach meiner Erfahrung ist der Ansatz mit dem Build-Server der bessere von beiden, da so bei den Entwicklern nicht das Gefühl aufkommt, dass sie geknechtet werden. Im Gegenteil, wenn alle anderen sehen können, dass der aktuelle Build kaputt ist und wer ihn kaputt gemacht hat, besteht eine Motivation bei jedem Einzelnen, keine Regelverstöße zu verursachen.

Architektur-Checks

Möglicherweise lehne ich mich etwas zu weit aus dem Fenster, wenn ich behaupte, dass sich auch die Architektur der Software mit Checkstyle überprüfen lässt. Doch gibt es die Möglichkeit, über eine sogenannte “import-control”-Datei festzulegen, welche Packages in anderen Packages erlaubt sind – oder eben verboten.

Die “Import Control”-Datei legt fest, welche Pakete importiert werden dürfen.

Auf diese Weise kann ich festlegen, welche Module von anderen Modulen verwendet werden dürfen, und welche nicht. Im Bild oben ist beispielsweise das Package “de.wolf.checkstyle.api” im Package “de.wolf.checkstyle” als Import nicht erlaubt, da in diesem Package die API für meine Software definiert wird. Und die soll natürlich nicht in meinem Code verwendet werden. Im Package “de.wolf.checkstyle.common” ist es etwa nicht gestattet, auf Module der Packages “core” oder “gui” zuzugreifen. Es ist einiges an Aufwand notwendig, um diese Datei zu erstellen und die Regeln festzulegen. Gleichzeitig macht man sich aber Gedanken über die Architektur der eigenen Software und findet möglicherweise Potential für Verbesserungen.

Arbeiten mit Konfigurationssets

Abhängig von euren Projekten und eurer Software ist es manchmal sinnvoll, mehrere Konfigurationssets für unterschiedliche Teile der Software zu verwenden. Obige “Import Control”-Datei kann ich z.B. nicht für Code verwenden, der direkt auf Android-Pakete zugreift, da “android” ein verbotenes Package ist. Es macht also Sinn, eine Konfigurationsdatei für den reinen Java-Code zu verwenden und eine für den Native-Code.

Ähnlich verhält es sich bei Software, die zum Teil aus Legacy-Code besteht und zum Teil aus komplett neu geschriebenen Komponenten. Entwickelt man zum Beispiel ein neues, eigenes Common-Paket, das man in verschiedenen Projekte verwenden möchte, so bietet es sich an, gleich mit dem härtesten Checkset einzusteigen, das man sich definiert hat. Für den Legacy-Code kann man Anfang ein reduziertes Set verwenden, um auf dem Jenkins-Server keinen Fehler zu haben. Alternativ kann für den Legacy-Code auf eine 0-Warnungen-Strategie verzichtet werden. Stattdessen kann festgelegt werden, dass jeder Commit oder jeder Build weniger Warnungen haben muss, als der vorherige, um so Stück für Stück zu einer besseren Software zu kommen.

 

Das war’s zum Thema Checkstyle, nächstes Mal werde ich ReSharper Ultimate im Detail vorstellen. Wenn ihr Erfahrungen mit oder Fragen zu Checkstyle habt oder Verbesserungsvorschläge für meinen Beitrag loswerden wollt, ich freue mich über Kommentare oder E-Mails von euch.

 

Kommentare 1

Leave a Reply

Your email address will not be published. Required fields are marked *