Beruflich Dokumente
Kultur Dokumente
Thomas Gängler
1 Einleitung
Software-Qualität und das damit verbundene Code-Quality-Management spie-
len eine große Rolle bei modernen Software-Entwicklern. Dass die Wahrung von
Qualitätskriterien mit wachsender Codezeilenanzahl eines Projektes immer kom-
plexer und schwieriger wird, ist ein einfache logische und allseits bekannte Folge.
Die immer umfangreicheren Entwicklungsumgebungen oder separate Werkzeuge
sollen dem Entwickler dabei einen großen Teil der manuelle Test- und Analy-
searbeit abnehmen. Trotzdem herrscht bei den beteiligten Rollen im Software-
entwicklungsprozess noch oft Unklarheit bei folgenden Fragen. Welche Möglich-
keiten zum Test- und Analysieren gibt es berhaupt? Welches Werkzeug erledigt
welche Aufgabe im Qualitätssicherungszyklus? Deshalb soll dieser Aufsatz einen
Einblick und Überblick in die Vielzahl vorhandener Test- und Analysewerkzeuge
und deren Einsatzgebiete beschrieben. Als Erstes soll eine Typisierung für Werk-
zeuge zur Sicherung von Software-Qualität vorgestellt werden und insbesondere
auf die Kategorien zum Testen und zur Codeanalyse eingegangen werden (s.
Kap. 2). Dabei werden immer wieder Beispielwerkzeuge genannt, wobei der Fo-
kus i.A. auf frei erhältlichen Vertretern liegt und diese oft auch als Plug-in für
die Eclipse Entwicklungsumgebung erhältlich sind.
Danach wird auf die, erweiterten statischen Analysewerkzeuge eingegangen, wel-
che durch kurze Beschreibungen von zwei Beispielen abgerundet wird (s. Kap.
3). Anschließend folgt ein Kapitel über Portale (s. Kap. 4). Diese Form ver-
eint mehrere Werkzeugtypen in auf sinnvolle Art und Weise, und erleichtert die
2
2 Werkzeugtypen
Die Unterteilung der Werkzeugtypen hält sich grob an die Vorlage von Ligges-
meyer [6]. Dabei wird insbesondere auf die Typen dynamische Testwerkzeuge
(s. Kap. 2.1) und statische Analysewerkzeuge (s. Kap. 2.2) eingegangen. Diese
kooperieren oft miteinander bzw. sind ineinander integriert und bilden gene-
rell die zahlenmäßig stärkste Kategorie. Deshalb werden sie in diesem Aufsatz
besonders analysiert. Des weiteren werden anschließend noch die beiden Werk-
zeugtypen formale Verifikationswerkzeuge (s. Kap. 2.3), und modellierende und
analysierende Werkzeuge (s. Kap. 2.4) vorgestellt, welche zwar Grundlagen für
die erweiterten statischen Analysewerkzeuge (s. Kap. 3) bereitstellen, generell
aber gesondert und ausführlicher betrachtet werden müssen.
2
http://www.eclipse.org/tptp/
3
http://www.coverity.com/
4
kreten Testfällen und Testdaten nötig. Durch den engen Bezug zum Quellcode
sind Werkzeuge dieser Kategorie oft programmiersprachen-spezifisch. Wie schon
beschrieben, bilden die statischen Analysewerkzeuge oft eine Einheit mit den
dynamischen Testwerkzeugen. Analog zu Diesen gibt es hier eine weitere Unter-
kategorisierung, welche nun vorgestellt wird.
Messwerkzeuge. Als erste, sehr verbreitete und recht alte Unterkategorie stehen
die Messwerkzeuge. Sie dienen zur Informationsgewinnung und -darstellung mit-
tels statischer Analyse. Hierbei wird der gesamte Quellcode eines Programms
analysiert und bestimmte Merkmale registriert. Verbreitete Maße hierfür sind:
zyklomatische Zahl, Halstead -Maße, Maße zur Datenkomplexität (z.B. Anzahl
der Klassen) oder Anzahl der Codezeilen (engl. Lines of Code) durch den Nut-
zer. Diese Maße müssen präzise definiert sein, d.h. es darf kein manueller Eingriff
während der Analyse vom Nutzer stattfinden.
Die Ergebnisse lassen sich entweder in textueller (Tabellen, Bäume) oder in gra-
fischer Form (Graphen, Diagramme) darstellen. Die Messwerkzeuge ermöglichen
es dem Entwickler oft Grenzewerte für diverse Maße zu definieren und in der Er-
gebnisdarstellung Grenzüberschreitungen aufzeigen zu lassen. Die abstrakte De-
finition der Maßberechnungen ist zwar i.A. programmiersprachen-unabhängig
aber zur Ermittlung dieser sind die Werkzeuge i.d.R. programmiersprachen-
spezifisch.
Beispiele sind das bekannte Open-Source Metrics-Plug-in für die Eclipse IDE
von Frank Sauer6 und SemmleCode von der Firma Semmle7 , welches ebenfalls
ein frei erhältliches Plug-in für die Eclipse Entwicklungsumgebung ist und u.a.
Metriken berechnen kann.
kann. Zusätzlich kann es noch diverse andere Probleme überprüfen (z.B. Erken-
nung von dupliziertem Code).
Werkzeuge zur Erzeugung von Tabellen und Grafiken. Werkzeuge dieses Typs
stellen im eigentlichen Sinn keine separate Unterkategorie von statischen Analy-
sewerkzeugen dar. Sie sind aber i.A. Bestandteil von vielen Werkzeugumgebun-
gen. Wie schon aus der Bezeichnung abgeleitet werden kann, dient dieser Werk-
zeugtyp zur Erzeugung verschiedenster Ergebnisdarstellungen, z.B. Kontroll-
fluss- und Aufrufgraphen, oder Variablen-Quer-Verweis-Tabellen.
Das Metrics-Plug-in von Frank Sauer kann solche Abhängigkeitsgraphen gene-
rieren oder die Analyseergebnisse in Tabellen mit Bäumen darstellen. Weitere
Beispiele für Werkzeugumbebungen, die eine solche Visualisierung ermöglichen
sind das kommerzielle CodeSonar von Grammatech9 oder SemmleCode, welches
Anfragen als Tabelle, Baum, Graph oder Diagramm ausgeben kann10 .
Zugriffssequenzen auf eine Variable (z.B. lesender Zugriff auf eine nicht initia-
lisierte Variable). Durch ihre essenzielle Funktionalität sind sie oftmals schon
in Compiler integriert. Die Analyse ist auf statischem Wege mit wenig Aufwand
realisierbar und stets automatisierbar. Dadurch bietet sie sichere und zuverlässli-
che Ergebnisse.
In der Eclipse Entwicklungsumgebung werden solche Fehler teilweise schon ad-
hoc bei der Programmierung ausgewertet und angezeigt (mittels Online-Fehler-
Überprüfung). Generell sind solche Werkzeuge in allen gängigen statischen Ana-
lysewerkzeugen mit enthalten (z.B. die Überprüfung auf Null-Pointer-Derefe-
renzierung).
Diese Kategorie von Werkzeugen soll nur kurz erwähnt werden, weil sie nicht dem
Hauptthema des Aufsatzes entspricht13 . Werkzeuge diesen Typs haben ihre An-
wendungsbereiche in der Risiko-, Sicherheits-, Zuverlässigkeits- und Verfügbar-
keitsanalyse. Sie sind generell eher programmiersprachen-unabhängig. Diese Art
beinhaltet effiziente Spezialisierungen bzw. Unterkategorien, z.B. FMECA14 -,
Fehlerbaumanalyse- oder Markov -Werzeuge.
Die Werkzeugumgebungen sind dabei häufig im kommerziellen Bereich angesie-
delt und beinhalten oft mehrere Werkzeugtypen dieser Kategorie. Des weiteren
besitzen die Software-Firmen oft eine langjährige Erfahrung in der Entwicklung.
12
http://www.uppaal.com/
13
für einen detaillierteren Einstieg bitte das zugehörigen Kapitel in [6] lesen
14
engl. Failure, Mode, Effects and Criticality Analysis
8
Beispielhafte Vertreter sind der Isograph Reliability Workbench 15 und das Relex
Reliability Studio 16 .
3.1 Grundstruktur
Der Aufbau dieser Analysewerkzeuge ist grafisch in der Abb. 1 visualisiert. Hier
sind klar die vier Grundkomponenten: Faktenextraktor / Dekorierer, Datenbank-
system (DBS), Analyse- und Reportkomponente zu erkennen. Dabei ist die zwei-
te Komponente nicht zwingend erforderlich, wenn die entstandenen Daten nicht
in einer Datenbank abgespeichert werden sollen. Wie aus der Grafik gut zu
erkennen ist, lässt sich der gesamte Knowledge-Discovery-Prozess leicht auto-
matisieren und z.B. das Werkzeug im Batch-Betrieb als Cron-Job ausführen. Im
Folgenden werden nun die einzelnen Bestandteile der Grundstruktur erklärt.
ein Systemmodell aus den Daten. Dessen Struktur und Inhalt wird durch ein
Systemmetamodell vorgegeben. Dabei werden Artefakte wie z.B. Verzeichnisse,
Quellcode-Dateien, Pakete, Klassen, Methoden oder Attribute erfasst. Des weite-
ren werden noch die Referenzen zwischen bestimmten Artefakttypen ermittelt.
Das sind Eigenschaften wie z.B. Enthaltenssein- und Vererbungsbeziehungen
oder Methodenaufrufe und Attributbenutzungen.
Diese Artefakttypen und Referenzarten variieren je nach Programmiersprache
(z.B. friend in C++ und implements in Java). Daraus ergibt sich das Problem
der Definition des Systemmetamodells. Entweder es werden alle vorhandenen
Unterschiede in einem universellen bzw. generischen Systemmetamodell verei-
nigt, oder es wird ein separates Modell für jede Programmiersprache erstellt.
Optional hingegen ist die Systenmodellanreicherung durch Dekorierer. Sie be-
stimmen noch nicht ermittelte Merkmale aus dem Quellcode oder Log-Dateien
eines Konfigurations-Management-Systems (z.B. CVS oder Subversion). Bei-
spiele für solche Merkmale sind u.a. Änderungshäufigkeit oder Angaben über
die Vollständigkeit der Javadoc- oder Doxygen-Kommentare. Zusätzlich können
mit Dekorierern Vorberechnungen für wiederholt benötigte Daten für die Ana-
lysephase vorgenommen werden (z.B. Berechnung der transitiven Hülle der Ver-
erbungsbeziehungen). Generell führen diese Vorberechnungen zu einem späteren
Performance-Gewinn.
Die eigentliche Datenmenge wird durch den Faktenextraktor und Dekorierer re-
duziert und es ist damit keine vollständige Rückwärtsgenerierung möglich.
Laufzeit der Berechnungen, welche durch Wahl geeigneter Hardware, Wahl eines
geeigneten DBSs und Anfrageoptimierung verbessert werden kann.
3.2 Technik
Die erweiterte statische Analyse hat ihre Wurzeln, in den schon erwähnten,
Model-Checking-Technologien und in der abstrakten Interpretation [2]. Sie nutzt
symbolischen Eingaben, d.h. abstrakte Werte, um viele konkrete Werte gleichzei-
tig abzudecken und somit effizient zu arbeiten. Folglich arbeiten diese Werkzeu-
ge im Kontrast zu dynamischen Testwerkzeugen, wo konkrete Werte verwendet
werden. Dies hat den Vorteil, das i.A. einen höhere Abdeckung erzielt wird ohne
spezielle Testfallgenerierungen. Dies geschieht durch die abstrakte Betrachtung
und Auswertung der Pfade und Bedingungen.
3.3 Fachterminologie
Die Technologie der erweiterten statischen Analyse führte zur Bildung einer
Reihe von neuen Fachbegriffen. Die Grundlage bilden die Fehlermuster, wel-
che Problemmuster genannt werden. Dies ist die spezielle Beschreibung eines
wiederkehrenden und i.d.R. erkennbaren Fehlverhaltens von Programmcode. Sie
entstehen z.B. durch die unterschiedlichen Eigenschaften der Programmierspra-
chen, falsch verstandene Schnittstellen-Methoden oder einfache kleine Versehen
(z.B. Nutzung des falschen Boolean-Operators). Diese Fehlermuster werden dann
nach ihrer Art in Fehlerklassen zusammengefasst. Dabei gibt es verschiedene
Ansätze und Kategorisierungen. Beispiele für Fehlerklassen sind unvorhersehba-
re/ kritische Fehler (z.B. Pufferüberlauf/-unterlauf), Speicher-Allokations-Fehler
(z.B. doppeltes Freigeben) oder Konkurrenz-Fehler (z.B. doppeltes Sperren von
kritischen Abschnitten). Manche Kategorien beziehen sich nur auf bestimmte
Programmiersprachen. Demzufolge spielen Speicher-Allokierungs-Fehler in Java,
welches eine automatische Speicherverwaltung besitzt, keine Rolle. Letztendlich
werden die Problemmuster in Qualitätsindikatorenkataloge [8] oder Fehlermu-
sterkatalogen zusammengefasst. Diese variieren dann von Werkzeug zu Werk-
zeug und können teilweise noch selbst von den Entwicklern definiert werden.
Ein wichtiger Vergleichswert zwischen der Leistungsfähigkeit der verschiedenen
Werkzeuge ist die sogenannte False-Positive-Rate [9]. Diese fasst die Warnun-
gen zusammen, welche gar keine richtigen Fehler sind. Dem gegenüber steht
die False-Negative-Rate, welche die Anzahl der nicht gefunden Fehler widerspie-
gelt. Generell sind die Entwickler von erweiterten statischen Analysewerkzeugen
bestrebt ein geringe False-Positive-Rate bei ihren Analysen zu erzielen. Diese
variiert aber von Fehlermuster zu Fehlermuster.
11
1 void f 0 ( ) { i f ( ∗ ) { A; } e l s e { B ; } } // 2 Pfade
2 void f 1 ( ) { f 0 ( ) ; f 0 ( ) ; } // 4 Pfade
3 void f 2 ( ) { f 1 ( ) ; f 1 ( ) ; } // 16 Pfade
4 ...
5 void f i ( ) { f i − 1 ( ) ; f i − 1 ( ) ; } // 2ˆ(2ˆ i ) Pfade
Listing 1.1. Beispiel für die Entwicklung der Pfadanzahl [9]
Nach dem derzeitigen Stand der Technik können erweiterte statische Analyse-
werkzeuge trotzdem keine 100%-ige Pfadabdeckung18 ermöglichen [9]. Dies liegt
in der exponentiellen Pfadanzahlerhöhung bei Schleifen und Rekursionen.
Wie man im Listing 1.1 sieht, steigt die Anzahl der Pfade recht schnell an. In der
ersten Methode befindet sich eine Bedingung woraus sich zwei Pfade ergeben.
Danach werden in den nachfolgenden Methoden die Vorherigen jeweils zweimal
aufgerufen. Somit ergibt sich durch die azyklischen, interprozeduralen Metho-
denaufrufe ein doppelt exponentieller Anstieg der Anzahl der Pfade.
Des weiteren gewährleisten die Zeiger-Analyse-Algorithmen noch keine exak-
te Analyse [9]. Die Folge sind falsche Verweise (nicht durchführbare Verweise)
die in den Aufrufgraphen auftauchen oder fehlende Verweise, welche z.B. durch
redundante Bedingungen entstehen. Generell ignorieren die Werkzeuge solche
Ausnahmen die zu unvorhersehbaren Ausführungspfaden führen. Auf der ande-
ren Seite fordern aber diverse Sicherheitsstandards (z.B. DO-178B Standard für
die Luftfahrt) 100%-ige Abdeckung in verschiedenen Risikoklassen.
Eine andere Grenze der erweiterten statischen Codeanalyse ist die eingeschränkte
Modellierung von konkurrienden Thread -Zugriffen (engl. mutlithreading). Hier-
bei werden oft nur Annäherungen vorgenommen.
Dem allgemeinen Problem, der Reduzierung der False-Positive-Rate, wird ver-
sucht sich mit verschiedenen Techniken anzunähern. Auf der einen Seite werden
die Werkzeuge mit automatischen Lernfunktionen ausgestattet. Diese versuchen
gebräuchlichen Programmierausdrücke/ -muster und deren Absichten zu verste-
hen. Auf der anderen Seite kann der Nutzer selbst bestimmte Verhaltensweisen
definieren um somit die False-Positive-Rate zu verringern.
Letztendlich können diese Werkzeugtypen aber keine logischen Fehler im Pro-
grammablauf erkennen. Diese lassen sich aber gut durch dymamische Tests her-
ausfinden.
3.5 Beispiele
Hierbei sollen nun kurz zwei frei erhältliche Beispielwerkzeuge für die erweiter-
te statische Analyse betrachtet werden und weitere Anwendungen nur genannt
werden.
FindBugs. Dies ist ein Open-Source-Projekt von der Universität von Maryland
für die Programmiersprache Java und als Eclipse Plug-in erhältlich19 . Es analy-
18
Obwohl es andere Hersteller behaupten; s. [7]
19
http://findbugs.sourceforge.net/
12
siert mittels Detektoren, die auf den Visitor -Entwurfsmuster beruhen, den Java-
Bytecode. Dabei behaupten die Entwickler immer eine False-Positive-Rate ge-
ringer als 50% zu erzielen [5]. Durch seine Struktur ist es beliebig mit neuen
Fehler-Detektoren erweiterbar. Bei der Analyse werden die anfallenden Daten
direkt weiter verarbeitet und ausgewertet.
Mittlerweile besitzt das Werkzeug schon einen ziemlich umfangreichen Fehlermu-
sterkatalog der sich in verschiedene Kategorien unterteilt. Des weiteren ermög-
licht es durch diverse Filter die Analyse einzuschränken und diese z.B. nur mit
gewissen Detektoren durchzuführen oder nur auf bestimmte Klassen anzuwen-
den. Letztendlich kann man die Ergebnisse als XML-Report exportieren und
immer wieder in das Programm zur Fehlerauswertung und -beseitigung laden.
SemmleCode. Das schon bereits erwähnte Werkzeug SemmleCode ist ein ziemlich
umfangreiches und flexibles Analysewerkzeug. Es ist als frei erhältiches Eclipse
Plug-in verfügbar und basiert auf der objekt-orientierten, Allzweck-Anfragespra-
che .QL, welche mehrere Ansätze in sich vereint. Somit hat sie eine starke Ähn-
lichkeit zu SQL, nutzt die Fixpunkt-Semantik von Datalog 20 , und gebraucht
die Eindhoven Quantifier Notation zur simplen Konstruktion von Aggregat-
Funktionen21 .
Durch diese erweiterte Anfragesprache ist es möglich eine Vielzahl der Aufgaben
der statischen Analyse abzudecken und mit einer guten Performance zu berech-
nen und ausgeben zu lassen, z.B. Fehler finden, Metriken berechnen, Abhängig-
keiten zu verstehen oder Anfragen anzupassen und neu zu definieren. Die anfal-
lenden Daten der Analyse werden in einer relationalen Datenbank abgespeichert.
4 Portale
Wie der aufmerksame Leser vielleicht schon während des Lesen dieses Aufsatzes
festgestellt hat, reicht ein einzelnes Werkzeug heutzutage nicht mehr aus um alle
Bereiche der Codeanalyse zur Qualitätssicherung abzudecken. Deshalb werden
die einzelnen Werkzeugtypen oft in einer Werkzeugumgebung zusammengeführt
(z.B. TPTP ) oder ein Werkzeug ist so flexibel um mehrere Kategorien gleich-
zeitig abzudecken (z.B. SemmleCode).
Darauf aufbauend erstreckt sich das Gebiet der Portale zur Codeanalyse, welche
eine zentralisierte, komplexe Datenerhebung systemweit ermöglichen und diese
20
Welches eine einfache Form von logischer Programmierung ist
21
Für eine detailierte Beschreibung von .QL bitte [3] lesen
22
http://www.castsoftware.com/Default.aspx
13
23
Welche auch nur auf die zu bearbeitenden Module beschränkt werden können
14
für Portale sind das schon erwähnte Prevent 24 , Insight von Klocwork25 und die
Client/ Server-Werkzeuge von PolySpace26 .
5 Fazit
Nachdem nun eine Vielzahl von Werkzeugtypen, deren Einsatzgebiete mit Bei-
spielen vorgestellt wurde, sollte klar sein, dass die Nutzung solcher Hilfsmittel
in einem guten Software-Entwicklungs-Prozess unerlässlich aber auch teilwei-
se recht einfach ist. Die modernen Werkzeugumgebungen zum Testen und zur
Codeanalyse ergänzen oft die komplexen Entwicklungsumgebungen oder binden
sich gut in diese als Plug-in ein. Die Vertreter aus dem Open-Source-Bereich
brauchen sich nicht vor den kommerziellen Konkurrenten zu verstecken, da die
kostenlosen Projekte oft ein breites Industriekonsortium hinter sich haben (s.
TPTP ).
Eine logische Folge, ist auch die Vereinigung mehrere Kategorien in einer Werk-
zeugumgebung. Generell bilden die statischen Typen eine gute Ergänzung zu
den dynamischen Testwerkzeugen, ersetzen diese aber nicht. Sie helfen dem Ent-
wickler trotzdem effizient echte Fehler zu finden und somit die Software-Qualität
zu steigern.
Durch die breite Automatisierung reduzieren statische Analysewerkzeuge die Ko-
sten im Entwicklungsprozess und sparen natürlich eine Menge Zeit ein. Mittels
24
Welches sehr gut mit dem ThreadAnalyzer von Coverity zusammenarbeitet und auch
als Eclipse Plug-in in der Java-Version erhältlich ist
25
http://www.klocwork.com/default.asp
26
http://www.mathworks.com/
15
Literatur
1. Liggesmeyer Home [online]. Available from: http://www.liggesmeyer.de.
2. P. Anderson. Detecting Bugs in Saftey-Critical Code. Dr. Dobb’s Journal, March,
2008.
3. O. de Moor, M. Verbaere, E. Hajiyev, P. Avgustinov, T. Ekman, N. Ongkingco,
D. Sereni, and J. Tibble. Keynote Address: .QL for Source Code Analysis. Technical
report, Semmle Limited, 2007.
4. M. Harman and R. M. Hierons. An Overview of Program Slicing [online]. Available
from: http://www.dcs.kcl.ac.uk/staff/mark/sf.html.
5. D. Hovemeyer and W. Pugh. Finding Bugs is Easy. Technical report, Dept. of
Computer Science, University of Maryland, 2004.
6. P. Liggesmeyer. Software-Qualität: Testen, Analysieren und Verifizieren von Soft-
ware. Spektrum, Akademischer Verlag, 2002.
7. Misc. Prevent SQS C/C++. Technical report, Coverity, Inc., 2008.
8. F. Simon, O. Seng, and T. Mohaupt. Code-Quality-Management. dpunkt.verlag,
2006.
9. M. Zarins. Overview of GrammaTech Static-Analysis Technology. Technical report,
GrammaTech, Inc., 2008.