Clean Code – Part 2

1. Einleitung
Diese Blogartikel-Reihe soll einen Einblick in die Kriterien für „Clean Code“ geben – damit ist Code gemeint, der unter anderem die Kriterien Lesbarkeit, Testbarkeit und Änderbarkeit/Wartbarkeit erfüllt. Code, der diese Kriterien nicht erfüllt, kann für die lesenden Entwickler schnell anstrengend werden und sie aufhalten.
Mit der Blogartikel-Reihe soll eine Diskussionsbasis geschaffen werden. Aufbauend auf dieser kann dann in Projektgruppen oder in einem Unternehmen eine detaillierte, individuelle Definition von Codequalität erarbeitet werden – denn natürlich gibt es, wie so oft, kein allgemein gültiges Geheimrezept.
Im ersten Teil dieser Reihe [1] ging es um die Benennung von Variablen, Funktionen und Klassen sowie um die Implementierung von Funktionen. Wer die dortigen Tipps befolgt, der ist bereits auf einem guten Weg, sauberen Code zu schreiben. Aber es geht auch noch besser! In diesem Teil des Artikels soll es um das Kommentieren gehen – oder eigentlich eher darum, was alles besser nicht kommentiert werden sollte – und um die Formatierung von Code. Die gesamte Reihe orientiert sich an dem Buch „Clean Code“ von Robert C. Martins [2].
2. Kommentare
Wenn wir Code kommentieren, dann gibt es eine ganz wichtige Regel: „Kommentiere keinen schlechten Code, sondern schreibe ihn neu“ [übersetzt aus 2]. Meistens sind Kommentare tatsächlich ein Hinweis darauf, dass der Code nicht sauber genug geschrieben ist.
Code sollte – das haben wir im ersten Teil schon gelernt – selbsterklärend sein. Und wenn der Code sich selbst erklärt, dann ist ein erklärender Kommentar überflüssig. Aber jetzt stelle man sich vor, ein solcher, selbsterklärender Code würde geändert. Dann würde den überflüssigen Kommentar vermutlich niemand lesen, er würde nicht mit geändert werden und am Ende etwas ganz Falsches erklären oder an der ganz falschen Stelle stehen! Und dann würde uns unser – zunächst ja gut gemeinter und ganz harmlos daherkommender – Kommentar am Ende nur verwirren.
Aber es gibt ja nicht nur Kommentare, die den Code erklären. In Wahrheit ist auch nicht jeder Kommentar ein Zeichen für schlechten Code – nicht, dass nun jemand sofort alle Kommentare in seinem Quellcode löscht, die er jemals geschrieben hat. An der richtigen Stelle, im richtigen Umfang und mit dem richtigen Ziel können Kommentare den Code verständlicher und lesbarer machen! Im Folgenden werden aus [2] entnommene Kriterien für gute Kommentare und schlechte Kommentare aufgelistet – zum Teil direkt mit Beispiel.
Ein Kommentar sollte verwendet werden, wenn…
- … er Copyrights und Autorenschaft des Codes dokumentiert, also rechtliche Hinweise.
/*
* Copyright (c) 2019 eck*cellent IT.
* All rights reserved.
*/
/*
* ATTENTION:
* Running this part of code will take extremely long!
*/
/*
* ATTENTION:
* Altering the following method will break the whole system
*/
Ein Kommentar sollte NICHT verwendet werden, wenn…
- … er „Gemurmel“ ausdrückt – also eigentlich gar nichts. Manchmal ist es durch einen Prozess notwendig oder durch einen Codestyle im Projekt erwünscht, dass Kommentare geschrieben werden. Wenn ein Kommentar geschrieben wird, sollten wir die notwendige Zeit aufbringen, um sicherzustellen, dass es der beste Kommentar ist, der an dieser Stelle stehen könnte.
- … er eine Redundanz darstellt, also nicht mehr aussagt als es der Code bereits tut und diesen auch nicht rechtfertigt (siehe „Absicht“ in der oberen Liste).
// make Bear eat honey 10 times
for (int i = 0; i < 10; i++) {
bear.eatHoney();
}
//send Mail
private void mailToContact(Contact contact) {
mail = Mail.createMail(contact);
}
/* added by Diana on 24th of September, 2019*/
private class Contact{
//…
}
///////////// ACTION! ////////////////
} //if
} //for
/**
* Port on which the hardware would be connected. Defaults to 8082.
*
* @param hardwarePort
*/
public void setHardwarePort(int hardwarePort) {
this.port = hardwarePort;
}
/*
_ _ _ _ _ _ _ _
(c).-.(c) (c).-.(c) (c).-.(c) (c).-.(c)
/ ._. \ / ._. \ / ._. \ / ._. \
_\( Y )/__ __\( Y )/__ __\( Y )/__ __\( Y )/__
(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)
|| B || || E || || A || || R ||
_ .' `-' '._ _.' `-' '._ _.' `-' '._ _.' `-' '._
(.-./`-'\.-.)(.-./`-'\.-.)(.-./`-'\.-.)(.-./`-'\.-.)
`-' `-' `-' `-' `-' `-' `-' `-'
*/
3. Formatierung
Wenn andere Entwickler unseren Code ansehen, dann wollen wir sie damit beeindrucken. Sie sollen am besten auf den ersten Blick sehen, dass hier ein Profi am Werk war – aber wie schaffen wir das? Ein ganz wichtiger Punkt ist die Formatierung. Sie ist eine der Grundlagen zur Kommunikation mit dem Code. Wenn unser Code nicht schön und konsistent formatiert ist, dann wird ein Leser uns möglicherweise unterstellen, dass wir auch Rest des Projekts mit genauso wenig Sorgfalt behandelt haben. [2]
Es gibt zwei Prinzipien, auf die wir achten können, wenn wir eine schöne Formatierung angehen möchten: die vertikale und die horizontale Formatierung.
Vertikale Formatierung
Hier geht es um die Größe von Source Files und die Anordnung des Codes innerhalb dieser.
Auch wenn in Java die Größe der Dateien eng zusammenhängt mit der Größe von Klassen, soll die Klassengröße erst einmal eine untergeordnete Rolle spielen – dazu kommen wir dann im dritten Teil dieser Reihe. Grundsätzlich gilt, dass kürzere Dateien einfacher verständlich sind als längere Dateien. In einer Analyse, die in [2] durchgeführt wurde, stellte sich heraus, dass es möglich ist, signifikante Systeme zu bauen, die aus Dateien mit einer mittleren Länge von 200 Zeilen Code bestehen und bei denen die Dateien 500 Zeilen nicht überschreiten. Das ist ein Ziel, das angestrebt werden sollte.
Zur Anordnung des Codes können wir uns unsere Source-Dateien ein wenig so vorstellen wie einen Zeitungsartikel. Wenn wir einen Zeitungsartikel lesen, dann erwarten wir, dass der Titel erklärt, was in dem Artikel stehen wird, dass der erste Absatz die wichtigsten Informationen ohne viele Details zusammenfasst und dass im Folgenden dann die einzelnen Aspekte noch einmal genauer erläutert werden. So ähnlich können wir es mit den Source-Dateien auch halten: der Name des Moduls sollte uns verraten, ob wir an der richtigen Stelle sind, oben sollten die High-Level-Konzepte und Algorithmen stehen und im weiteren Verlauf immer kleinere Details behandelt werden. [2]
Um eine solche Struktur zu erreichen, gibt es einige Konzepte, auf die wir achten können:
- Die vertikale Dichte ist ein Maß dafür, dass inhaltlich eng zusammenhängende Codezeilen auch dicht beieinander stehen. Variablendeklarationen sollten so nahe bei der Verwendung der Variablen stehen wie möglich, also am besten am Anfang jeder Funktion; Schleifen-Variablen sollten in der Schleifendeklaration stehen; Instanz-Variablen am Anfang der Klasse. Voneinander abhängige Funktionen sollten ebenfalls dicht beieinander stehen. [2]
- Die vertikale Distanz ist allerdings auch wünschenswert – und zwar dann, wenn es um Codezeilen geht, die inhaltlich nicht direkt zusammenhängen. Ein „Absatz“ im Code sollte etwa einem Gedanken entsprechen. Die einzelnen Absätze sollten durch Leerzeilen getrennt werden, sodass beim Lesen ein Gedanke nach dem anderen angesehen und verstanden werden kann. [2]
- Konzeptuelle Affinität: Es gibt Code-Teile (z.B. Funktionen), die einfach gerne zusammen stehen möchten. Je höher die Affinität, desto näher sollten die Teile zusammenstehen. Eine solche Affinität kann sich neben der direkten Abhängigkeit auch dadurch ausdrücken, dass ähnliche Operationen ausgeführt werden (oft erkennbar an ähnlichen Namensgebungen). [2]
private void eatHoney() {
//...
}
private void eatBees() {
//...
}
private void eatFish() {
//...
}
Das Gesamtziel der vertikalen Anordnung ist, dass der Flow innerhalb einer Datei – eben wie in einem Zeitungsartikel – von groben zu detaillierten Konzepten geht. Das wird fast automatisch erreicht, wenn die aufrufende Funktion jeweils über der aufgerufenen Funktion steht; man spricht dann davon, dass Aufruf-Abhängigkeiten von oben unten zeigen.
Horizontale Formatierung
Neben der vertikalen Formatierung ist auch die Horizontale wichtig.
Einigen Entwicklern mag der Name Hollerith noch ein Begriff sein: Herman Hollerith entwickelte 1890 ein Lochkartenverfahren mitsamt Stanz- und Auswertungsmaschinen, das später im Computerbereich weit verbreitet war. Diese Lochkarten hatten eine Zeilenlänge von 80 Zeichen. Die 80 Zeichen wurden dann auch lange über das Ende der Lochkarten-Ära hinaus noch als Grundlage für die maximalen Zeilenlängen von Emails, Texten und auch Terminals verwendet. [5]
Doch genug der Geschichte. Eine Analyse, die in [2] durchgeführt wurde, zeigt: Entwickler präferieren tatsächlich kurze Codezeilen. Etwa 70% der untersuchten Codezeilen war unter 80 Zeichen lang. Auch Zeilen mit 100 oder 120 Zeichen werden durchaus regelmäßig genutzt und sind – laut [2] – auch noch lesbar. Alles was darüber hinausgeht sollte allerdings dringend überprüft werden – vermutlich kann es gekürzt werden.
Einige weitere Faktoren zur schönen horizontalen Formatierung, die in [2] genannt werden, sind im Folgenden aufgelistet:
- Auch in horizontaler Richtung gibt es die Konzepte Dichte und Distanz. Leerzeichen können – genauso wie Leerzeilen, aber auf einer detaillierteren Ebene – verwendet werden, um anzuzeigen, wie eng zusammenhängend Codeteile sind. Beispielsweise werden Zuweisungsoperatoren häufig durch Leerzeichen rechts und links abgetrennt. Das betont, dass sie aus dem Teil bestehen, dem etwas zugewiesen wird und dem Teil, der zugewiesen wird. Funktionsargumente hingegen werden üblicherweise nicht mit Leerzeichen von der Funktion abgetrennt, weil sie enger miteinander zusammenhängen.
int number = 3;
setNumber(number);
private Bear bear;
private String bearName;
private SomethingWithALongName something;
private int bearAge;
private double bearSize;
while(doSomething) { } // Negativbeispiel
while(doSomething) {
} // besser!
Natürlich sind die hier beschriebenen Regeln nicht in Stein gemeißelt. Jeder Entwickler hat seine eigenen Vorlieben, wenn es um Formatierung geht (man sehe sich nur die endlose Diskussion um Tabs oder Leerzeichen an). Wenn er aber in einem Team arbeitet, dann sollte das Team die Regeln bestimmen. Zu Beginn eines Projektes sollten sich alle Entwickler einmal für etwa 10 Minuten zusammensetzen, um einen Coding-Style auszumachen – so können konsistente, leicht lesbare Source Dateien erstellt werden [2]. Es kann darauf vertraut werden, dass Formatierungen, die in einer Datei benutzt wurden, in einer anderen dasselbe bedeuten.
Die wichtigste Regel ist also keine der oben genannten, sondern dass das Team sich auf einen Coding-Style einigt und diesen dann konsistent umsetzt. Schließlich soll es nicht so aussehen, als wäre die Software durch einen Haufen sich widersprechender Individuen entstanden, denn das wirkt unprofessionell – und unser Ziel ist ja, dass unsere Software auf den ersten Blick als das Werk von Profis erkannt wird!
4. Zusammenfassung
In diesem Artikel wurde eine ganze Reihe Regeln vorgestellt, wann Kommentare zu schreiben und wann sie besser zu unterlassen sind. Zusammengefasst lässt sich sagen: Kommentare sollten nur dann verwendet werden, wenn es nicht möglich ist, das, was gesagt werden soll, im Code auszudrücken. Dann allerdings können sie dafür sorgen, den Code verständlicher und lesbarer zu machen. Es ist außerdem wichtig, darauf zu achten, Kommentare zu ändern (oder häufig besser: zu löschen), wenn man Code ändert, damit die Kommentare nicht nutzlos werden. [6] Außerdem haben wir die Konzepte der vertikalen und horizontalen Formatierung kennengelernt und welche Regeln hier für übersichtlichen Code sorgen. Wichtig ist hierbei vor allem, dass alle Mitglieder einen Teams sich einigen, wie formatiert werden soll und sich dann daran halten.
In den meisten Unternehmen gibt es unternehmens- und/oder projektweit spezielle Coding-Styles zum Thema Kommentare und Formatierung, welche von allen Beteiligten eingehalten werden sollen – so ist es einfach, Code zu schreiben, der gleich auf den ersten Blick einen professionellen Eindruck macht.
Wer mehr über Clean Code erfahren möchte, kann noch einmal den ersten Teil dieses Artikels lesen [1] oder sich direkt das Buch [2] schnappen, in dem alles noch einmal ausführlicher beschrieben ist. Natürlich könnt ihr auch gespannt auf den nächsten Teil dieser Artikel-Reihe warten! Dort wird es dann um Objekte, Datenstrukturen und Fehlerbehandlung gehen.
5. Quellen
-
- https://eckcellent-it.blog/clean-code-part-1/
- Clean Code: A Handbook of Agile Software Craftsmanship von Robert C. Martin. Prentice Hall International, ISBN 978-0-13-235088-4.
- https://www.todaysoftmag.com/article/1120/clean-code-comments-and-formatting
- https://improvingsoftware.com/2011/06/27/5-best-practices-for-commenting-your-code/
- https://de.wikipedia.org/wiki/Lochkarte#Hollerith-Lochkarte
- http://nicolecarpenter.github.io/2016/03/08/clean-code-chapter-4-comments.html

Softwareentwicklung