Softwareanalyse mit CodeCity

Java-Code visualisieren: Stadtneurotiker

Bastian Helfert und Steffen Hohn

Wie können wir kurzfristig einen Überblick über die Entwurfsqualität eines komplexen objektorientierten Softwaresystems gewinnen? Wo liegen potenzielle Schwachstellen, was sind mögliche Lösungen? Mithilfe des Werkzeugs CodeCity kann Java-Code in Form einer dreidimensionalen Stadt visualisiert werden. Der Artikel zeigt, wie sich beim virtuellen Spaziergang durch eine solche Stadt mögliche Fehlkonstruktionen erkennen und korrigieren lassen.

Als Softwarearchitekten würden wir am liebsten ausschließlich frische Systeme auf der grünen Wiese entwickeln. Die Realität sieht aber anders aus: Viel häufiger müssen wir an muffigen Altsystemen arbeiten oder marode Projekte retten. Die entstandenen Altsysteme weisen zumeist eine über längere Zeit gewachsene Struktur auf. Vielfach waren auch schon einige Entwicklergenerationen an der Implementierung der Funktionalitäten beteiligt. Beide Faktoren führen in vielen Fällen zu einer Verschlechterung der Entwurfsqualität. So werden beispielsweise Klassen als reine Datencontainer missbraucht, ein Großteil der Logik konzentriert sich an viel zu wenigen Punkten im System und die Codeduplizierung treibt ihre Blüten. Um sich trotzdem einen schnellen aber guten Überblick über das komplexe Altsystem zu verschaffen, ist das Studium des Quellcodes nicht der geeignete Ansatz. Ein sehr hilfreiches Werkzeug, um dieses Ziel zu erreichen, ist CodeCity.

CodeCity

Die Anwendung visualisiert Metriken in Form einer dreidimensionalen Stadt. Ein Beispiel für einen Ausschnitt aus einer solchen Code City findet sich in Abbildung 1. Klassen werden hierbei als Gebäude dargestellt. Die Anzahl ihrer Attribute wird durch die Größe der Gebäudegrundfläche ausgedrückt, wohingegen die Gebäudehöhe ein Maß für die Anzahl der Methoden ist. Die Anzahl der Codezeilen (LOC) bestimmt den Grad der Blaufärbung des Gebäudes (dunkelblau = wenige LOC, hellblau = viele LOC). Die Darstellung von Packages erfolgt durch die Unterteilung der Stadtfläche in Bezirke verschiedener Grautöne (dunkelgrau = Package höherer Ebene, hellgrau = Package unterer Ebene). Durch diese Art der Visualisierung stellt sich ein erstes Bauchgefühl für die Ästhetik der Stadt ein. Möchten Sie in dieser Stadt leben?

Abb. 1: Code City des zu analysierenden Beispielprojekts

Die Darstellung ermöglicht es uns allerdings nicht direkt, potenzielle strukturelle Entwurfsprobleme lokalisieren und kontextabhängige Mittel zu ihrer Behebung identifizieren zu können. Hierfür bietet es sich an, auf objektorientierte Entwurfsmetriken zurückzugreifen. CodeCity benutzt dazu die Metriken, die von Michele Lanza und Radu Marinescu unter [1] beschrieben werden. Einige von diesen stellen wir im Folgenden vor.

Von Heuristiken, Prinzipien, Entwurfsmustern und schlechten Gerüchen
Heuristik

Für einen guten objektorientierten Entwurf gilt: Verteile die Intelligenz (die Funktionalität, das Verhalten, die Aufgaben) eines Systems gleichmäßig auf die Klassen oberster Ebene (Heuristic 3.1 aus [2]).

Prinzip

Single Responsibility Principile (SRP): Jede Klasse sollte nur genau eine Verantwortlichkeit besitzen. Mit anderen Worten: „Es sollte nie mehr als einen Grund geben, eine Klasse zu ändern.“ [3]

Entwurfsmuster

Strategie: „Definiere eine Familie von Algorithmen, kapsele jede einzeln und mache sie austauschbar. Das Strategiemuster ermöglicht es, den Algorithmus unabhängig von ihn nutzenden Klienten zu variieren.“ (Übersetzung von [4])

Schlechter Geruch

Feature Envy: Eine Methode hat mehr Interesse an einer anderen Klasse als an der eigenen. Üblicherweise bedeutet das, die Methode ist „neidisch“ auf die Daten dieser anderen Klasse [5].

Entwurfsdisharmonien

Anhaltspunkte für einen guten objektorientierten Entwurf sind in der Literatur in Hülle und Fülle zu finden: Es werden beispielsweise Heuristiken genannt, Prinzipien definiert und Entwurfsmuster formuliert. Schlechte Entwurfsqualität steigt in die Nase, wie Martin Fowler und Kent Beck bereits beschrieben haben. Beispiele hierzu finden sich im Kasten „Von Heuristiken, Prinzipien, Entwurfsmustern und schlechten Gerüchen“. Diese Anhaltspunkte dienten Lanza und Marinescu als Grundlage zur Identifikation von Gerüchen schlechter Entwurfsqualität, die sie Entwurfsdisharmonien genannt haben.

Die God Class

Eine häufig auftretende Entwurfsdisharmonie ist die God Class. Sie besitzt folgende negative Eigenschaften:

  • benutzt zu viele Attribute fremder Klassen
  • hat eine sehr hohe funktionale Komplexität
  • hat eine niedrige Kohäsion

Eine God Class zentralisiert einen bedeutenden Anteil der Anwendungslogik und führt somit zu viele Arbeiten selbst durch. Wenn sie Logik fremder Klassen nutzt, ist diese nur simpel. Eine God Class arbeitet zum großen Teil auf den Daten anderer, trivialer Klassen (häufig „Datensäcke“, siehe Abschnitt „Data Class“). Ihre funktionale Komplexität, also das Maß für die Anzahl der Verzweigungen in ihren Methoden, ist übermäßig hoch. Die Methoden und Attribute innerhalb einer God Class weisen einen nur schwachen Zusammenhalt, also eine geringe Kohäsion auf. Das bedeutet, dass im Verhältnis zu der Gesamtzahl ihrer Methoden nur wenige auf den Attributen der Klasse arbeiten.

Warum ist eine God Class problematisch? Sie besitzt zu viele Verantwortlichkeiten. Dies erschwert die Verständlichkeit und Wartbarkeit des Systems. Systemänderungen wirken sich immer wieder auf die Klasse aus. Betrachtet man die God Class für sich, verstößt sie offensichtlich gegen das grundlegende Prinzip der einzigen Verantwortlichkeit (SRP). Auf der Makroebene wird zusätzlich die im Kasten erwähnte Heuristik verletzt. Eine God Class stellt hingegen weniger ein Problem dar, wenn sie in einem stabilen und isolierten Teil eines Systems existiert.

Geschrieben von
Bastian Helfert und Steffen Hohn
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.