Berufsakademie Stuttgart - Außenstelle Horb Fachrichtung Informationstechnik Code-Review in Java Möglichkeiten, Tools und Anwendung erstellt im Rahmen der Vorlesung: Software-Engineering · Semester 5 · Dozent: Prof. Dr.-Ing. Olaf Herden Martin Linder <[email protected]> Markus Ulmer <[email protected]> Inhaltsverzeichnis 1. Einführung 1.1. Motivation . . . . . . . . . . . . . . . . . . . . 1.2. Verschiedene Varianten des Code-Reviews . . 1.2.1. Analyse nach Metriken . . . . . . . . . 1.2.2. Stil-Analyse . . . . . . . . . . . . . . . 1.2.3. Programmfluss-Analyse . . . . . . . . 1.3. Möglichkeiten und Grenzen des Code-Review 1.4. Ansätze zur Durchführung von Code-Reviews . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2. CAP: Code Analysis Plugin 2.1. Programmbeschreibung . . . 2.2. Konfiguration & Anwendung 2.3. Arbeitsweise . . . . . . . . . . 2.4. Bewertung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 . 8 . 9 . 10 . 11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 4 5 5 5 6 6 7 3. Checkstyle 12 3.1. Programmbeschreibung . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 3.2. Konfiguration & Anwendung . . . . . . . . . . . . . . . . . . . . . . . . . 13 3.3. Bewertung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 4. PMD 4.1. Programmbeschreibung 4.2. Konfiguration von PMD 4.3. Arbeitsweise . . . . . . . 4.4. Bewertung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 15 17 17 17 5. FindBugs 5.1. Programmbeschreibung . . 5.2. Konfiguration von Findbugs 5.3. Arbeitsweise . . . . . . . . . 5.4. Bewertung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 18 20 21 21 . . . . 2 Inhaltsverzeichnis 6. Fortify 22 6.1. Programmbeschreibung . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 6.2. Arbeitsweise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 6.3. Bewertung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 7. Fazit 24 7.1. Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 7.2. Ausblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 A. Freie Tools für Java-Code-Review 26 3 1. Einführung „Viele Programmierer wechseln nach zwei Jahren den Arbeitgeber, da sie ihren eigenen Code nicht mehr lesen können. Dafür übernehmen sie ein Projekt, von einem anderen Programmierer, der gerade gekündigt hat, da er ebenfalls den Code nicht mehr lesen kann. Nach einigen Wochen oder Monaten überzeugt der Programmierer in seiner neuen Stelle seinen Chef, den Code seines Vorgängers zu verwerfen und neu zu beginnen. Nach zwei Jahren wiederholt sich die Geschichte.“ [Büt03] 1.1. Motivation Heutzutage wird in sehr vielen Branchen effektive Teamarbeit gefordert. So sind an größeren IT-Projekten oft viele Programmierer beteiligt. Oftmals zeigt sich, dass dabei jeder einen eigenen Programmierstil hat, was sich für die Teamarbeit sehr störend auswirkt. Aus diesem Grund werden in vielen Unternehmen spezielle Codekonventionen festgelegt, an die sich die Programmierer halten müssen. Code-Review dient zum Durchsetzen solcher Regeln und kann auf verschiedene Arten durchgeführt werden. Code-Review im eigentlichen Sinne bedeutet die Durchsicht und Überprüfung von Quelltexten durch eine andere Person. Es dient der Verbesserung sowie der Qualitätssicherung von Computerprogrammen. Der Code-Reviewer überprüft dann unter anderem die Einhaltung der Codekonventionen. Der Einsatz von Mitarbeitern als Code-Reviewer ist allerdings relativ teuer, da der Mitarbeiter mit dieser Arbeit voll ausgelastet ist. Glücklicherweise gibt es heutzutage auch günstigere und effiziente Möglichkeiten des Code-Reviews: Auf dem Markt sind zahlreiche Produkte verfügbar, die neben dem Überprüfen des Quelltextes auf Codekonventionen auch weitere sehr interessante Features bieten, wie beispielsweise die Erkennung von BufferOverflows oder NullPointerExceptions im Vorfeld. Im Rahmen dieser Arbeit sollen verschiedene Software-Produkte vorgestellt und beurteilt werden. 4 1. Einführung 1.2. Verschiedene Varianten des Code-Reviews Das Hauptaugenmerk beim Code-Review liegt in der Überprüfung der Einhaltung von Codekonventionen. Allerdings sind heutzutage auf dem Markt zahlreiche Tools verfügbar, die noch einiges mehr leisten. Dabei ist eine Unterteilung in drei Kategorien sinnvoll [Rup05]. 1.2.1. Analyse nach Metriken Die Analyse nach Metriken findet auf Quellcode-Ebene statt. Hierbei wird die DesignQualität in Hinblick auf Erweiterbarkeit, Wiederverwendbarkeit und Wartbarkeit untersucht. Existieren viele Abhängigkeiten zwischen Paketen, so führt dies zu schlechter Wiederverwendbarkeit und zu hohen Wartungskosten. Ziel der Softwareentwicklung sollte es also sein, eine lose Kopplung zwischen Paketen zu schaffen. Beispiele für Tools, die eine Metrik-Analyse durchführen, sind JDepend und CAP - Code Analysis Plugin, auf welches später noch eingegangen wird. 1.2.2. Stil-Analyse Auch die Stil-Analyse bewegt sich auf der Quellcode-Ebene. Hierbei wird vor allem die Einhaltung von Codekonventionen überprüft, was der Erhöhung der Lesbarkeit des Codes dient. Dies umfasst unter anderem die Benennung von Variablen, Konstanten und Methoden. Außerdem kann beispielsweise überprüft werden, ob für Ausgaben immer ein Logging-Framework anstatt von normalen print-Befehlen benutzt wird. Neben solchen Konventionen kann in der Stil-Analyse auch die Code-Dokumentation überprüft werden: So werden beispielsweise alle relevanten Javadoc-Parameter auf Vorhandensein kontrolliert und validiert. Es kann auch geprüft werden, ob für alle Pakete eine Beschreibungsdatei (package.html ) vorliegt. Zwei Tools zur Stil-Analyse (Checkstyle und PMD) werden im Folgenden noch detailliert beschrieben. 5 1. Einführung 1.2.3. Programmfluss-Analyse Im Gegensatz zu den beiden vorgehenden Kategorien findet die Programmfluss-Analyse auf Ebene des Bytecodes statt. Der Code wird dabei auf Sicherheitslücken und Schwachstellen überprüft. So können beispielsweise NullPointerExceptions im Vorfeld erkannt und somit beseitigt werden. In einem großen Projekt können auf Anhieb ohne weiteres 100 mögliche NullPointerExceptions gefunden werden. Allerdings ist die Erkennung von Fehlern hierbei begrenzt, da keine Kenntnis über das Laufzeitverhalten bekannt ist. Ziel der Programmfluss-Analyse ist die Verringerung der Laufzeit-Fehler. Das freie Tool Findbugs wird später noch behandelt. Außerdem werden auch die Möglichkeiten der kommerziellen Produkte von Fortify Software beschrieben. 1.3. Möglichkeiten und Grenzen des Code-Review Ein konsequenter Einsatz von Code-Review-Tools führt zu verständlicherem Code und kann somit den Entwicklungsprozess entscheidend vereinfachen und beschleunigen. Vor allem die Wartbarkeit des Codes wird dadurch stark erhöht. Natürlich führt dies auch zu (nur schwer einschätzbaren) Einsparungen. Hieran lassen sich bereits Probleme in Verbindung mit Code-Reviews erkennen: Die Ergebnisse zeigen sich nicht unmittelbar am Anfang eines Projekts, sondern werden erst nach einer gewissen Zeit sichtbar. Die zu Entwicklungsbeginn in Code-Reviews investierte Zeit macht sich jedoch später bezahlt. Außerdem wird mittels Code-Reviews „lediglich“ die innere Qualität der Software erhöht, was sich in einer kürzeren Korrekturphase und besserer Wartbarkeit niederschlägt. Beides sind allerdings nur schwer quantifizierbare Größen [Tam05]. Ein weiteres Problem ist, dass viele Programmierer keine Kritik an ihrem Code vertragen und sich nur ungern auf Konventionen einlassen. Alles in allem ist Code-Review vor allem dann sinnvoll, wenn man schon zu einem frühen Entwicklungszeitpunkt damit beginnt. 6 1. Einführung 1.4. Ansätze zur Durchführung von Code-Reviews Beim Ablauf des Code-Reviews kann, wie Abbildung 1.1 zeigt, zwischen verschiedenen Ansätzen unterschieden werden. Abbildung 1.1.: Verschiedene Ansätze des Code-Review-Ablaufs Die Festlegung der Codekonventionen erfolgt bei den meisten Tools mittels einer XMLDatei, wobei die Syntax sich hierbei von Programm zu Programm unterscheidet. Die Durchführung des Code-Review kann auf verschiedene Arten erfolgen. Für viele Tools werden für verschiedene integrierte Entwicklungsumgebungen (IDE) wie beispielsweise Eclipse1 Plugins angeboten. Diese erlauben meist eine „Echtzeit“-Überprüfung des Quelltextes - Verstöße und Fehler werden also sofort als solche angezeigt und können schnell korrigiert werden. Sehr verbreitet ist die Überprüfung mittels Ant2 -Tasks: Bei der Kompilierung wird dieser Task durchgeführt und erstellt einen Fehlerbericht, in dem alle Verstöße und sonstige Fehler aufgeführt werden. Diese Error-Reports werden oft in Form von HTML-Dateien erstellt. Die Ant-Tasks können üblicherweise in die IDE integriert werden, sodass ein komfortables Arbeiten gewährleistet ist. Eine dritte Variante ist die Code-Überprüfung über eigenständige Programme - teils kommandozeilenorientiert, teils mit grafischer Benutzeroberfläche (GUI). Diese Möglichkeit ist allerdings nicht sehr komfortabel, da keine IDE-Integration möglich ist. 1 2 http://www.eclipse.org/ http://ant.apache.org/ 7 2. CAP: Code Analysis Plugin 2.1. Programmbeschreibung CAP (http://cap.xore.de/) ist ein Plugin für die Eclipse Plattform (Version 3.0+) zur Analyse von Abhängigkeiten zwischen Klassen und Paketen in einem Java-Projekt. Es beinhaltet eine eigene Eclipse-Perspektive und zeigt die Ergebnisse anhand verschiedener Diagramme. Abbildung 2.1.: Die CAP-Perspektive in Eclipse 8 2. CAP: Code Analysis Plugin Die Ziele von CAP sind das Erkennen von typischen Schwächen und Fehlern in einer Architektur sowie die Hilfe bei der Bewertung und Verbesserung des Softwaredesigns. Daraus resultiert eine Verbesserung der Wartbarkeit und der (Wieder-)Benutzbarkeit. Außerdem dient die Software der Optimierung der Kapselung. Dies wird unter anderem dadurch erreicht, dass auf eine lose Kopplung von Paketen geachtet wird. Die Kopplung geschieht dabei über Interfaces und abstrakte Klassen. Natürlich kann CAP keine gute Architektur erkennen oder gar erstellen. Dennoch ist CAP beim Auffinden von Design-Schwachstellen sehr hilfreich und ist aus Sicht der Autoren „ein mächtiges Werkzeug in der Hand des Verständigen“ [SM05]. 2.2. Konfiguration & Anwendung Nach der Installation von CAP kann die Analyse über das Kontextmenü des zu überprüfenden Projekts im Package Explorer gestartet werden. Daraufhin wird automatisch die CAP-Perspektive geöffnet. Diese Perspektive besteht aus folgenden Sichten: Package Explorer CAP besitzt einen eigenen Package Explorer, der alle im Projekt verwendeten Pakete und die darin enthaltenen Klassen und Interfaces anzeigt. Beziehungsfenster Im Beziehungsfenster werden die ein- und ausgehenden Beziehungen eines Package graphisch dargestellt. Distance Graph Hier werden die Pakete des Projekts als Punkte in einem Koordinatensystem (Abstraktheits-Instabilitäts-Diagramm) angezeigt, wobei die Größe der Punkte die Anzahl der Klassen des Paketes repräsentiert. Dies wird in Abschnitt 2.3 noch detailliert beschrieben. Statistics Das Statistik-Fenster gibt einen Überblick über die ermittelten Kennzahlen. Statistic Chart Hier werden die ermittelten Kennzahlen mithilfe von Kreis- und Balkendiagrammen für den Benutzer übersichtlich angezeigt. Aferente/Eferente Deps Diese Fenster zeigen die ein- und ausgehenden Beziehungen des analysierten Paketes in einer Übersicht an. 9 2. CAP: Code Analysis Plugin 2.3. Arbeitsweise Zur Durchführung der Code-Analyse müssen zunächst verschiedene Kennzahlen ermittelt werden. Beispiele sind die Anzahl eingehender und ausgehender Verbindungen von Klassen und Paketen oder die Anzahl von abstrakten Klassen. Aus diesen Kennzahlen wird anschließend die Abstraktheit A und die Instabilität I der Architektur ermittelt, wobei I, A ∈ [0, 1]: Abstraktheit A Verhältnis der abstrakten zu den konkreten Klassen. A = 0 bedeutet, dass das Paket keine abstrakten Klassen und Interfaces beinhaltet. A = 1 bedeutet, dass das Paket nur aus abstrakten Klassen und Schnittstellen besteht. Instabilität I Quotient, der angibt wie hoch das Verhältnis der herausführenden Abhängigkeiten im Verhältnis zu der Summe der Abhängigkeiten ist. I = 0 bedeutet, dass das Paket komplett stabil ist, d.h. es exsistieren keine Abhängigkeiten von anderen Paketen. I = 1 bedeutet, dass das Paket komplett instabil ist. Das Paket reagiert somit sehr empfindlich auf Änderungen in anderen Paketen Ein Großteil der Berechnungen basiert auf der Analyse OO Design Quality Metrics 1 von Robert Martin aus dem Jahre 1994. Abbildung 2.2.: CAP analysiert das Verhältnis zw. Abstraktheit u. Instabilität 1 http://www.objectmentor.com/resources/articles/oodmetrc.pdf 10 2. CAP: Code Analysis Plugin Die Abbildung 2.2 zeigt ein Abstraktheits-Instabilitäts-Diagramm. Eine optimale Architektur befindet sich auf der gestrichelten Linie: Hier herrscht eine optimalen Balance zwischen Abstraktheit und Stabilität. Optimale Pakete sind vollständig abstrakt und stabil oder entsprechend konkret und instabil. Als Maß für die Güte einer Architektur gibt CAP den Abstand des betreffenden Paketes zur Wunschlinie an. 2.4. Bewertung Die Installation gestaltet sich als einfach, da hier der Eclipse-Update-Manager benutzt werden kann. Lediglich die Abhängigkeiten von Draw2d und JFreeChart sind hierbei zu beachten. Auch die Benutzung von CAP ist sehr einfach und intuitiv. Schade ist, dass die Software die Ergebnisse der Analyse nur anzeigt, aber keine Tipps zur Verbesserung der Architektur gibt. Allerdings steht dieses Feature bereits auf der ToDo-Liste der Entwickler. 11 3. Checkstyle 3.1. Programmbeschreibung Das weit verbreitete Open-Source-Tool Checkstyle (http://checkstyle.sourceforge. net/) dient zur Überprüfung der Einhaltung von Code-Konventionen in Java-Projekten. Die Regeln werden mittels regulären Ausdrücken definiert und in XML-Dateien abgelegt. Mit dem Programm werden bereits verschiedene Konfigurationen mitgeliefert. Die voreingestellte Konfiguration überprüft den Code hinsichtlich den Code-Konventionen von Sun (http://java.sun.com/docs/codeconv/). Checkstyle ist in der Lage, sehr umfangreiche Reports zu generieren. Checkstyle bietet zwei Varianten des Code-Reviews an: Zum einen kann der Quelltext über ein kommandozeilenorientiertes Tool überprüft werden - zum anderen wird ein entsprechender Ant-Task mitgeliefert. Die Buildtools Maven (http://maven.apache.org/) und Centipede (http://www.krysalis.org/centipede/) unterstützen Checkstyle bereits out-of-the-box. Außerdem werden von Drittherstellern zahlreiche Plugins für verschiedene IDEs angeboten, Tabelle 3.1 gibt einen Überblick: IDE Eclipse Eclipse NetBeans JBuilder vim Name Eclipse Checkstyle Checkclipse nbCheckStyle Checkstyle4JBuilder java_checkstyle.vim Homepage http://eclipse-cs.sourceforge.net/ http://www.mvmsoft.de/ http://nbcheckstyle.sourceforge.net/ http://www.pautinka.com/ http://vim.sourceforge.net/scripts/ script.php?script_id=448 Tabelle 3.1.: Verfügbare Checkstyle-Plugins für verschiedene IDEs (Auszug) 12 3. Checkstyle 3.2. Konfiguration & Anwendung Die Konfiguration erfolgt über XML-Dateien, in welchen spezifiziert wird, welche Module eingebunden werden sollen. Diese Module sind in einer Baumstruktur organisiert, deren Wurzel das Checker -Modul bildet. Ein sehr mächtiges Modul ist TreeWalker, das als Container für zahlreiche Untermodule zur Untersuchung von java-Dateien dient. Im Folgenden sollen beispielhaft einige interessante Module vorgestellt werden: StringLiteralEquality verhindert den Vergleich von String-Literalen durch == und !=. Da Strings in Java Objekte sind, würden dabei die Referenzen der Strings miteinander verglichen. Deshalb zwingt dieses Modul den Programmierer zur Verwendung der equals-Methode, die lediglich die Strings miteinander vergleicht. StrictDuplicateCode vergleicht die Codezeilen aller Java-Dateien. Es alarmiert, wenn eine bestimmte Anzahl gleicher Zeilen, die sich nur in der Einrückung unterscheiden, an verschiedenen Stellen vorkommen. PackageHtml überprüft, ob in allen Verzeichnissen mit Java-Dateien die Datei package.html existiert. Somit ist gewährleistet, dass zu jedem Package eine Dokumentation existiert. AvoidStarImport verhindert, dass in den Imports ein * vorkommt. Dadurch wird verhindert, dass unbenötigte Klassen importiert werden. Um ein Modul zu aktivieren genügt es <module name="ModulName" /> an die entsprechende Stelle im Modulbaum einzufügen. Bei einigen Modulen müssen außerdem spezielle Parameter definiert werden: <module name="GenericIllegalRegexp"> <property name="format" value="System[.]out[.]print" /> </module> Diese Einstellung verhindert die Verwendung der Methoden System.out.print und System.out.println. Dies ist beispielsweise dann sinnvoll, wenn ein Logging-Framework wie Log4J benutzt werden soll. 13 3. Checkstyle Insgesamt sind weit über hundert Checks verfügbar. In der Standard-Konfiguration werden unter anderem Javadoc-Kommentare, Namenskonventionen, Header-Kommentare, Import-Anweisungen, Modifier sowie doppelter Code überprüft. Außerdem stehen weitere optionale Checks für die Java 2 Platform Enterprise Edition (J2EE) zur Verfügung. Ferner können auch eigene Checks (in Java) realisiert werden. 3.3. Bewertung Checkstyle ist ein voll konfigurierbares mächtiges OpenSource-Tool für Code-Reviews. Aufgrund der großen Verbreitung sind für alle gängigen Java-IDEs Plugins verfügbar, die einfach handzuhaben sind. Ohne Konfiguration werden die Code-Konventionen von Sun benutzt, die bereits eine sehr große Hilfe bei der Programmierung darstellen. Über die XML-Dateien lassen sich relativ einfach eigene Konfigurationen erstellen. Reicht dies nicht aus, so können in Java eigene Checks implementiert werden. 14 4. PMD 4.1. Programmbeschreibung PMD ist ein Open-Source-Tool (http://pmd.sourceforge.net/), das dabei hilft kleine „Stilfehler“ und auch Probleme und Fehler, die im Programm auftauchen können, zu beseitigen. Das Tool gibt es als Plugin für viele bekannte und weit verbreitete IDEs wie z.B. JDeveloper, Eclipse, JBuilder, NetBeans, Maven, Emacs oder Ant. Abbildung 4.1 zeigt einen Screenshot von PMD in der Eclipse-IDE in einem geöffneten Projekt. Abbildung 4.1.: Screenshot von PMD als Eclipse-Plugin 15 4. PMD In Abbildung 4.1 erkennt man den Quellcode und im unteren Teil die Auflistung der Fehler, die PMD entdeckt hat. Es lässt sich über die Prioritätsstufen 1-5 auswählen, welche Art von Fehlern angezeigt werden soll. Priorität 1 bezeichnet hierbei schwerwiegende Fehler und Prorität 5 kleine, unrelevante Stilfehler. PMD setzt sich vor allem mit folgenden Arten von Fehlern auseinander: • Leere Try-Catch-, Finally-, Switch-Blöcke • Nicht verwendete Variablen und Methoden • Variablenbenennung und Sichtbarkeit von Variablen • Leere if-else Konstrukte • Komplizierte und komplexe Konstrukte, die vereinfacht werden können Bei leeren Blöcken weist PMD darauf hin, dass diese unnötig sind und entfernt werden können. Entsprechend verhält sich das Tool bei Variablen und Methoden, auf die niemals zugegriffen wird, oder auch bei leeren if-else-Konstrukten. Für die Variablenbenennung meldet das Tool, wenn Variablen, die nicht als Laufvariablen verwendet werden, kurze Namen wie z.B. Object o = new Object verwendet werden und weist darauf hin, dass man aussagekräftige Namen verwenden soll oder Variablenbenennungen wie z.B. value nicht aussagekräftig sind und diese Variablen anders benannt werden sollen. Bei der Sichtbarkeit von Variablen meldet das Tool, wenn z.B. eine Variable nur lokal von einer Methode gelesen und geschrieben wird, die Variable aber weiträumiger sichtbar deklariert wurde, dass sie lokal deklariert werden kann. Weiterhin wird auch geprüft, ob eine öffentliche Variable nicht auch private deklariert werden kann oder, ob Variablen nicht als final Konstanten verwendet werden können. Ein weiteres Augenmerk richtet PMD auf komplizierte und komplexe Code-Konstrukte. So wird z.B. geprüft, ob es mehrfach auftretende lange Code-Konstrukte gibt, die durch eine Methode ersetzt werden können, oder bei Ausgaben Strings, die jedes mal als "<STRING>" angegeben werden durch eine Konstante ersetzt werden können. Dies macht den Code besser lesbar und übersichtlicher. Auch wird bei extrem großen Klassen darauf hingewiesen, dass es besser wäre diese Klasse in mehrere kleine Klassen aufzuteilen. Dies macht den Code schneller und auch übersichtlicher. 16 4. PMD 4.2. Konfiguration von PMD PMD lässt sich (abhängig von der IDE) über eine GUI oder auf Kommandozeilenbasis konfigurieren. Hier wird dann konfiguriert, welche Regel (de)aktiviert werden soll. Es ist jedoch möglich auch eigene Regeln für PMD aufzustellen und diese dann in das Tool einzubinden. 4.3. Arbeitsweise PMD hat definierte Regeln und prüft den Quellcode, ob er den Regeln entspricht. Im Detail arbeitet PMD folgendermaßen: • PMD gibt den Inhalt der Klasse an einen Parser weiter • PMD bekommt von dem Parser eine Referenz auf einen Syntax-Baum des Codes • PMD prüft den Syntax Baum auf Deklarationen und Verwendungen von Variablen und Methoden • Jede Regel wird auf den Syntax-Baum angewendet und geprüft • Jede Regelverletzung wird gespeichert und je nach Anwendung entsprechend angezeigt 4.4. Bewertung PMD ist ein Tool, das einfache, kleine Verbesserungen gibt, die den Code übersichtlicher, verständlicher und besser lesbar machen. Es ist speziell für die nicht-kommerzielle Nutzung sehr gut geeignet, da es auf viele Stilfehler aufmerksam macht und auch redundanten Code erkennt und sich dieses Problem dadurch beheben lässt. Der Nachteil vom PMD ist, dass es bei großen Projekten (>> 100 Klassen) sehr speicherintensiv und vor allem langsam arbeitet. Jedoch ist es für kleinere Projekte gut einsetzbar. 17 5. FindBugs 5.1. Programmbeschreibung Das Open-Source-Tool FindBugs (http://findbugs.sourceforge.net/) ist ein CodeReviewing Tool für Java, das im Vergleich zu anderen Tools weniger auf den Programmierstil, sondern mehr auf Schwachstellen und Fehler im Code prüft. FindBugs sucht dabei in den .class-Dateien nach sogenannten „Bug-Patterns“. Hierbei handelt es sich um Code-Konstrukte, die zu Schwachstellen und Fehlern führen können. Bug-Patterns enstehen durch falsche Anwendung der Klassenbibiotheken oder schlechte Implementierungen. Das Tool besitzt eine grafische Oberfläche, lässt sich aber auch kommandozeilenorientiert steuern. Das Tool gibt es auch als Eclipse Plugin bei dem man den Code eines Projekts sehr einfach auf seine Schwachstellen prüfen lassen kann und die Fehler schnell beheben kann. Bisher ist das Tool in der Lage, den Code in Hinblick auf folgende Aspekte zu überprüfen: • Korrektheit • Performance • Internationalisierung • Multithreading Korrektheit • Stil • Bösartige Code Schwachstellen Wenn FindBugs einen Fehler oder eine Schwachstelle entdeckt, wird auf diese mit einer entsprechenden Meldung hingewiesen, um welche Art von Fehler es sich handelt. Es lässt sich auch eine detailliertere Fehlerbeschreibung aufrufen. Hierdurch kann dieser Fehler oft einfach behoben werden. 18 5. FindBugs Beispiel für „fehlerhaften“ Quellcode: Listing 5.1: Test.java 1 public c l a s s Test extends Thread { 2 public s t a t i c S t r i n g s ; 3 public s t a t i c F i l e f i l e ; 4 5 public s t a t i c void main ( S t r i n g [ ] a r g s ) { 6 s = new S t r i n g ( ) ; 7 f i l e = new F i l e ( " t e s t . f i l e " ) ; 8 try { 9 B u f f e r e d R e a d e r i n = new B u f f e r e d R e a d e r 10 (new F i l e R e a d e r ( f i l e ) ) ; 11 s = in . readLine ( ) ; 12 } catch ( FileNotFoundException e ) { 13 } catch ( IOException e ) { 14 } 15 System . out . p r i n t l n ( s ) ; 16 } 17 18 public Object t e s t ( ) { 19 start (); 20 Object o = null ; 21 return o ; 22 } 23 24 public void run ( ) { 25 f i l e = new F i l e ( " t e s t 1 . f i l e " ) ; 26 try { 27 B u f f e r e d R e a d e r i n = new B u f f e r e d R e a d e r 28 (new F i l e R e a d e r ( f i l e ) ) ; 29 s = in . readLine ( ) ; 30 } catch ( FileNotFoundException e ) { 31 } catch ( IOException e ) { 32 } 33 } 34 } 19 5. FindBugs Meldungen, die FindBugs zum Code in Listing 5.1 liefert: Field should be package protected: Die beiden öffentlich sichtbaren Variablen sollen protected gesetzt werden, da sonst aus allen Klassen heraus auf sie zugegriffen werden kann. Method invokes dubious new String() constructor; just use : Ein String sollte nicht mit String s = new String(); angelegt werden, sondern mittels String s = ""; Write to static field from instance method: Wenn aus einer vom Konstruktor aus ausgeführten Methode auf statische Objekte der Klasse schreibend zugegriffen wird, kann dies zu Problemen führen. Method may fail to close stream: Diese Fehlermeldung weist darauf hin, dass ein FileStream nicht geschlossen wurde oder evtl. nicht geschlossen werden kann. Der Code lässt sich trotzdem ohne Probleme kompilieren und auch ausführen. Jedoch kann es in größeren Projekten zu Problemen und Fehlern oder zu Schwachstellen im Code durch die nicht sicher geschlossenen Streams kommen. Diese Schwachstellen lassen sich durch FindBugs einfach und schnell auffinden. 5.2. Konfiguration von Findbugs Das Tool FindBugs lässt sich als Eclipse Plugin einfach und für jedes Projekt individuell konfigurieren. Es müssen dazu die Projekteigenschaften geöffnet werden. Hier lässt sich FindBugs dann konfigurieren. Es kann ausgewählt werden, ob FindBugs automatisch nach Schwachstellen suchen soll oder ob die Suche manuell gestartet werden muss. Weiterhin können Prioritäten eingestellt werden, d.h. es kann eingestellt werden, ob schon „kleinere“ Fehler oder Schwachstellen angezeigt werden sollen oder ob nur wirkliche Sicherheitslücken markiert werden sollen. Gewählt werden kann, ob auf Code Korrektheit, Performance, Internationalisierung, Multithreading Korrektheit, Stil oder bösartige Code Schwachstellen geprüft werden soll. Weiterhin lässt sich einstellen, welches der beim Punkt Arbeitsweise beschriebenen Bug-Patterns verwendet werden soll. Durch diese Art von Konfiguration lässt sich praktisch beliebig einstellen, welcher Fehler und welche Schwachstelle angezeigt werden sollen. 20 5. FindBugs 5.3. Arbeitsweise Das Tool arbeitet mit einem sogenannten Bug-Pattern-Detector. Dieser Detektor prüft die einzelnen Klassen auf die entsprechenden Fehler. Für jede Art von Fehler gibt es ein Bug-Pattern. Dadurch lässt sich der Bug-Pattern-Detector nahezu beliebig durch neu implementierte Klassen erweitern. [Vio04] 5.4. Bewertung Das Tool FindBugs ist ein Tool, mit dessen Hilfe sich Fehler im Code, die zu Schwachstellen führen können, finden und beheben lassen. Das Tool arbeitet bei kleineren Projekten relativ schnell und problemlos. Jedoch kann es bei sehr großen Projekten zu Problemen und Fehlern kommen. Speziell für die Entwicklung von Applikationen, die viel mit Streams und Threads arbeiten, ist FindBugs zu empfehlen, da es Fehler aufzeigt, die evtl. beim Ausführen der Applikation auftreten oder zu Sicherheitslücken der Applikation führen könnten. Was bei dem Tool jedoch fehlt, ist die Möglichkeit, dass man an einer bestimmten Stellen eine Fehlermeldung deaktivieren kann, weil es an der Stelle vielleicht trotzdem gewünscht ist genau so zu programmieren. Insgesamt ist FindBugs ein Tool, das für eine saubere, fehlerfreie Programmierung sehr nützlich und hilfreich ist. 21 6. Fortify 6.1. Programmbeschreibung Das Tool „Fortify Source Code Analysis“ des Unternehmens Fortify Software 1 dient Java und C++ Quellcode auf Fehler, Schwachstellen, Sicherheitslücken und zusätzliche Eigenschaften des Codes zu überprüfen. Das Tool setzt sich aus mehreren Komponenten zusammen, die unterschiedliche Aufgaben übernehmen um einen großen Teil der Schwachstellen im Code zu identifizieren und dem Entwickler zu melden. Fortify erkennt inzwischen über 500 Arten von Schwachstellen und Sicherheitslücken im Quellcode. Fortify bietet die Möglichkeit Sicherheitslücken zu entdecken, bevor die Applikation veröffentlicht wird und z.B. Hacker sie entdecken und ausnutzen können. Das Tool ist als Windows- und Linux-Anwendung erhältlich und lässt sich zusammen mit den gängigen Entwicklungsumgebungen nutzen. 6.2. Arbeitsweise Das Tool setzt sich aus mehreren Komponenten zusammen, die gemeinsam viele Schwachstellen entdecken sollen. Fortify nutzt dabei zum einen eine Technik namens „Extended Static Checking“. Diese Technik soll helfen, mögliche Buffer Overflows oder Formatkettenfehler zu entdecken. Das Tool soll dem Programmierer schon beim Entwickeln mitteilen, dass die Funktion, die er nutzen möchte, möglicherweise riskant ist. Hierbei wird im Vergleich zu vielen anderen Tools der Quellcode und seine Eigenschaften geprüft und nicht erst das fertige Programm. Das Tool arbeitet dabei ähnlich wie ein Compiler. Der Code wird vom Tool abgearbeitet und wie bei einem Compiler, der den Code an einer bestimmten Stelle nicht parsen kann, wird mitgeteilt, welche Risiken an dieser Stelle auftreten können. 1 http://www.fortifysoftware.com 22 6. Fortify Fortify Source Code Analysis hat auch eine Serverkomponente, die Teile des Quellcodes mit eigenen Eingaben testet und prüft, wie diese Eingaben intern weiter verarbeitet werden. Weiterhin besitzt das Tool eine Komponente namens „Red Team Workbench“. Diese Applikation simuliert Hackversuche und bösartiges Verhalten und meldet, falls ein Hackversuch erfolgreich war. [Sei04] 6.3. Bewertung Fortify ist ein starkes, vielseitiges Tool zum Entdecken von Schwachstellen und Sicherheitslücken im Quellcode. Es entdeckt diese schon bei der Entwicklung und macht dadurch spätere Sicherheitsupdates überflüssig. Das Tool ist jedoch nicht frei verfügbar, deswegen empfiehlt sich Fortify Source Code Analysis eher im kommerziellen Bereich eingesetzt zu werden. 23 7. Fazit 7.1. Zusammenfassung Code-Review ist eine wichtige Maßnahme zur Sicherstellung der inneren Softwarequalität. Vorteile sind unter anderem weniger Fehler zur Laufzeit, Behebung von Sicherheitslücken, eine bessere Lesbarkeit des Quelltextes und dadurch bessere Wartbarkeit sowie höhere Wiederverwendbarkeit. Zahlreiche Aspekte des Code-Reviews lassen sich automatisieren und mittels freier Tools schnell und einfach durchführen. Dabei sollte je nach Projektart, -umfang und -umfeld abwägen werden, welche Tools eingesetzt werden sollen. Bei umfangreichen, sicherheitsrelevanten Projekten kann vor allem der Einsatz von kommerziellen Tools wie beispielsweise Fortify Source Code Analysis sehr hilfreich sein. 7.2. Ausblick Sun wird in Zukunft Aspekte des Code-Reviews immer stärker berücksichtigen. Der Java-Compiler des Java Development Kit 5.0 bietet mitteles der Option -Xlint bereits fünf Tests. Unter anderem kann bei switch-Anweisungen überprüft werden, ob eine break-Anweisung fehlt oder ob in einem finally-Block eine Exception geworfen wird. [Tam05] 24 Literaturverzeichnis [Büt03] Büttcher, Stefan: Code-Reviews & Code-Generierung als Bestandteile des Entwicklungsprozesses. http://stefan.buettcher.org/cs/epta/ codereviews.pdf, Januar 2003. [Rup05] Rupp, Heiko W.: Bessere Code-Qualität mit zusätzlichen Tools/EclipsePlugins. http://www.java-forum-stuttgart.de/folien/E4_syngenio.pdf, Juli 2005. [Sei04] Seiler, Martin: Fehler schon während der Entwicklung entdecken: Fortify checkt Code auf Schwachstellen. Computerwoche, April 2004. [SM05] Schneider, Johannes und Matthias Mergenthaler: Offizielle Homepage von CAP (Code Analysis Plugin), 2005. aufgerufen am 14. Oktober 2005. [Tam05] Tamm, Michael: Alles geregelt: Automatisches Code-Review. iX, Januar 2005. [Vio04] Violka, Karsten: Das Werkzeug FindBugs spürt in Java-Programmen problematische Codezeilen auf. c’t, April 2004. 25 A. Freie Tools für Java-Code-Review Die folgende Zusammenstellung soll einen Überblick über verschiedene kostenlose CodeReview-Tools für Java geben. Die Informationen über die Tools wurden zum Teil [Tam05] entnommen. CAP (Code Analysis Plugin) ist ein Eclipse-Plugin zur Überprüfung der Software-Architektur. Die Ergebnisse werden in verschiedenen Diagrammen visualisiert. Checkstyle kontrolliert die Einhaltung von Code-Konventionen. Das Tool ist voll konfigurierbar und bietet über hundert fertige Checks. DoctorJ erkennt unter anderem Rechtschreibfehler im Code. Derzeit sind allerdings nur englische Dictionaries verfügbar. Außerdem vergleicht das Tool Javadoc-Kommentare mit dem zugehörigen Code. ESC/Java2 (Extended Static Checker for Java version 2) ist ein Tool zum Aufspüren von allgemeinen Runtime-Fehlern. Es findet NullPointerExceptions, Überschreitungen von Arraygrenzen, TypeCast-Fehler und Race-Conditions. Findbugs findet semantische Java-Fehler wie Zugriffe auf nicht initialisierte Variablen. Hammurapi beinhaltet mehr als 120 so genannte Inspektoren und kommt mit seltenen Features wie automatischen und manuellen Ausnahmen und kaskadierenden Regeln. Jalopy ist ein Tool zur Quelltextformatierung. Es ordnet gültigen Java Code nach großzügig konfigurierbaren Regeln an. Jamit (Java Access Modifier Inference Tool) überprüft Access-Modifier. Wenn möglich werden die Modifier durch restiktivere Modifier ersetzt. Java Path Finder ist eine JVM zum Aufspüren von Schwachstellen wie nicht aufgefangenen Exceptions oder Deadlocks. 26 A. Freie Tools für Java-Code-Review JCSC (Java Coding Standard Checker) dient zur Überprüfung von Namenskonventionen, des strukturellen Layouts von Klassen, sowie von Vorschriften für Klammern und Leerzeichen. Regeln können über einen grafischen Editor definiert werden. JDepend Ist wie CAP ein sehr mächtiges Tool zur Überprüfung der Software-Architektur. Jikes Der OpenSource-Compiler Jikes meldet auch zahlreiche Code-Warnungen. JLint findet Fehler, Inkonsistenzen und Synchronisations-Probleme durch ProgrammflussAnalyse. Relativ schnell, da es sich um ein C-Programm handelt. JWiz (JavaWizard) findet typische Java-Fehler (derzeit rund 50 Arten) wie beispielsweise die Benutzung von == anstatt der equals-Methode bei Stringvergleichen. Macker kontrolliert die Einhaltung selbst definierter, struktureller Regeln, beispielsweise dass Klassen des UI-Layers nicht auf solche des Datenlayers zugreifen dürfen. PMD überprüft Namenskonventionen, entdeckt unbenutzten Code, überprüft das Klassendesign sowie Klammer- und Leerzeichenvorschriften. Neben einer Ant-Task sind für zahlreiche IDEs Plugins verfügbar. Simian untersucht Quellcode (Java, C++, C#, Cobol, JSP und andere) nach doppelten Codefragmenten. 27