Software-Visualisierung und -Analytics: Stand der Technik und Perspektiven

Seite: 2/3

Welche Arten von Visualisierungen und welche Interaktionsformen gibt es?

Graphen sind eine weit verbreitete Form der Visualisierung in der Wartung. Sie bieten sich in natürlicher Weise an für Abhängigkeiten zwischen Software-Teilen und andere binäre Relationen. Auch die meisten UML-Diagrammarten wie Klassendiagramme oder Kollaborationsdiagramme sind letzten Endes Graphen. Ein Beispiel für die Visualisierung von Klassendiagrammen ist in Abbildung 1 gezeigt (siehe Bildergalerie). Das UML-Diagramm selbst ist in der rechten oberen Ecke zu finden. Darum herum findet man alternative Sichten. Unterhalb des Diagramms wird Quellcode angezeigt. Die Darstellung weist eine Reihe wichtiger Eigenschaften auf. Es stellt beispielsweise verschiedene Sichten dar, abstraktere und detaillierte.

Bildergalerie
Bildergalerie mit 14 Bildern

Es ist bei Software-Visualisierungen im Allgemeinen auch notwendig, einen Bezug von der Visualisierung zum Quellcode herzustellen, wie es in dieser Darstellung geschieht. Links vom UML-Diagramm sieht man eine Darstellung der Hierarchie. Auch dies ist typisch, weil große Systeme hierarchisch strukturiert sind. Unter der Hierarchie findet man die Darstellung von Attributen eines ausgewählten Elements des UML-Diagramms. Hier lassen sich Details abfragen.

Diese Visualisierung unterstützt das von Shneiderman vorgeschlagene Vorgehen, das jede Visualisierung nach anstreben sollte (so genanntes „Mantra der Informationsvisualisierung“): Zuerst soll eine Übersicht geboten werden. Dann kann man Informationen suchen und filtern. Schließlich erhält man Details auf Anfrage.

UML-Werkzeuge können objektorientierte Konzepte mit graphischen Mitteln der UML darstellen. Was sich durch UML-Konzepte nicht ausdrücken lässt, kann man nicht damit visualisieren. Auch die Perspektiven, aus denen die Software dargestellt wird, sind vorgegeben und vom Benutzer meist nicht selbst frei festzulegen beziehungsweise zu erweitern.

Aus diesen Gründen ist es wünschenswert, generischere Darstellungsmöglichkeiten bereitzustellen, das heißt, alternative visuelle Sprachen von Nutzern selbst bestimmen zu lassen. Generische Darstellungen von Graphen und Möglichkeiten zur Erweiterung werden beispielsweise von dem in den Neunzigerjahren von Hausi Müller entwickelten Grapheneditor Rigi angeboten. Rigi wurde für die Visualisierung von Software mit Hilfe getypter Graphen entwickelt und ist eines der frühesten Werkzeuge seiner Art, das viele andere Werkzeuge maßgeblich beeinflusst hat. Es wird mittlerweile nicht mehr entwickelt, hat aber die Entwicklung vieler späterer Werkzeuge inspiriert.

Eine Darstellung eines Abhängigkeitsgraphen mit Rigi ist in Abbildung 2 gezeigt. Es zeigt Zusammenhänge von Funktionen und Datentypen. Die Typen der Knoten werden durch verschiedene Ikone und Farben unterschieden. Die Farbe der Kanten drückt deren Semantik aus, hier beispielsweise wird zwischen Funktionsaufrufen und Verwendungen von Datentypen in der Signatur von Funktionen farblich differenziert.

Die Graphen, die Rigi verarbeiten kann, sind generisch. Das heißt, ein Verwender von Rigi kann die Typen der Knoten und Kanten selbst festlegen und Attribute frei spezifizieren. Generische Filter und Navigationsmöglichkeiten stehen für den Endanwender zur Verfügung. Zur Erweiterbarkeit bietet Rigi eine Scripting-Schnittstelle, die den Graphen abfragen und manipulieren kann. Auf diese Weise können eigene Sichten geschaffen werden. Der graphische Editor ist somit programmierbar.

Die Graphen in Rigi sind hierarchisch. Das heißt, ein Knoten kann anderen Knoten enthalten. Das Zusammenfügen von Knoten kann entweder interaktiv durch den Benutzer vorgenommen werden oder aber programmatisch über die Scripting-Schnittstelle. Auf diese Weise kann man große unübersichtliche Graphen in Gruppen zusammenfassen. Das Kriterium für die Gruppierung ist anwendungsspezifisch und wird vom Benutzer beigesteuert. Die Forschung zum so genannten Software-Clustering beschäftigt sich mit dem automatisierten Gruppieren von Software-Einheiten. Abbildung 3 zeigt das Ergebnis eines solchen automatisierten Clusterings. Hier wurden die Funktionen mit den Datentypen, die in ihrer Signatur auftauchen, zu abstrakten Datentypen zusammengefasst.

Eine Alternative zu Graphen zur Darstellung binärer Relationen sind Adjazenzmatrizen. Ein Aufrufgraph kann zum Beispiel wie in Abbildung 4 gezeigt dargestellt werden. An den beiden Achsen sind alle Funktionen aufgeführt. An der Koordinate wird ein Punkt gesetzt, wenn die Funktion an der x-Achse eine andere Funktion an der y-Achse aufruft. Rekursive Aufrufe schlagen sich somit als ein Punkt auf der Diagonalen nieder. Der Punkt kann eingefärbt werden, um zusätzliche Information unterzubringen, zum Beispiel die Häufigkeit eines Aufrufs.

Die Vorteile dieser Darstellung sind ihre Einfachheit sowie Skalierbarkeit in Bezug auf den für die Darstellung notwendigen Rechenaufwands. Das automatische Layouting großer dichter Aufrufgraphen ist sehr rechenintensiv, während eine Adjazenzmatrix schnell dargestellt werden kann. Auch die Übersichtlichkeit ist bei Adjazenzmatrizen höher als bei dicht besetzten Graphen. Ihr Nachteil ist jedoch, dass Wege nicht zu erkennen sind. Hier sind Graphen deutlich überlegen. Zudem ist die Skalierbarkeit für Graphen mit sehr vielen Knoten in der Ausnutzung des verfügbaren Platzes für die Darstellung nicht gegeben. Graphen sind häufig dünn besetzt, wodurch der Platz nicht effizient ausgenutzt wird. Lange X- und Y-Achsen machen Schiebebalken oder andere Interaktionsformen notwendig, so dass man nicht immer alles auf einen Blick sieht.

Wenn es um Abfolgen geht (zum Beispiel bei den Ergebnissen dynamischer Analysen) kann man Sequenzdiagramme verwenden, die auch Teil der UML sind. Eine Erweiterung von UML-Sequenzdiagrammen durch Farben und anderes bietet JInsight. Jeder vertikale Streifen repräsentiert ein Objekt (vergleiche Abbildung 5). Die Farbe des Streifens kodiert die Klasse, zu der das Objekt gehört. Die Zeit schreitet wie bei Sequenzdiagrammen üblich von oben nach unten fort. Aufrufe sind durch Kanten zwischen Objekten dargestellt und haben die aufgerufene Methode als Label. Die zeitlichen Bereiche, in denen ein Objekt tatsächlich aktiv ist (d.h. nicht nur eine andere Methode aufruft sondern tatsächlich selbst rechnet), sind im Streifen etwas heller dargestellt.

Sequenzdiagramme, die tatsächliche Abläufe, die mittels einer dynamischen Analyse eines realistischen Programms gewonnen wurden, sind sehr lange. Häufig wiederholen sich darin Teilsequenzen, wenn diese etwa im Programm in einer Schleife ausgeführt werden. Würde ein langlaufendes Programm auf diese Weise dargestellt werden, würde man sich mit einem Schiebebalken sehr lange über die angezeigte Sequenz bewegen müssen. JInsight erlaubt es deshalb, wiederkehrende Aufrufmuster automatisch zu erkennen und darzustellen. Ähnliche, aber leicht unterschiedliche Muster können dabei übereinandergelegt werden, um so die Unterschiede darzustellen. Hier sieht man erneut, wie wichtig Vorverarbeitungsschritte in Form automatisierter Analysen sind, damit ein Bild lesbar und nützlich wird.

Wenn es um die Visualisierungen von Metriken geht, kann man auf einen großen Satz klassischer Visualisierungen zurückgreifen. Dazu gehören Tortendiagramme, Funktionsgraphen, Box-Plots, Balkendiagramme und viele andere. Wichtig ist bei der Visualisierung, dass man die dargestellten Metriken sehr einfach mit anderen Visualisierungen der Software in Verbindung bringen kann. Wie wir bereits am Beispiel des Eingangs gezeigten UML-Werkzeugs gesehen haben, wird Software meist durch verschiedene Sichten unterschiedlichen Abstraktionsgrads abgebildet. Abbildung 6 zeigt auf der linken Seite einen Aufrufgraphen. Auf der rechten Seite sehen wir mehrere Koordinatensysteme. Jede Funktion im Aufrufgraphen wird in jedem Koordinatensystem als Punkt dargestellt. Die Koordinatensysteme beschreiben unterschiedliche Metriken zu verschiedenen Aspekten der Software. Dazu gehören beispielsweise statische Code-Metriken, wie die Anzahl von Kommentaren oder Bedingungen, dynamische Metriken wie zum Beispiel die Testabdeckung oder die Laufzeit, aber auch Metriken zu Aspekten des Entwicklungsprozesses, wie die Häufigkeit von Änderungen an den Funktionen oder die Anzahl der verschiedenen Entwickler, die die Funktionen geändert haben.

Der Bezug zwischen den Koordinatensystemen und dem Aufrufgraph wird hergestellt, indem die Punkte selektiert werden. Wird eine Funktion im Aufrufgraph selektiert, dann wird der entsprechende Punkt in allen Koordinatensystemen farbig hervorgehoben und umgekehrt.

Wenn es um die Darstellung von Hierarchien geht, deren Blätter mit Metriken assoziiert sind, kann man sich der so genannten Tree-Maps bedienen. Hier wird eine Baumstruktur in die Ebene projiziert. Die Fläche, die ein Blatt einnimmt, ist proportional zu ihrem Metrikwert. Um gleichzeitig die Hierarchie abzubilden, werden alle Nachfolger in einem Teilbaum räumlich geschachtelt dargestellt. Die Hierarchiegrenzen werden mit einem Rahmen versehen.

Abbildung 7 hilft, das Vorgehen zu erläutern. Zunächst beginnt man mit einer quadratischen Fläche, auf die der Baum projiziert werden soll. Dann aggregiert man die Metrikwerte durch Summenbildung von den Blättern zu den Vorgängern im Baum. Der Knoten X hat dann den Wert 99, der Knoten Z den Wert 50, der Knoten Y den Wert 100 und die Wurzel W schließlich den Wert 199. Die Flächen werden nun von der Wurzel ausgehend proportional auf die Nachfolger im Baum verteilt. Die beiden Knoten X und Y haben nahezu denselben Anteil 99/199 beziehungsweise 100/199. Diese Werte werden rekursiv auf die Nachfolger verteilt. Die Knoten a, b und c erhalten alle den gleichen Anteil, der ihrem gemeinsamen Vorgänger X zugesprochen wurde, nämlich jeweils ein Drittel von 99/199. Die Knoten Z und d erhalten jeweils die Hälfte von 100/199. Für die Nachfolger von Z wird dieser Anteil abermals halbiert.

Damit die Schachtelung des Baumes deutlich wird, werden die Flächen alternierend in der Baumtiefe vertikal und dann horizontal verteilt. Schließlich ergibt sich dann die Fläche, die rechts neben dem Baum in Abbildung 7 gezeigt ist.

Ein realistischeres Beispiel ist in Abbildung 8 dargestellt. Es stellt Redundanzen in Form von dupliziertem Code in einem sehr großen realen Programm dar, das in einem industriellen Unternehmen entwickelt wurde. Die Struktur der Tree-Map gibt die Quelltextdateien und ihre Organisation in der Verzeichnisstruktur wieder. Die Flächen sind proportional zur relativen Größe der Dateien, gemessen in Code-Zeilen. Der Grad der Redundanz wird durch die rote Einfärbung abgebildet; je redundanter eine Datei ist, desto dunkelroter ist die Fläche. Die blaue Fläche ist die Datei, die vom Nutzer im Augenblick selektiert wurde. Alle anderen Teile, die Redundanzen mit der selektierten Datei haben, sind grün eingefärbt. Kanten verbinden die grünen Teile mit der selektierten blauen Fläche.

Der Grad von hell- bis dunkelgrün zeigt wie im Falle der unverbundenen Flächen den Grad der Redundanz an – mit der blauen oder auch mit jeder anderen Fläche. Wie viele zusammenhängende Code-Teile spezifisch zwischen den grün eingefärbten Dateien und der selektierten, blau eingefärbten Datei kopiert wurden, wird durch die Zahlen in den grünen Flächen angezeigt. Diesem Bild kann man unmittelbar entnehmen, dass es große Dateien mit einem sehr hohen Grad an Redundanz gibt und dass im Falle der aktuell selektierten Datei, die Redundanz nicht lokal ist, sondern gemeinsame Code-Teile über weit entfernte Dateien existieren.

Der Vorteil der Tree-Maps ist es, dass sie sowohl proportional Metriken als auch zeitgleich die Hierarchie darstellen. Die Voraussetzung ist, dass die Metriken von den Blättern zu den inneren Knoten als Summe aggregiert werden können. Der gesamte zur Verfügung gestellte Raum wird effizient genutzt. Der Raum selbst kann zu Anfang vorgegeben werden. Es kann also nicht passieren, dass Informationen aus dem sichtbaren Bereich wandern. Die Skalierung ist nur begrenzt durch die Auflösung der Darstellung und der Fähigkeit des Betrachters, noch Punkte auseinanderhalten zu können. Selbstverständlich kann diese Darstellung auch leicht das Hinein- und Herauszoomen unterstützen.

Jedoch muss man sich mit dieser Visualisierung einige Zeit auseinandergesetzt haben, bis man sie leicht in allen Teilen verstehen kann. Gerade die Abgrenzung der Hierarchie in tief verschachtelten Bäumen wird schnell schwierig. Außerdem sind die Metriken auf die Blätter begrenzt.

Tree-Maps hatten wir als eine erste Möglichkeit kennen gelernt, die Visualisierung von Graphen und Metriken zu kombinieren. Allerdings konnten damit keine allgemeine Graphen, sondern nur Bäume dargestellt werden. Binäre Relationen können allenfalls durch eingeblendete Kanten dargestellt werden, wie es das Beispiel in Abbildung 8 zeigte. Dort werden die Kanten aber nur für die aktuell selektierte Datei eingeblendet. Würde man alle Kanten gleichzeitig darstellen, wären die Knoten kaum mehr zu sehen.

Artikelfiles und Artikellinks

(ID:45490923)