Über unsMediaKontaktImpressum
Stefan Dirschnabel 10. August 2021

Die Makrooptische Analyse: Software beurteilen in 60 Sekunden

Egal ob Entwickler, Scrum Master oder Manager, im Bereich der Softwareentwicklung werden verschiedenste Rollen im Unternehmen regelmäßig mit Programmcode konfrontiert. Dieser Programmcode muss immer wieder beurteilt werden. Physische Produkte wie Autos oder Möbel können meist auch von Nicht-Technikern beurteilt werden. Bei Programmcode ist das schon deutlich schwieriger.

Entwickler müssen Quellcode bei Erweiterungen, der Fehlersuche oder schlicht bei Wartungsarbeiten beurteilen. Scrum Master und Stakeholder werden in Live-Demos mit Entwicklern mit Quellcode konfrontiert, können dessen Qualität aber aufgrund des kryptischen Erscheinungsbildes nicht beurteilen. Gerade in schwierigen Projekten, bei Qualitätsproblemen oder geringer Produktivität ist der Wunsch für Außenstehende groß, die Qualität eines Softwareprodukts jenseits von dessen Benutzeroberfläche beurteilen zu können.

Die "Makrooptische Analyse" ist ein Verfahren, um anhand von optischen Mustern im Quelltext schnell auf dessen Qualität zu schließen. Anstatt Programmcode zu lesen und aufwändig zu interpretieren, wird Programmcode anhand Mustern in der Typografie kategorisiert und direkt bewertet.

Wie viele Augen (Punkte) zählen Sie in der linken Abbildung?

Und wie viele Augen (Punkte) erkennen Sie in der rechten Abbildung?

Bei beiden Fragen ist die richtige Antwort Zehn. Bei der rechten Abbildung hatten Sie das Ergebnis aber sicherlich deutlich schneller (und das, obwohl Sie addieren mussten). Anstatt zu zählen, hat Ihr Gehirn automatisch ein Muster erkannt. Können wir dieses Vorgehen auf die Beurteilung von Programmcode übertragen? Dieser Artikel proklamiert die These, dass das möglich ist. Wir erforschen gemeinsam die Welt der Makrooptischen Analyse.

Software beurteilen in 60 Sekunden

Im Bereich der Softwareentwicklung werden wir im Unternehmen regelmäßig mit Programmcode konfrontiert und müssen diesen immer wieder beurteilen. Nicht-Techniker werden vor allem in Live-Demos mit Entwicklern mit Quellcode konfrontiert. Gerade in schwierigen Projekten, bei Qualitätsproblemen oder widersprüchlichen Aussagen zur Codequalität ist für Außenstehende der Wunsch groß, die Qualität eines Softwareprodukts jenseits von dessen Benutzeroberfläche beurteilen zu können. Gerade Personen, die nicht jeden Tag Programmcode schreiben, gibt die Makrooptische Analyse ein Werkzeug an die Hand, mit dem eine erste Beurteilung des Codes durch bloßes "darüberscrollen" möglich ist.

Entwickler sind in der tiefgreifenden Analyse von Quellcode geübt und führen die Makrooptische Analyse intuitiv durch.

Ansatz

Programmcode ist für den Computer das, was für den Koch das Rezept ist: eine fest definierte Folge von Arbeitsanweisungen. Wenn Sie in einer Buchhandlung stehen und ein Kochbuch kaufen möchten. Wie würden Sie das Buch beurteilen, wenn Sie einfach nur "durchblättern" und sich nicht für den genauen Inhalt interessieren?

Sie achten auf Darstellungsmerkmale wie z. B. die Typografie des Texts. Gibt es Absätze? Wird mit übersichtlichen Tabellen und Aufzählungslisten gearbeitet? Ist das Inhaltsverzeichnis übersichtlich? Wie ist ein Rezept aufgebaut – sind die Zutaten vor der eigentlichen Zubereitung notiert oder müssen Sie die Zutaten im Fließtext suchen? Ist das Rezept in die Vorbereitung der Zutaten und in das eigentliche "Kochen" aufgeteilt?

Sie beurteilen das Buch anhand optischer Muster im Textbild. Analog dazu ist die Makrooptische Analyse eine Methode, um die Qualität von Programmcode anhand optischer Muster im Textbild zu erkennen.

Kann dieser Ansatz so einfach auf Software übertragen werden? Moderne Entwicklungsumgebungen formatieren Quellcode nach bestimmten Regeln. Dadurch ergibt sich immer ein ähnliches Textbild. Wichtig ist nur:

  1. Eine auffällige Optik ist ein deutlicher Hinweis auf Qualitätsprobleme, eine unauffällige Optik aber kein Garant, dass es nicht doch Qualitätsprobleme gibt. Hintergrund ist, dass Qualitätsprobleme verschiedene Ursachen haben können. Zum einen handwerkliche Schwächen im Softwaredesign (hier gibt die Makrooptische Analyse erste Hilfestellung). Und zum anderen semantische Schwächen. Mit semantischen Schwächen ist eine schlechte Abbildung der Domänenlogik gemeint. Semantische Schwächen können logischerweise nur durch tiefes Verständnis aufgeklärt werden.
  2. Der Ansatz der Makrooptischen Analyse lässt sich nicht auf XML-ähnliche Daten (z. B. HTML oder XAML bei WPF) übertragen, da diese per se hierarchisch strukturiert sind. Diese Daten werden bei der Definition von Oberflächen eingesetzt. Sie erkennen diese Daten anhand der häufigen Verwendung von XML-Tags, zum Beispiel <IRGENDEINTEXT> </IRGENDEINTEXT>.

Die Geschäftslogik hinter der Definition der Oberflächen kann jedoch wieder makrooptisch analysiert werden.

Vorgehen

Um das Textbild des Quellcodes einfach zu analysieren, treten Sie im einfachsten Fall einen Schritt vom Bildschirm zurück oder kneifen die Augen zusammen. Achten Sie nicht auf die einzelnen Zeichen, sondern auf die Darstellung und Symmetrie der Textblöcke. In einigen Entwicklungsumgebungen wird auch innerhalb der Scrollbar ein verkleinertes Abbild des Quelltexts angezeigt. Dies eignet sich ebenfalls zur Mustererkennung.

Vier auffällige Muster

The Never Ending Story

Das Muster der Unendlichen Geschichte ist selbst für absolute Laien einfach zu erkennen. Dieses Muster bezieht sich ganz einfach auf die Größe der Datei, in welcher der Quellcode definiert ist. Genauso wie bei der Arbeit mit geschäftlichen Dokumenten wird auch Quellcode auf mehrere Dateien aufgeteilt. Oder arbeiten Sie mit nur einer Excel-Datei in der sich hunderte von Arbeitsblättern befinden? Diese Aufteilung dient vor allem der Übersicht und teilweise auch einer semantischen Gruppierung.

Je mehr Programmzeilen eine Datei aufweist, desto höher ist die Wahrscheinlichkeit, dass das Programm schlecht modularisiert ist. Die Übersichtlichkeit und Erweiterbarkeit leidet. Die Anzahl der Zeilen wird in den meisten Entwicklungsumgebungen am linken Bildschirmrand oder unten in der Fußzeile angezeigt. Bleibt nur noch die Frage zu klären, ab welcher Anzahl von Zeilen eine Datei "zu groß" ist. Über Details streiten sich Experten regelmäßig. Da dieser Artikel keine Haarspalterei betreiben, sondern für Nicht-Techniker einen einfachen Leitfaden geben will, lege ich die kritische Grenze auf 800 Zeilen fest. Bei allem darüber sollten die Alarmglocken klingeln.

The Black Hole

In den meisten Programmiersprachen werden bestimmte Befehle verwendet um den Programmablauf zu steuern. Ein typografisches Merkmal dieser Befehle ist, dass alles nach dem Befehl mit einer "Einrückung" (Texteinzug) gekennzeichnet ist. Finden Sie in einem Programm viele aufeinanderfolgende Einrückungen, sieht das ungefähr so aus wie in Abb. 4.

Wenn der Text um 90 Grad im Uhrzeigersinn gedreht wird, erinnert er an einen Trichter. Die vielen aufeinanderfolgenden Steuerbefehle sind komplex, bedingen sich meist irgendwie gegenseitig und sind eine häufige Stelle von Softwarebugs. Diese Programmstellen verschlingen viel Zeit um sie zu verstehen. Sie verschlingen Ressourcen wenn man die dortigen Fehler beheben will. Wie ein schwarzes Loch.

In kleinen Dateien ist das Black Hole noch nicht so kritisch. Schlimmer wird es, wenn das Black Hole zusammen mit der Never Ending Story auftritt. Es ergibt sich ein fließender Übergang zum nächsten Muster: Spaghetti-Code.

Spaghetti-Code

Sie können keine Symmetrie im Textbild erkennen?

Dann liegt höchstwahrscheinlich Spaghetti-Code vor.

Wenn wir die Muster nach Schweregrad sortieren müssten, dann würde das Spaghetti-Code-Muster an erster Stelle stehen. Es handelt sich um eine Kombination aus Never Ending Story und Black Hole. Es kennzeichnet sich nicht nur durch tiefe Verschachtelungen und viele Einrückungen, sondern ganz einfach dadurch, dass sie keine "Symmetrie" im Textbild erkennen können.

Normalerweise sollte Programmcode so lesbar sein wie ein Buch. Selbst Nicht-Techniker können dann Software verstehen.

Das vorliegende Codefragment scheint eine Bestellung auszuführen. Über die Auftragsnummer (orderId) wird die Bestellung gesucht, abgeschlossen, eine Rechnung erzeugt und diese an den Kunden geschickt.

[HttpPost("{orderId}/execute")]
public Result ExecuteOrder(string orderId)
{
   var order = FindOrder(orderId);
   CompleteOrder(order);
   var invoice = CreateInvoice(order);
   SendToCostumer(invoice);

   return Result.Success;
}

Mit der Zeit wird das Programm aber immer unleserlicher und sieht schlussendlich so aus:

Der Grund für Spaghetti-Code ist, dass die primäre Intention des Codes durch (leider notwendige) Sekundäraspekte wie Validierung, Fehlerbehandlung usw. "verschmutzt" wird. Es gibt aber Mittel und Wege, mit den Sekundäraspekten vernünftig umzugehen. Für alle hier aufgeführten Muster gibt es Lösungsmöglichkeiten. Spaghetti-Code kann sehr gut durch das IOSP (Integration Operation Segregation Principle) gelöst werden [1].

Brain-Stopper

Ein Muster des Brain-Stoppers könnte wie rechts gezeigt aussehen. Zwischen einzelnen (kurzen) Programmzeilen gibt es eine längere Programmzeile. Die hier definierten Anweisungen sind meist komplex und es bedarf der intensiveren Betrachtung. Der Brain Stopper kennzeichnet sich primär dadurch, dass Entwickler beim Lesen von Programmcode kurz "stolpern". Der vorliegende Programmcode kann nicht einfach "verstanden werden", sondern muss "gelesen und interpretiert" werden.

Leider kann der Brain-Stopper nicht immer so einfach erkannt werden. Das liegt daran, dass einige der heutigen Entwicklungsumgebungen lange Zeilen automatisch in mehrere kurze Zeilen umbrechen. D.h. Sie erkennen das Muster dann nicht so einfach. Als wichtiges Merkmal des Brain-Stoppers sollte deswegen das Leseverhalten des Menschen nicht außer Acht gelassen werden.

Wir führen den Brain-Stopper an letzter Stelle, da er nicht ganz so auffällig und aussagekräftig ist wie die vorhergegangenen Muster. Das hängt damit zusammen, dass es je nach Programmiersprache (funktional vs. imperativ) oder API (Fluent-API), Notationskonzepte gibt, die einfach verständlich sind, aber trotzdem optisch in langen Zeilen enden. Orientieren Sie sich deswegen primär am Lesefluss!

Fazit

Indem wir auf optische Muster in der Typografie von Quellcode achten, erhalten wir schnell erste Hinweise auf schlechten Code. Vier solcher Muster haben Sie in diesem Artikel kennengelernt. Schlechter Code entsteht durch mangelnde Modularisierung. Die Vermischung von technischen Details mit der primären Intention, die das Programm erfüllen soll, führt zu Spaghetti-Code.

Guter Code ist modularisiert, trennt zwischen der Intention (WAS geschieht) und der konkreten Ausführung (WIE etwas geschieht). Dadurch bleibt Programmcode lesbar, was sich in einem klaren und "unverwobenen" Textbild widerspiegelt. Falls bei Ihnen die Makrooptische Analyse auffällig ist und Sie Qualitätsprobleme vermuten, sollte für eine weiterführende Analyse ein Spezialist hinzugezogen werden.

Für alle gezeigten Muster gibt es Lösungsansätze, um zu nachhaltigem und erweiterbarem Programmcode zurückzukehren. Diese Lösungsansätze werden als "Refactoring" bezeichnet. Refactoring zielt darauf ab, die interne Struktur des Programmcodes zu verbessern, ohne sein externes Verhalten zu verändern. Viel wichtiger, als Programmcode aber ständig zu verbessern, sind Ansätze, schlechten Code erst gar nicht entstehen zu lassen [2].

Autor

Stefan Dirschnabel

Stefan Dirschnabel ist langjähriger Software-Architekt, -Trainer und -Berater mit den Schwerpunkten Microsoft.Net und Web. Sein Fokus ist Clean Code Development und die Beratung hinsichtlich eines sauberen Entwicklungsprozesses.
>> Weiterlesen
Das könnte Sie auch interessieren
Kommentare (0)

Neuen Kommentar schreiben