Die letzte Lektion könnte den Eindruck erweckt haben, Kommentare seien grundsätzlich ein Fehler. Das ist falsch — und die Übertreibung in diese Richtung ist genauso schädlich.
Es gibt Information, die der Code nicht ausdrücken kann, weil sie nicht im Code steht. Genau dort gehören Kommentare hin.
Das Warum, das nirgends sonst steht
Der Code sagt, was geschieht. Er kann nicht sagen, warum — und schon gar nicht, warum die naheliegende Alternative nicht gewählt wurde.
// Absichtlich sequenziell: Der Zahlungsanbieter drosselt ab 5 parallelen
// Anfragen pro Händlerkonto und antwortet dann mit 429 statt einer Fehlermeldung.
// Parallel getestet am 2026-03-11, Ticket ZAHL-2291.
foreach (var beleg in belege)
await _gateway.BucheAsync(beleg);Ohne diesen Kommentar wird die Schleife irgendwann von jemandem parallelisiert, der eine Optimierung sieht. Das Wissen steht in keinem Typ, keinem Namen und keiner Signatur — es steht in einer Erfahrung, die jemand gemacht hat.
Weitere Fälle derselben Art:
// Die Schnittstelle des Vorsystems liefert das Datum als "TTMMJJJJ" ohne Trenner.
// Das ist dokumentiert in der Spezifikation "IF-042", Abschnitt 3.2.
var datum = DateTime.ParseExact(feld, "ddMMyyyy", CultureInfo.InvariantCulture);
// Rundung kaufmännisch, nicht bankerrundung: So rechnet die Fachabteilung
// seit jeher, und die Abstimmung mit der Buchhaltung erfordert Gleichstand.
var steuer = Math.Round(netto * satz, 2, MidpointRounding.AwayFromZero);Der Test für einen guten Kommentar
Steht diese Information sonst nirgends? Wenn ja, ist der Kommentar wertvoll — und zwar unabhängig davon, wie sauber der Code darunter ist. Kein noch so guter Name kann ausdrücken, dass ein Fremdsystem ab fünf parallelen Anfragen aussteigt.
Warnungen
Ein Kommentar, der jemanden vor einer plausiblen, aber falschen Änderung bewahrt, zahlt sich schon beim ersten Mal aus:
// ACHTUNG: Reihenfolge ist relevant. Der Steuerschlüssel muss gesetzt sein,
// bevor die Positionen zugewiesen werden, sonst berechnet der Setter falsch.
rechnung.Steuerschluessel = schluessel;
rechnung.Positionen = positionen;Nebenbei: Dieser Kommentar beschreibt einen Entwurfsfehler. Die beste Fassung wäre, die Reihenfolge unmöglich zu machen — indem beides in den Konstruktor wandert. Solange das nicht geht, ist die Warnung das zweitbeste.
Reguläre Ausdrücke und dichte Ausdrücke
Manche Dinge sind aus sich heraus nicht lesbar, egal wie gut man sie benennt:
// Schweizer Postkonto: zwei Ziffern, Bindestrich, ein bis sechs Ziffern,
// Bindestrich, eine Prüfziffer. Beispiel: 01-100-5
private static readonly Regex Postkonto = new Regex(@"^\d{2}-\d{1,6}-\d$");XML-Dokumentation
Für öffentliche APIs — alles, was ausserhalb deines Projekts benutzt wird — ist /// mehr als ein Kommentar: Es erscheint in IntelliSense, landet in der generierten Dokumentation und kann vom Build erzwungen werden.
/// <summary>
/// Bucht einen Beleg beim Zahlungsanbieter.
/// </summary>
/// <param name="beleg">Der zu buchende Beleg. Muss einen Betrag > 0 haben.</param>
/// <returns>Die Buchungsreferenz des Anbieters.</returns>
/// <exception cref="ZahlungAbgelehntException">
/// Der Anbieter hat die Buchung abgelehnt — etwa wegen fehlender Deckung.
/// </exception>
public Task<string> BucheAsync(Beleg beleg) { … }Was hier den Unterschied macht
Nicht die <summary> — die wiederholt fast den Methodennamen. Wertvoll sind <exception> und die Bedingung im <param>: Vorbedingungen und Fehlerfälle sieht man einer Signatur nicht an. Genau die gehören dokumentiert.
Für interne Klassen lohnt sich das selten. <GenerateDocumentationFile> meldet dann für jedes undokumentierte öffentliche Element eine Warnung, und das Ergebnis ist die Sorte /// Holt oder setzt den Namen., die niemandem hilft. Aktiviere es für Bibliotheken, nicht für Anwendungscode.
Kurz nachgedacht
Zählt nicht — nur zum Prüfen, ob es angekommen ist.
1.Welcher Test unterscheidet einen wertvollen von einem überflüssigen Kommentar?