Oktober 2014

Volume 29 Number 10

Cutting Edge -Tipps zur besseren Lesbarkeit von Quellcode

Dino Esposito | Oktober 2014

Dino EspositoHaben Sie jemals vom Programmierwettbewerb International Obfuscated C Code Contest (IOCCC) gehört? Aus einer Handvoll C-Programmen wird in diesem offenen Wettbewerb ein Gewinnerbeitrag gekürt, der es schafft, ein bestimmtes Problem durch extrem verschleierten C-Code zu lösen. Die Gewinner der Vorjahre inklusive Quellcode finden Sie unter ioccc.org/years.html.

Der OCCC (Obfuscated C Code Contest) demonstriert auf amüsante Weise, wie wichtig der Programmierstil und die Lesbarkeit bei der Programmierung sind. In dieser Kolumne stelle ich kurz einige der wichtigsten Techniken vor, mit denen Sie leicht lesbaren und verständlichen Code programmieren können – sowohl im eigenen Interesse als auch dem Ihrer Kollegen.

Qualitätsmerkmal „Lesbarer Code“

Wartungsfreundlicher Code zeichnet sich in der Softwareentwicklung dadurch aus, dass er einfach geändert werden kann, beispielsweise um einen Programmfehler zu beheben, den Code zu pflegen, ein neues Feature zu implementieren oder Code an bestimmte Muster anzupassen. Gemäß der Norm ISO/IEC 9126 ist dies eines der Grundprinzipien der Softwareentwicklung. Eine ausführlichere Beschreibung der Softwaremerkmale finden Sie unter bit.ly/VCpe9q.

Die Wartungsfreundlichkeit von Code resultiert aus einer Vielzahl von Faktoren, darunter auch die Lesbarkeit. Schwer lesbarer Code ist gleichzeitig schwer verständlicher Code. Wenn sich Entwickler an Programmcode versuchen, den sie nicht vollständig durchblicken, können sie den Code sogar verschlimmern.

Hinzu kommt, dass jeder Einzelne die Lesbarkeit von Code anders definiert. So ist es nahezu unmöglich, sie mit einem Tool automatisch prüfen und protokollieren zu lassen. Und selbst wenn dies machbar wäre, würden solche Tools als höchst unzuverlässig und wenig vertrauensvoll gelten. Im Endeffekt lässt sich Lesbarkeit nur manuell erreichen und sollte von jedem Entwickler im Kontext des eigenen Codes umgesetzt werden. Die Fähigkeit, lesbaren Code zu schreiben, sollte zum Selbstverständnis jedes einzelnen Programmierers und seinem fundierten Instrumentarium gehören.

Generell ist die Lesbarkeit ein Codemerkmal, das sich Entwickler schon am Anfang ihrer Programmierlaufbahn zu eigen machen und nach und nach verfeinern und weiterentwickeln sollten. Genauso wie der Programmierstil und ein durchdachter Entwurf geht auch die Lesbarkeit nicht nur Experten etwas an. Vor allem aber gilt: Verschieben Sie diesen Aspekt nicht auf später, wenn Sie vielleicht einmal Zeit dazu haben.

Ein pragmatischer Ansatz für lesbaren Code

Aus Respekt vor anderen Entwicklern versteht es sich von selbst, lesbaren Code zu programmieren. Ein von StackOverflows geplagter Nutzer hat dies einmal so ausgedrückt: „Als Programmierer sollte man immer damit rechnen, dass es sich bei der Person, die den Code pflegt, um einen unberechenbaren Psychopathen handelt, der Ihnen vor der Haustür auflauert.“ Genauso gut könnte es sein, dass Sie sich eines Tages mit der Pflege Ihres eigenen Codes abmühen müssen.

Der Code anderer Programmierer hat manche Besonderheiten, die einen zur Weißglut treiben können. Besonders schwer lesbar wird der Code durch Datenstrukturen und Algorithmen ohne klares Ziel. Ein weiterer Aspekt sind Programmierstrategien, die auf Anhieb nicht zu erkennen und durch Kommentare nicht hinreichend erläutert sind. Im Folgenden finden Sie ein Beispiel:

// Find the smallest number in a list of integers
private int mininList(params int[] numbers)
{
  var min = Int32.MaxValue;
  for (var i = 0; i < numbers.length; i++) {
    int number = numbers[i];
    if (number < min)
      min = number;
  }
  return min;
}

Auch wenn ich das Beispiel zur besseren Übersicht in C# portiert habe, muss ich zugeben, dass kein C#-Entwickler jemals einen solchen Code programmieren würde. Der Grund liegt darin, dass er mit C# und Microsoft .NET Framework unter Verwendung von LINQ nahezu die gleichen Ergebnisse erzielt. Ähnlichen Code – allerdings in der Programmiersprache Java – habe ich einmal in einem Projekt verwendet. An einem bestimmten Punkt musste ich die Codebasis jedoch in .NET Framework und C# portieren.

Dieser Code könnte Ihnen auch in einem realen .NET-Projekt begegnen. Mit ein paar Kniffen können Sie die Lesbarkeit verbessern, ohne zu weit abzuschweifen. Das Erste, was mir auffällt, ist der Name der Funktion. Die Konvention ist strittig, weil der Name kein Verb und eine Kombination aus Groß- und Kleinbuchstaben enthält. Ein Name wie „GetMinFromList“ wäre hier besser geeignet. Der kritischste Aspekt an diesem Code ist jedoch der Private-Bezeichner im Namen.

Jeder Betrachter erkennt sofort, dass die Funktion als Hilfsfunktion dient. Anders ausgedrückt, stellt sie ein wiederverwendbares Codefragment dar, das die Programmierer von verschiedenen Orten der Codebasis aufrufen können. Folglich ist die Kennzeichnung „private“ nicht immer sinnvoll. Da die meisten Entwickler die YAGNI-Regel (You Ain’t Gonna Need It, Du wirst es nicht brauchen) kennen, machen sie auch keinen Code verfügbar, der nicht unbedingt erforderlich ist.

Möglicherweise hat der Autor dieses Codes die Wiederverwendbarkeit der Funktion im Blick gehabt – allerdings nicht beim Schreiben dieses Codes. Obwohl die Funktion so geschrieben wurde, dass sie einfach in eine wiederverwendbare Hilfsfunktion verwandelt werden kann, sorgt die Kennzeichnung „private“ dafür, dass sie nur in der Hostklasse sichtbar ist. Für externe Betrachter ist die zugrunde liegende Codierungsstrategie deshalb u. U. nicht sofort erkennbar. Dabei bedarf es nur einiger Kommentarzeilen, um den eigentlichen Zweck zu veranschaulichen. Wenn Sie keine erläuternden Kommentare hinzufügen, sind Sie der Programmierwelt nicht besonders nützlich. Zwar wird der Betrachter die eigentliche Absicht am Ende erkennen, braucht dafür jedoch einige Minuten und fängt an, sich über den Autor zu ärgern.

Praktische Regeln für lesbaren Code

Die Bedeutung lesbaren Codes ist unbestritten, allerdings fehlt es an einer formalisierten Vorgehensweise. Ohne diesen formalen Bezugsrahmen ist Lesbarkeit jedoch ein nahezu leerer Begriff. Indem Sie die Regel der „3 Ks“ – Kommentare, Konsistenz und Klarheit – befolgen, erzielen Sie allgemein eine gute Lesbarkeit.

Heutzutage sind IDE-Tools wesentlich intelligenter als noch vor ein paar Jahren. Auch wenn Entwickler nicht zwingend Hilfedateien schreiben müssen, integrieren sie ihre Dokumentation bereits in ihre Visual Studio-Projekte. Auf Grundlage der Kommentare werden QuickInfos erstellt und überall verfügbar gemacht. Moderne IDEs machen es einfach, spezifische Kommentare zu definieren. Sie überlegen sich einfach einen Text und überlassen der IDE den Rest. Dies entspricht der klassischen Kommentierung, durch die Sie den Methoden und Klassen eine präzise Beschreibung Ihrer Ziele hinzufügen. Diese Kommentare sollten gemäß den Standards der Plattform oder Programmiersprache verfasst werden. Darüber hinaus können Sie festlegen, dass offen gelegte Codefragmente kommentiert werden müssen.

Die Verbannung allzu offensichtlicher Kommentierungen ist ein weiterer wichtiger Schritt zur besseren Lesbarkeit. Diese Art von Kommentaren enthält keine relevanten Informationen und produziert nur überflüssigen Code. Laut Definition ist ein Kommentar ein erläuternder Text, der Ihnen hilft, eine nicht unmittelbar erkennbare Entscheidung im Code zu treffen. Ein Kommentar ist nichts weiter als eine erläuternde Anmerkung zu einem bestimmten Codeabschnitt. 

Das zweite „K“ steht für Konsistenz. Die Richtlinien der Codeprogrammierung müssen für alle Teams verbindlich sein. Noch besser wäre es, wenn sie unternehmensweit befolgt würden. Wenn es um Richtlinien geht, halten sich viele zunächst mit der Definition auf, anstatt einfach zu entscheiden, was richtig und was falsch ist. Ich würde jedoch behaupten, dass die Frage nach Falsch oder Richtig erst an zweiter Stelle kommt, nachdem die Verwendung einheitlicher Programmiermuster sichergestellt wurde.

Stellen Sie sich vor, Sie schreiben eine Bibliothek für die Zeichenfolgenmanipulation. An einigen Stellen dieser Bibliothek werden Sie wahrscheinlich prüfen, ob eine Zeichenfolge eine bestimmte Teilzeichenfolge enthält. Wie würden Sie dazu vorgehen? In .NET Framework und im Java-SDK führen mindestens zwei Wege zum selben Ziel: die Methoden „Contains“ und „IndexOf“. Allerdings erfüllt jede dieser Methoden einen eigenen Zweck.

Die Contains-Methode gibt als Antwort einen booleschen Wert zurück, an dem Sie erkennen, ob die Teilzeichenfolge in der Zeichenfolge enthalten ist. Die IndexOf-Methode gibt den 0-basierten Index zurück, in dem sich die durchsuchte Zeichenfolge befindet. Wenn keine Teilzeichenfolge enthalten ist, gibt „IndexOf“ den Wert „-1“ zurück. Aus rein funktionaler Sicht erreichen Sie mit „Contains“ und „IndexOf“ also dasselbe Ziel.

Für den Betrachter des Codes haben die Methoden jedoch eine unterschiedliche Bedeutung. Er ist also gezwungen, den Code ein zweites Mal daraufhin durchzusehen, ob „IndexOf“ aus einem bestimmten Grund anstelle von „Contains“ verwendet wird. Das nochmalige Lesen einer Codezeile stellt zunächst kein Problem dar, aber wenn sich der Vorgang in der gesamten Codebasis Tausende Male wiederholt, haben wir es mit einem echten Zeit- und Kostenfaktor zu tun. Wir sprechen hier von den direkten Kosten, die durch schwer lesbaren Code entstehen.

Die Programmierung von konsistentem Code sollte zum Selbstverständnis eines jeden Entwicklers gehören. Sie sollten sich stets bemühen, auf Anhieb sauberen Code zu schreiben, ohne darauf zu hoffen, ihn später noch bereinigen zu können. Wenn Sie Teamleiter sind, sollten Sie Konsistenzrichtlinien in Form von Check-In-Richtlinien durchsetzen. Im Idealfall wird Code erst nach erfolgreicher Konsistenzprüfung eingecheckt.

Die neueste Version von ReSharper kann Ihnen dabei eine wertvolle Hilfe sein. Die kostenfreien Befehlszeilentools stellen ein eigenständiges Toolset dar und integrieren Formulare für die Codequalitätsanalyse direkt in Ihr CI (Continuous Integration)- oder Versionskontrollsystem. Mit diesen Befehlszeilentools können Sie Code auch offline überprüfen. Dazu führen Sie die gleichen Codeüberprüfungen durch, die Sie live mit Visual Studio und ReSharper ausführen, um Doppelungen im Code zu finden. Je nach den Funktionen zur CI-Anpassung (Continuous Integration, Fortlaufende Integration) müssen Sie Befehlszeilentools u. U. mit einer Ad-hoc-Komponente umschließen. Weitere Informationen zu ReSharper finden Sie unter bit.ly/1avsZ2R.

Als drittes und abschließendes „K“ sorgt Klarheit für gut lesbaren Code. Von Klarheit sprechen wir, wenn sich Code, einschließlich der entsprechenden Gruppierungs- und Schachtelungsebenen, einfach und flüssig lesen lässt. IF-Anweisungen produzieren in der Regel eine Menge unübersichtlichen Code. Auch wenn Bedingungsanweisungen ein zentrales Merkmal jeder Programmiersprache sind und sich nicht immer vermeiden lassen, sollten Sie versuchen, die Anzahl der IF-Anweisungen zu reduzieren, um die Schachtelungsebenen und den Code übersichtlich und lesbarer zu halten. Anstelle geschachtelter IF-Anweisungen können Sie auch die Struktur „IF… ELSE … IF … ELSE“ verwenden.

Einige Aufgaben erfordern mehrere Codezeilen und eignen sich deshalb kaum oder überhaupt nicht für die Umgestaltung mithilfe von „Methode extrahieren“. In diesem Fall empfiehlt es sich, diese Zeilen in Blöcken zusammenzufassen, die durch Leerzeilen getrennt sind. Obwohl die Codesubstanz nicht geändert wird, ist der Code besser lesbar. Wenn Sie Ideen für die Programmierung Ihres Quellcodes suchen, schauen Sie sich einige Open-Source-Projekte an.

Kürzer ist besser

Längere Zeilen sind für das menschliche Auge schwer zu lesen. Aus diesem Grund drucken Zeitschriften und Magazine ihre Artikel in Spalten. Bei der Programmierung von Code sollten Sie nach dem gleichen Prinzip verfahren und die horizontale Länge der Zeilen und den vertikalen Bildlauf der Methoden beschränken. Welches ist die ideale Länge für einen Methodentext? Ab 30 Zeilen sollten Sie sich Gedanken darüber machen, wie Sie Ihren Code umgestalten können. Ob die Struktur der einzelnen Codeelemente durchdacht ist, spiegelt sich schließlich auch in der sinnvollen Organisation der Projektordner sowie der Übereinstimmung von Ordnern und Namespaces wider.

Beim Thema Lesbarkeit und sauberer Code stoßen die meisten auf einen weit verbreiteten Einwand: Die Programmierung von sauberem Code ist schwierig und dauert lange. Um dieses Vorurteil zu entkräften, können Sie zwei Argumente anführen. Zum einen können Sie einen Code-Assistenten verwenden, um sauberen Code zu programmieren. Dieser schlägt Umgestaltungen vor, durchsucht den Code auf fehlerhafte Muster und spürt toten und doppelten Code auf. Wenn Sie alle Assistentenfunktionen nutzen, spricht wirklich kein Grund mehr gegen das Schreiben von sauberem und lesbarem Code. Code-Assistenten werden von zahlreichen führenden Herstellern angeboten, Sie müssen sich nur für einen entscheiden.

Zum anderen tragen Weiterbildungsmaßnahmen dazu bei, dass sauberer Code für jeden Einzelnen zu einer Selbstverständlichkeit wird. Erfahrene Entwickler wissen genau, worauf es ankommt. Im Unterschied zu weniger erfahrenen Entwicklern können sie einschätzen, was gut lesbaren Code ausmacht und gezielt Anpassungen vornehmen.


Dino Esposito ist Mitautor von „Microsoft .NET: Architecting Applications for the Enterprise“ (Microsoft Press, 2014) und „Programming ASP.NET MVC 5“ (Microsoft Press, 2014). Esposito ist Technical Evangelist für die .NET Framework- und Android-Plattformen bei JetBrains und spricht häufig auf Branchenveranstaltungen weltweit. Auf software2cents.wordpress.com und auf Twitter unter twitter.com/despos lässt er uns wissen, welche Softwarevision er verfolgt.

Unser Dank gilt dem folgenden technischen Experten von Microsoft für die Durchsicht dieses Artikels: James McCaffrey