Kommentare

»Tatsächlich, wenn man sich nötigt, Kommentare für den Code zu schreiben, beginnt man ja sogar ansatzweise zu verstehen, was man da tut.«

Christian Heller I @plomlompom, Twitter, 3. Dezember 2009

Wenn Sie selbst programmieren, dann ist es entscheidend, dass Sie daran denken, dass die Leserschaft Ihres Sourcecodes eben nur zum Teil aus Maschinen besteht. Der weitaus wichtigere Teil Ihres Publikums besteht aus anderen Menschen. Sie sind die eigentliche Zielgruppe. Und im Unterschied zum Compiler Ihrer Programmiersprache findet diese Zielgruppe Kommentare oft sehr hilfreich.

BJarne Stroustrup, der Entwickler der Programmiersprache C++, versichert in »The C++ Programming Language«: »Gute Kommentare können genauso schwierig zu schreiben sein wie das eigentliche Programm.« Gehen Sie deshalb nicht zu hart mit sich ins Gericht, venn Ihnen Ihre eigenen Kommentare von vor zwei Wochen wie rätselhafte archäologi-..:he Fundstücke ohne erkennbaren Bezug zur Gegenwart erscheinen. Aber beheben Sie das Problem, denn das Schreiben guter Kommentare ist nicht nur genauso schwierig, sondern auch genauso wichtig wie das Schreiben von gutem Code.

V c man von unverständlichem Code und möglicherweise hinderlichen Kommentaren zu hilfreichen gelangt, soll das folgende Beispiel erläutern.

Dieser C-Code ist unverständlich:

void finalize(RHC* rhc) { int i;

for(i=O; rhc._mIdG->c > i; i=i+l) { free(rhc._mIdG->p[i]);

}

}

Dieser Code hat Kommentare, die ihn um 100% länger machen, ist aber kaum weniger unverständlich:

/* --------------------

*    void finalize(RHC* rhc)

*    Finalizing an RHC structure.

*    rhc: a pointer to the RHC structure to finalize

* --------------------* /

void finalize(RHC* rhc) {

int i;

// iterate over all IdGs // and free their pointers for(i=O; rhc._mIdG->c > i; i=i+l) { free(rhc._mIdG->p[i]);

}

}

Leider ist das oben genannte Beispiel durchaus repräsentativ für viele Programmierprojekte. Kommentare, die einfach nur die in der Programmiersprache formulierte Aussage 1:1 ins Englische - oder ins Deutsche - übersetzen, sind nicht nur wenig hilfreich, sondern sogar kontraproduktiv. Ihre Redundanz wird zum Problem, wenn man den Code umschreibt und dabei vergisst, die Kommentare nachzuziehen. lm Eifer einer nächtlichen Debugging-Session an einer abgestürzten Webapplikation kann es leicht passieren, dass zwar der Code, nicht aber die zugehörigen Kommentare verändert werden. Wenn dann alles wieder läuft, kümmert sich niemand mehr darum, dass sich Englisch und C nun widersprechen, und ein Jahr später wird jemand viel Zeit mit Haareraufen und Zweifeln am eigenen Verstand zubringen. Es bewährt sich, beim Lesen eigener wie fremder Kommentare allgemein nicht davon auszugehen, dass diese Kommentare in irgendeinem sinnvollen Verhältnis zum Code stehen. Betrachten Sie sie wie die Auskünfte eines Betrunkenen: interessiert, aber skeptisch.

Der Code im ersten, unkommentierten Beispiel ist nicht unverständlich, weil Programmiersprachen generell unverständlich für den Menschen sind und einer Übersetzung in Form von Kommentaren bedürften. Er ist unverständlich, weil der Autor keinerlei Mitgefühl für den Leser zeigt. Er ist unverständlich, weil der Autor eine Unzahl von Abkürzungen verwendet, die beim Leser ein detailliertes Wissen über den Rest des Programmcodes voraussetzen. Er ist unverständlich, weil er den Leser im Dunklen darüber lässt, was die Idee hinter diesem Code ist, warum er überhaupt nötig ist - er gibt dem Leser keinen Kontext. Diese Eigenschaften finden sich in der Welt der natürlichen Sprachen so geballt nur noch in Anleitungen der Deutschen Telekom zum Anschluss des NTBA an den ADSL2+-Splitter und das Datenendgerät wieder.

Durch Vermeidung von Abkürzungen und eine Benennung der Funktion, die ihren Zweck offenbart (siehe auch Kapitel 5), erhalten wir folgenden Code:

void freeAllGlobalIDs(RawHandlerContext* rhc) { for(int i=O; i < rhc.globalID->count; ++i) { free(rhc.globalID->buffer[i]);

}

}

Zwar haben wir keine Ahnung, was wohl ein RawHandlerContext sein mag. Immerhin wissen wir jetzt aber, dass es ihn gibt, dass er globale IDs von irgendwas hat und dass diese Funktion diese IDs freigibt. Das sind schon mal sehr viel mehr Informationen. Und das ganz ohne Kommentare.

Und noch eine Version des Codes:

/* Unfortunately this code is necessary because there seems to be a glitch in RawHandlerManager that otherwise leaks GloballD buffers. I have not the slightest idea why.

Hope we can fix that bug soon and then get rid of

this workaround. 2008-07-23 -- regular@muskelfisch.com */

void freeAllGlobalIDs(RawHandlerContext* rhc) { for(int i=O; i < rhc.globaliD->count; ++i) { free(rhc.globaliD->buffer[i]);

}

}

Aha! Dieser Kommentar wiederholt nichts mehr von dem, was bereits im Code steht. Er erklärt uns den Gesamtkontext. Er enthält die Informationen, die für die Maschine irrelevant sind und sich ausschließlich an Menschen richten, weshalb sie nicht in der Programmiersprache ausdrückbar sind. Wir wissen nun, wo wir weiterrecherchieren können, und sogar, wen wir dazu befragen könnten. Noch wichtiger: Wir wissen, dass der Autor mit dieser Funktion unglücklich ist. Und das gibt uns in wenigen Worten einen sehr tiefen Einblick, den wir aus perfektem Code allein nicht hätten gewinnen können.

Mehr ist manchmal mehr

Zur angemessenen Kommentarmenge lässt sich wenig Allgemeingültiges sagen. Sehr schlechte Programmierer kommentieren ihren Code manchmal überhaupt nicht, aber das tun auch viele gute Programmierer. Man kann die beiden daran unterscheiden, dass die guten Programmierer ihren eigenen Code auch später noch verstehen.

»Ich kommentiere sehr viel; manche sagen: viel zu viel. Aber ich habe es gern, wenn mir der Code alles erklärt, als wäre ich vier Jahre alt. lch sehe auch nicht gern viele Codezeilen ohne Leerzeilen dazwischen. Wenn ich irgendwo drei, vier Zeilen sehe, die zusammengehören, dann füge ich eine Leerzeile ein und meistens auch gleich einen kurzen Kommentar, der erklärt, was im nächsten Block passiert. [ ... ] Das einzige Problem, das ich dabei sehe, ist, dass viele Leute vergessen, die Kommentare zu ändern, wenn sich der Code ändert. Dann steht da ein falscher Kommentar, und das ist schlimmer als gar kein Kommentar, weil es den Leser auf eine falsche Fährte lockt.«

Richard Mazorodze, Softwareentwickler

Ratgeber für erfahrenere Programmierer empfehlen, nicht das Offensichtliche noch einmal in Worte zu fassen. Aber nicht alles ist für alle Leser gleichermaßen offensichtlich, und gerade als Anfänger tut man sich mit der Beurteilung schwer, welcher Kommentar -ich später als hilfreich erweisen wird. Wir möchten unseren Lesern daher abweichend

Mehr ist manchmal mehr |    63

vom Empfehlungsstandard dazu raten, erst einmal lieber zu viel als zu wenig zu kommentieren. Mangelhafter, gründlich kommentierter Code ist mangelhaftem, unkommen-tiertem Code klar vorzuziehen. Vielleicht hilft die ausführliche Beschreibung dabei, den Vorgang im Kopf des Programmierers zu strukturieren, ähnlich wie bei kleinen Kindern, die im Laufe des Spracherwerbs eine Phase durchmachen, in der sie laut denken: »Jetzt leg ich den blauen Stein auf den grünen, und dann ...« Selbst wenn man längst ein besserer Programmierer geworden ist, kann man nie wissen, welches hilflose Häschen, das diesen Code vielleicht im Rahmen eines Praktikums einmal lesen muss, sich auch über offensichtliche Hinweise freuen wird. Und wenn es einmal sein muss, sind peinliche Kommentare leichter zu löschen als peinlicher Code - nur weil man sie entfernt, bricht nicht an der anderen Hausecke alles zusammen.

Stellt man allerdings fest, dass man ausufernde Kommentare nur verfasst, um den Code halbwegs verständlich zu machen, dann ist das ein Warnsignal. In diesem Zusammenhang werden häufig die Programmierautoritäten Brian Kernighan und Rob Pike mit dem Satz »Don’t document bad code - rewrite it« zitiert. Das ist natürlich leichter gesagt als getan und kann dazu führen, dass schlechter Code aus Furcht vor Kernighan und Pike nicht kommentiert, aber auch nicht neu geschrieben wird. Deshalb möchten wir den Ratschlag um einen zweiten Teil ergänzen: Wenn man den schlechten Code nicht neu schreibt, soll man ihn wenigstens kommentieren. Sonst vergisst man am Ende noch, was daran schlecht war und warum. Nebenbei ärgert man sich vielleicht währenddessen so sehr über die Kommentarmühe, dass man lieber doch alles neu schreibt.

Zur äußeren Form von Kommentaren

Es gibt in vielen Sprachen zwei Arten von Kommentaren: Inline-Kommentare, die am Ende der Codezeile stehen, und mehrzeilige Kommentare, die vor dem betreffenden Code stehen und sich über mehrere Zeilen erstrecken können.

Inline-Kommentare sind mit einem speziellen Kommentarzeichen vom Codeteil der Zeile abgesetzt, je nach Sprache zum Beispiel / /, # oder - -.

II set the default color color = "#ff0000" II insanely red if ( (rowlndex % 2) == o) { II even rows only color = "#303060" II a blueish shade of gray

}

Für mehrzeilige Kommentare hat sich in vielen Sprachen der C++-Standard durchgesetzt:

I* To make our table more friendly to the eye

*    we use two alternating colors for the table row

*    background.

*I

Der englische Wikipedia-Eintrag Comment (Computer programming)1 enthält einen Überblick über die Kommentarstile in verschiedenen Sprachen.

Anfänger benutzen oft nur eine der Varianten, mehrzeilig oder inline. Tatsächlich haben aber beide ihre spezifischen Einsatzgebiete. Die meisten Kommentare sind auf eigenen Zeilen gut aufgehoben. Erstens sind sie dort beim Lesen des Codes leichter zu überblicken. Zweitens hat man auf eigenen Zeilen mehr Platz und ist deshalb weniger stark versucht, Kommentare auf Kürze statt auf Verständlichkeit zu optimieren. Die ZeilenendeVariante hingegen eignet sich zur Dokumentation von Parametern und Variablen und wird häufig verwendet, um beispielsweise die Maßeinheit und den Wertebereich einer Variablen anzugeben:

const float speedLimit = 300.0; II meters per second

global int timeLastMoved = 0; II in milliseconds since start of the program .. viele Zeilen anderer Code ... void moveSpaceship(

int currentTime, II in milliseconds since start of program (needs to be >=0) float deltaX, II horizontal movement in meters float deltaY II vertical movement in meters

) {

spaceShip.x += deltaX; spaceShip.y +; deltaY;

II calculate the distance the spaceship was just moved II using formula aA2 + bA2 = cA2

float distanceMoved = squareRoot(deltaX* detaX + deltaY* detlaY);

II calculate number of seconds passed since last movement

float deltaT = (currentTime - timelastMoved) I 1000.0; II calculate speed in meters per second

float speed = distanceMoved I deltaT;

II if we have no record of when we were called

II the last time, we cannot calculate the ship's speed

if (timeLastMoved != 0) {

II is the spaceship faster than allowed? boolean tooFast ; speed > speedlimit; if (tooFast) {

}

}

II remember current time for next call timelastMoved = currentTime;

}

Dabei ergibt sich ein Problem: Oft hat der Programmierer beim Lesen des Codes weder . Variablendeklaration noch den dort stehenden Kommentar im Blick, geschweige .Jcnn im Kopf. Da aber zum Beispiel die Maßeinheit von speedLimit im Beispiel oben nur in der Deklaration erwähnt wird, müsste er dort nachsehen, um sicherzustellen, dass bei einem Vergleich der Form speed > speedLimit nicht Äpfel mit Birnen verglichen

en.wikipi,dia.org/wiki/Comment_(computer_programming)#Stylcs.

Zur äußeren Form von Kommentaren |    65

werden. Besser ist es daher, die Maßeinheit in den Variablennamen aufzunehmen (siehe Kapitel 5). Dann reicht ein einziger Blick, um die Korrektheit des Codes zu überprüfen: speedlnMetersPerSecond > speedLimitlnMetersPerSecond.

Eine Angabe des gültigen Wertebereichs zum Beispiel für einen Funktionsparameter (im Beispiel oben muss currentTime ein positiver Wen sein) ist sehr hilfreich. Noch besser ist es, diese Angabe gleich vom Computer testen zu lassen, hierfür gibt es die As sert-Anwsi-sung (siehe den Abschnitt »Assertions« in Kapitel 26).

Mehrzeilige Kommentare sollten vor dem Code stehen. Das sorgt dafür, dass man bei kritischen Codeblöcken erst den Kommentar wahrnimmt und sich nicht schon länger den Kopf über den Code zerbrochen hat. Ein Beispiel:

webSettings.setJavaScriptCanOpenWindowsAutomatically(false); webView.setWebViewClient(new KCWebViewClient());

/* Warkaround for

*    https://code.google.com/p/android/issues/detail?id=12987 "WebView

*    is broken on Android 2.3". Warkaround courtesy of

*    http://quitenoteworthy.blogspot.com/2010/12/handling-android-23-webviews-broken.html */

if ((Build.VERSION.SDK_INT == 9) II (Build.VERSION.SDK_INT == 10)) { javascriptlnterfaceBroken = true; webView.setWebChromeClient(new KCWebChromeClient());

}

Der Kommentar bezieht sich auf den if-Block und soll mit den Links erläutern, warum hier seltsame Bedingungen abgefragt werden, um Features des Programms auf bestimmten Versionen der Plattform abzuschalten.

Mehrzeilige Kommentare werden zusammen mit der Zeile eingerückt, zu der sie gehören (hier also die if-Anweisung), damit sie auch optisch einen Bezug zu ihrem Code bekommen

Kommentare müssen möglichst nah an den Zeilen stehen, die sie betreffen, sonst ist es nicht nur unwahrscheinlich, sondern praktisch ausgeschlossen, dass man sie jemals zusammen mit dem Code ändern wird. Statt einen ganzen Roman am Anfang einer Funktion schreibt man also besser kurze Kommentare vor ihre Einzelteile.

Dokumentationskommentare

Die oben beschriebenen Kommentare sind für Leser des Sourcecodes gedacht und stehen deshalb im Code an den Stellen, auf die sie sich beziehen. Eine andere Art von Kommentaren, die sogenannten Dokumentationskommentare, ist dazu bestimmt, durch Dokumentationsgeneratoren aus den Source-Dateien herausgezogen und in externe Dokumentation verwandelt zu werden, beispielsweise in Form von HTML-Seiten.

Dokumentationskommentare stehen immer oberhalb von Variablen bzw. Funktionen oder am Anfang von Klassendefinitionen und beschreiben die Klasse oder direkt folgende

Funktion oder Variable. Für den Compiler sind es normale Kommentare, die durch zusätzliche Formatierungszeichen dem Dokumentationsgenerator verraten, dass sie durch diesen verarbeitet werden wollen.

Java war bei der Verwendung von Dokumentationskommentaren führend: Bereits die ersten Versionen der Sprache wurden durch diese Kommentarform, hier javaDoc genannt, dokumentiert. Ein JavaDoc-Kommentarblock vor einer Methode sieht ungefähr folgendermaßen aus:

/**

*    Constructor and main entry point for reading a board page

*

*    @date: 10.11.2009 17:27:11

*    @author Johannes Jander

*

*    @param url URL to load and parse

*    @param boardDbld unique ID of board in database

*    @return parsed page content *I

public String KCPageParser(String url, long boardDbld) {

}

Normale mehrzeilige Codekommentare sind bei Java in /*    */ eingeschlossen. Das

zusätzliche Sternchen am Beginn des Kommentars kennzeichnet ihn als JavaDoc-Kom-mentar.

Dokumentationskommentare haben eine bestimmte Struktur: Der erste Absatz enthält eme kurze Beschreibung der Klasse oder der dokumentierten Funktion. Er soll einem Programmierer ermöglichen, diesen Code zu verwenden, ohne den Code selbst lesen zu müssen, indem er kurz erläutert, was der Code bezweckt. Daraufhin folgen bei einer Funktion ihre Parameter, die jeweils mit @param gekennzeichnet werden, und durch §return benannt das Resultat der Funktion. Weitere Felder wie @author oder @version -.md weniger gebräuchlich.

In anderen Sprachen existieren teilweise ähnliche, teilweise unterschiedliche Dokumentationsgeneratoren: RDoc für Ruby, Docstrings für Python, Doxygen für C++. Perl hat ein Dokumentationssystem (>>pod«), das etwas anders funktioniert, und C# hat ein XMLDOC genanntes System, bei dem Dokumentationskommentare in XML geschrieben werden.

Wann und was soll man kommentieren?

Kammentare sind kein dekoratives Element, das man ganz zum Schluss anbringt, wenn die eigentliche Arbeit getan ist.1 Bei Menschen von durchschnittlicher (lies: nicht vorhandener) Selbstdisziplin und Willenskraft findet dieser letzte Schritt sowieso nie statt. Und - Ausnahme: Ein Hase in ASClI-Art am Dateiende.

selbst wenn man sich dazu durchringt, hat man die Hälfte der Überlegungen, die einen beim Schreiben des Codes beschäftigten, schon wieder vergessen. Besser ist es daher, die Kommentare zusammen mit dem Code zu schreiben. Wenn einem der Code so viel Konzentration abverlangt, dass man währenddessen keine Kommentare schreiben kann, dann handelt es sich um Code, den man besser gar nicht erst schreibt - nämlich um viel zu komplizierten. Manche Autoren empfehlen sogar, die Kommentare vor dem Code zu schreiben. Denn wenn man zuerst in Pseudocode darlegt, was man plant, verheddert man sich nicht in den Details der Umsetzung, sondern hat Zeit, erst einmal über das allgemeine Design des Codes nachzudenken. Der Pseudocode funktioniert dann als Erklärung für einen selbst und andere Leser. Nebenbei kann man durch den Vergleich von Kommentar und Code überprüfen, ob man wirklich das geschrieben hat, was man ursprünglich vorhatte.

Als Faustregel kann man sich daran orientieren, dass ein Kommentar alles enthalten sollte, was man auch seinen Kollegen sagen würde, ginge man mit ihnen den Code durch. Idealerweise wiederholt der Kommentar dabei nicht das, was der Code tut, sondern beschreibt, was der Code tun sollte und warum. Es ist kein Fehler, dabei statt des spezifischen Lösungswegs das allgemeine Konzept zu beschreiben. (Das hat nebenbei den Vorteil, dass der Kommentar nicht geändert werden muss, wenn man später dasselbe Ziel auf andere, elegantere Weise erreicht.) Ein gutes Zeichen ist es, wenn Ihre Kommentare ein »weil ...« enthalten. Schreiben Sie also nicht einfach nur »Loop rückwärts durch das Array«, sondern >>Loop rückwärts durch das Array, weil die Default-Sortierung in der Anzeige absteigend ist«. Dass das Array rückwärts durchlaufen wird, kann man dem Code relativ leicht ansehen, warum das geschieht, aber nicht.

Wenn Sie vor Ihre Funktionen und Methoden Kommentare schreiben, die deren Bedeutung erläutern, können Sie dazu eine Erzählform nutzen: »Ich möchte, dass die Funktion von einem gegebenen Startwert die nächsten 50 Einträge aus der USER-Tabelle holt. Falls keine weiteren 50 Einträge vorhanden sind, soll sie mir eben die restlichen geben. Wenn der Startwert größer als die Zahl der Einträge der Tabelle ist, soll sie nichts zurückliefern, und wenn er kleiner 0 ist, einen Fehler werfen«. Diese weniger technische Form hat den Vorteil, dass Sie nicht so sehr in Versuchung geführt werden, den bestehenden Code zu beschreiben. Sie hilft Ihnen, stattdessen die Anforderungen und das gewünschte Verhalten zu notieren.

Unser Beispiel ist von den »User Stories« aus der Agilen Softwareentwicklung abgeleitet, die immer in der Ich-Form erzählt sind. Eine andere häufige Kommentarperspektive ist das Wir:

II we need to check if the file exists before we write to it

Damit können unterschiedliche Wirs gemeint sein: >>Wir, die Entwickler dieses Codes«, »Ich und die Technik, wir beide« oder >>Ich als Autor und du als Leser, wir beide«. Ebenfalls gebräuchliche Varianten sind die direkte Anrede,

II you need to change this value to 0 for debugging

Passivkonstruktionen

II this value needs to be changed to 0 for debugging

und die uneindeutige Form

II check if the file exists, then write to it

Deutschsprachige Programmierer neigen zu Passivkonstruktionen - auch wenn sie Englisch schreiben. Das hat den Nachteil, dass man häufig nicht weiß, wer da agiert. Es sollte 1mmer klar formuliert sein, wer da etwas tut: der beschriebene Code, der aufrufende Code, ein bestimmtes Objekt, der Benutzer oder mystische Kräfte des Universums.

Davon abgesehen, ist die Entscheidung Geschmackssache, und es ist auch nicht nötig, -Ich konsequent an eine bestimmte Variante zu halten. In manchen Situationen bietet q eh eine bestimmte Form an, etwa die »you<<-Form, wenn man Leserinnen des Codes erklärt, wie eine API zu benutzen ist. Geht es um das Eingeständnis schändlicher Hacks, sollten Sie zur Ich-Form stehen. Versetzen Sie sich beim Schreiben hin und wieder in die Leserperspektive, damit es Ihnen nicht ergeht wie »mrgoat«, der über warnende Kommentare der Form »Don't be tempted to do blah without looking at foo« schreibt: »Ich fv früher selbst so kommentiert. Später musste ich dann was am Code reparieren und \ar beleidigt wegen der arroganten Unterstellungen von irgendeinem Programmiereridioten. >Tja<, dachte ich, >du kannst mich mal mit deinem bugverseuchten Code!< Und dann fiel mir wieder ein, dass der Code von mir war.«2

Anzeichen, dass ein Kommentar eine gute Idee wäre

Wenn der Code unerwartetes Verhalten zeigt

Normalerweise sollten Sie dieses Verhalten zwar beseitigen, aber vielleicht verwenden Sie Fremdcode, Frameworks oder APls, auf die Sie wenig Einfluss haben. Wenn etwas beim ten Lesen kontraintuitiv ist, dann wird es das beim zweiten Mal auch noch sein und gehört kommentiert. Das folgende Beispiel (in Java) illustriert dieses Prinzip.3

File tempFile = new File(tempFStr);

FileOutputStream out = new FileOutputStream (tempFile);

out.write(content);

out.close();

I* If we cannot move files across file system boundaries, we have to do a copy and rename. See the API-docs for the reasoning:

(http://docs.oracle.com/javase/7/docs/api/java/io/File.html#renameTo(java.io.File)):

"Many aspects of the behavior of this method are inherently platform-dependent: The rename operation might not be able to move a file from one filesystem to another, it might not be atomic, and it might not succeed if a file with the destination abstract pathname already exists. The return value should always be checked to make sure that the rename operation was successful."*/

if (!tempFile.renameTo(outFile)) {

FilelnputStream source = new FilelnputStream(tempFile);

FileOutputStream destination ; new FileOutputStream(outFile);

FileChannel sourceFileChannel ; source.getChannel();

FileChannel destinationFileChannel = destination.getChannel(); sourceFileChannel.transferTo(o, sourceFileChannel.size(), destinationFileChannel);

}

Hier passiert Folgendes: Unser Programm soll eine Datei mit Messwerten von einem Webserver füllen. Dabei darf nicht etwa bei einem Verbindungsabbruch nur die Hälfte der Daten geschrieben werden, sondern es soll das Prinzip »ganz oder gar nicht« gelten. Daher schreiben wir die Daten (content) zunächst in eine temporäre Datei. Weil wir gesetzesneue Bürger sind, haben wir diese Datei im Verzeichnis für temporäre Dateien, dem temp-Verzeichnis angelegt, das Schreiben hat geklappt und wir sind uns an dieser Stelle sicher, dass wir den Inhalt der temporären Datei verwenden können.

Wir möchten die in Java vorhandene renameTo( )-Methode verwenden, um die temporäre Datei an ihren endgültigen Ort zu verschieben. Die Erwartung wäre, dass das bis auf Fehlerfälle (am Zielort existiert bereits eine Datei gleichen Namens) problemlos klappt.

Leider stellt sich dann aber heraus, dass Java intern nur die systemeigene Funktion zum Verschieben und Umbenennen von Dateien verwendet - und diese hat z. ß. unter Linux die Eigenschaft, nicht über Filesystem-Grenzen hinweg verschieben zu können (also z. ß. von einer Fe tplatte auf eine andere). Damit scheitert auch ihrJava-Pendant dann kläglich, wenn das temp-Verzeichnis auf einer anderen Festplatte als das Zielverzeichnis liegt (und das ist so ungewöhnlich nicht). Die Entwickler der renameTo() - Methode haben sich unschönerweise für einen Booleschen Rückgabewert entschieden, der nur den Erfolg der Operation anzeigt, anstatt die Fehlerursache - etwa durch eine Exception - zu nennen.

Kein großes Problem, in diesem Fall kopieren wir die Datei einfach an ihren neuen Ort (im Beispiel sind noch ein paar Fehlerfälle und ihre Behandlung ausgelassen) und können dann die temporäre Datei löschen. Das dauert zwar länger, führt aber auch zum Ziel. Da diese Einschränkung von renameTo() schnell in Vergessenheit geraten kann, ist ein Kommentar sehr sinnvoll, der einem auch zwei Jahre später noch erklärt, warum man den Erfolg von renameTo() prüft und im Fehlerfall eine andere Art wählt, um die Datei an ihren endgültigen Platz zu befördern.

Wenn Sie Überarbeitungsbedarf sehen, aber gerade nicht genug Aufmerksamkeit oder Zeit übrig haben

Allein die Tatsache, dass ein Codeabschnitt überarbeitet oder neu geschrieben werden muss, ist einen Kommentar wert. Hat man erkannt, dass ein Rewrite nötig ist, es fehlt aber gerade die Muße dafür, weil die Aufmerksamkeit auf ein anderes Problem gerichtet ist, hilft ein Kommentar in der Form »TODO: this code is bad, rewrite it« zumindest, die 'teile zu markieren. Die Information, dass der Autor beim Schreiben nicht von seinem Code überzeugt war, ist immerhin besser als gar nichts. Noch besser natürlich, er schreibt auch dazu, warum.

Der folgende Kommentar ist schlecht (er stammt aus dem Code der Riesenmaschine-Blog-Engine). Trotzdem war es kein Fehler, ihn zu schreiben:

# TODO: ein bisschen bescheuert ist das schon

Was hier warum bescheuert ist, bleibt unklar. Aber immerhin teilt der Kommentar der nächsten Leserin mit, dass bei zukünftigen Änderungen an dieser Stelle erhöhte Vorsicht geboten ist.

Wahrscheinlich wusste die Autorin des Kommemars im Moment des Schreibens sogar, \as an dieser Stelle nicht stimmte. Sie hielt das Problem jedoch für offensichtlich und glaubte daher, es sei nicht nötig, die Details im Kommentar niederzulegen. Wenn Sie zufällig gerade a) verstehen, was der Missstand ist und b) womöglich sogar eine Idee Haben, wie man ihn beheben könnte: Schreiben Sie beides unbedingt sofort auf! Was sich m diesem Moment wie selbstverständliches Wissen anfühlt, fällt Ihnen in Wirklichkeit nur auf, weil Sie gerade im Thema drin sind.

Entscheiden Sie sich für eine einheitliche Kennzeichnung solcher Stellen, schreiben Sie also nicht »to do<<, »TODO«, »FIXME«, »XXX« und »!!!!!« durcheinander, das erschwert die spätere Suche nach Problemen. Eine gängige Konvention ist, >>TODO« für alles zu envenden, was nicht kaputt, aber verbesserungsfähig ist. Mit >>FlXME<< Markiertes ist ekanntermaßen kaputt, und >>XXX<< kennzeichnet das Code-Äquivalent von heraushän-.:enclen Starkstromkabeln. Hierzu gehört am besten eine entsprechende Regel im Projekt: TODOS, FlXMEs usw. sind grundsätzlich vor dem nächsten Release zu beseitigen.

TODO-Kommentare

In vielen Entwicklungsumgebungen werden Kommentare, die mit >>TODO« anfangen, als Aufgaben für später geführt. Es gibt eine spezielle Ansicht, die die ganzen TODOs auflistet, und diese Punkte werden beim Compile auch gerne als eigene Problemklasse aufgezählt.

Wenn der Code nur für einen eingeschränkten Anwendungsbereich bestimmt ist

Aaron Darling, Bioinformatiker an der University of California, berichtet in der Zeitschrift Nature von einem durch fahrlässige Dokumentation verursachten Problem: 'ein Code zum Vergleich von Genomen war nur für die Arbeit mit nah verwandten rganismen ausgelegt. Weil er diese Einschränkung nicht deutlich genug erwähnte, envendeten andere Forscher seinen Code zum Vergleich entfernter Verwandter, was einer unbrauchbaren Veröffentlichung führte: >>Es war reines Glück, dass mir das aufgefallen ist, denn die veröffentlichten Ergebnisse der anderen waren komplett

falsch, aber das konnten sie nicht wissen, weil ich meinen Code nicht ausreichend dokumentiert hatte.«4

Wenn Sie Codeteile »vorübergehend« auskommentieren

Oft wird zum Testen ein Codeteil auskommentiert, der zum Beispiel prüft, ob ein Benutzer berechtigt ist, eine Funktion auszuführen. Das ist ein schneller und bequemer Weg, einzelne Codeteile zu debuggen5 (siehe Kapitel l6). Klingelt dann aber im falschen Moment das Telefon, besteht die Gefahr, dass ein solcher Codeteil versehentlich auskommentiert bleibt (/* if (not user_is_authorized) return*/'). Gleich zu Anfang ein »^X« zu vermerken, hilft dabei, diese Stelle wiederzufinden. Noch besser: Man notiert den Grund für die Auskommentierung, denn wer weiß, ob man nach dem Telefonklingeln nicht vielleicht erst nächstes Jahr wieder an diese Stelle im Code zurückkehrt. Dasselbe gilt sinngemäß für vorübergehend geänderte Werte: $days_to_keep = 1; / / CHANGEME ist weniger hilfreich als $days_to_keep = 1; // XXX change me back to 7'.

Wenn Sie einen naheliegenden Lösungsansatz schon ausprobiert haben und damit gescheitert sind

Der Gedanke, der Ihnen heute naheliegend erscheint, wird das vermutlich in drei Monaten wieder tun, und dann verschwenden Sie ein zweites Mal Zeit in derselben Sackgasse. Kommentieren Sie den Code aus und vermerken Sie so etwas wie:

II This doesn't work (for reasons unknown)

Wenn Sie unseren guten Rat ignorieren, ein Versionskontrollsystem einzusetzen

In diesem Fall ist es hilfreich, alle Änderungen mit einem Datum zu versehen. Wenn mehrere Personen am Code arbeiten, empfiehlt sich außerdem ein Namenskürzel. So haben Sie drei Wochen später, wenn nichts mehr geht, eine Chance, zu erahnen, woran das liegt. Das gilt insbesondere für Änderungen, die Sie nicht so ganz verstehen oder für heikel halten. Nachteil: Sie werden den Vermerk niemals anpassen, wenn Sie den Code verändern. Denken Sie noch einmal über ein Versionskontrollsystem nach.

Wenn eine Lösung auf den Betrachter unnötig kompliziert wirken könnte

Wenn Sie tatsächlich einmal eine schlaue Lösung gefunden haben, belegen Sie deren Schlauheit am besten (»Code wird dadurch um 75% schneller«) und begründen auch, warum sie besonders schlau ist. Die Ursache kann ja möglicherweise längst weggefallen sein, wenn Sie das nächste Mal auf den Code sehen. Wenn Sie Ihre Lösung unkommen-tiert lassen, kommt sonst demnächst jemand, der den Code für reine Angeberei auf Kosten der Lesbarkeit hält, und macht alles wieder zunichte.

Wenn Sie schon wissen oder ahnen, dass Sie gerade etwas falsch machen

W enn Sie beispielsweise nicht testen, ob etwas wirklich passiert ist, sondern es nur aus irgendwelchen indirekten Zeichen ableiten oder schlicht annehmen, dann verschweigen Me diesen Sachverhalt nicht schamvoll. Schreiben Sie einen ehrlichen Kommentar und markieren Sie ihn mit einem TODO. Wenn es später Probleme gibt, können Sie auf diese Art schneller zur Ursache Vordringen.

Wenn Sie öfter unter Verwirrung angesichts Ihrer verschlungenen Kontrollstrukturen leiden

Ae könnten es sich zur Gewohnheit machen, das Ende solcher Strukturen mit einem Kommentar zu versehen:

for (cat_counter = 0; cat_counter < count(cats); cat_counter++) { if (cat_counter % 2 != 0) {

for (hedgehog_counter = 0; hedgehog_counter < count(hedgehogs); hedgehog_ counter++) {

II hier steht viel Code

} II end for hedgehog_counter } else {

II hier steht noch mehr Code

} II end if cat_counter ; II end for catcounter

Langfristig sollten Sie versuchen, zu kürzeren, übersichtlicheren Kontrollstrukturen zu gelangen. Ein paar Vorschläge, wie das gehen könnte, finden Sie in Kapitel 15.

A enn Fremdcodeschnipsel zum Einsatz kommen

ermerkc-n Sie die Quelle des fremden Codes. Vielleicht tauchen später Fragen dazu auf, vielleicht stellt der Autor eines Tages auch eine neue und verbesserte Version zur Verfügung. (Achtung: Das gilt wirklich nur für Schnipsel. Wenn Sie größere Mengen Fremdcode einbinden, also alles in der Größenordnung zwischen ein paar Zeilen und einer _anzen Bibliothek, sollten Sie den fremden Code als separate Datei einsetzen und diese Datei unbedingt unverändert lassen.)

Wenn mitten im Code Zahlen auftauchen

Nachdem Sie Kapitel 14 gelesen und beherzigt haben, stehen in Ihrem Code hoffentlich :eine Zahlen mehr einfach so im Weg herum. Sie haben diese Zahlen in Konstanten gesteckt. Die Definition einer solchen Konstante gewinnt fast immer an Nützlichkeit, venn Sie noch einen Kommentar hinzufügen, der erläutert, warum Sie sich gerade für „ en Wert entschieden haben und wofür er verwendet wird.

Selbst wenn der Grund

II found by trial and error: this value seems to provide II the least retina-scorching colors

lautet, helfen Sie Ihren Lesern damit weiter.

1

Wann und wassoll man kommentieren? |    67

2

wie. hulver.com/scoop/poU/l 086869940_ZZXTfTN N.

3

Dieses Beispiel ist stark vereinfacht, zum Beispiel fehlt jede Fehlerbehandlung. Außerdem wäre es sinnvoller, stattdessen eine Bibliothek wie »FileUtils« von Apache Commons zu verwenden, die das renameTo-Problem selbstständig berücksichtigt. Aber dann gäbe es hier kein Beispiel, also nehmen Sie es bitte nicht so genau.

4

   u’U’U’.nature.comlnatureljournalM67/n 7317/index.html.

5

   Leider ist es aber auch ein Zeichen für schlechtes Design. Besser wäre es, den Code testbar anzulegen und entsprechende Testroutmen zu schreiben (siehe Kapitel 16).