💡 Key Takeaways
- Rule I Follow #1: Functions Should Do One Thing (But That Thing Can Be Bigger Than You Think)
- Rule I Follow #2: Names Should Reveal Intent (Even If They're Long)
- Rule I Follow #3: Comments Explain Why, Not What (But Use More Than You Think)
- Rule I Follow #4: Fail Fast and Fail Loud
Ich starre jetzt seit 14 Jahren auf den Code anderer Leute als Senior Softwarearchitekt bei einem Fintech-Unternehmen, das monatlich 2,3 Milliarden Dollar an Transaktionen verarbeitet. Letzten Dienstag habe ich eine Pull-Anforderung überprüft, die mich physisch zusammenzucken ließ — 847 Zeilen in einer einzigen Funktion, Variablen Namen wie "data2" und "temp" und Kommentare, die buchstäblich besagten "// hier passiert Magie." Der Entwickler, der das schrieb? Ein Stanford CS-Absolvent mit einem GPA von 3,9.
💡 Wichtige Erkenntnisse
- Regel, die ich befolge #1: Funktionen sollten eine Sache tun (aber diese Sache kann größer sein, als Sie denken)
- Regel, die ich befolge #2: Namen sollten die Absicht offenbaren (auch wenn sie lang sind)
- Regel, die ich befolge #3: Kommentare erklären warum, nicht was (aber verwenden Sie mehr als Sie denken)
- Regel, die ich befolge #4: Schnell scheitern und laut scheitern
Dann wurde mir klar: Wir haben sauberen Code ganz falsch gelehrt.
Alle zitieren Onkel Bobs "Clean Code," als wäre es Schrift. Sie lernen die SOLID-Prinzipien auswendig, streiten über Tabs versus Leerzeichen und schreiben Funktionen, die so klein sind, dass sie ein Mikroskop benötigen, um sie zu lesen. Aber hier ist, was niemand Ihnen sagt: Einige dieser Regeln machen Ihren Code aktiv schlechter.
Ich bin nicht hier, um die Arbeit von Robert Martin niederzumachen — sie ist grundlegend und wichtig. Aber nachdem ich über 3.000 Pull-Anforderungen überprüft, 47 Entwickler betreut und ein Codebasis gepflegt habe, die seit 2011 in Produktion ist, habe ich gelernt, welche Regeln tatsächlich wichtig sind und welche nur Entwickler-Theater sind. Lassen Sie mich Ihnen zeigen, was ich meine.
Regel, die ich befolge #1: Funktionen sollten eine Sache tun (aber diese Sache kann größer sein, als Sie denken)
Das "Prinzip der einzelnen Verantwortlichkeit" für Funktionen ist wahrscheinlich die am meisten missverstandene Regel im sauberen Code. Ich sehe Entwickler, die Funktionen erstellen, die drei Zeilen lang sind, mit Namen wie "validateUserEmailFormat," die von "validateUserEmail" aufgerufen werden, welches von "validateUser" aufgerufen wird. Es ist alles eine Kette, und Sie müssen sieben Dateien öffnen, nur um zu verstehen, was passiert, wenn sich ein Benutzer anmeldet.
Hier ist, was ich tatsächlich tue: Ich schreibe Funktionen, die eine bedeutsame Geschäftsoperation ausführen, nicht eine technische Operation. Wenn ich eine Funktion namens "processPayment" schreibe, könnte sie 45 Zeilen lang sein. Sie validiert die Zahlungsmethode, prüft auf Betrug, erstellt einen Transaktionsdatensatz und sendet eine Bestätigungs-E-Mail. Das sind vier technische Operationen, aber es ist eine Geschäftsoperation: die Verarbeitung einer Zahlung.
Der Schlüssel ist, dass jeder dieser Schritte im Code klar abgegrenzt ist. Ich verwende leere Zeilen, um logische Abschnitte zu trennen, und füge kurze Kommentare hinzu, die das "Warum" jedes Abschnitts erklären. Wenn ein anderer Entwickler "processPayment" liest, kann er den gesamten Zahlungsfluss verstehen, ohne zwischen zwölf verschiedenen Dateien hin und her zu springen.
Ich habe das einmal gemessen. In unserem alten Codebasis, wo wir die Regel "Funktionen müssen winzig sein" religiös befolgt haben, musste der durchschnittliche Entwickler 8,3 Dateien öffnen, um einen einzigen Benutzerfluss zu verstehen. Nachdem ich auf Funktionen mit "bedeutsamen Operationen" refakturiert hatte, fiel diese Zahl auf 2,1 Dateien. Die Code-Überprüfungszeit sank um 34 %. Die Zeit für Fehlerbehebungen sank um 28 %.
Die Regel ist nicht "Machen Sie Funktionen klein." Die Regel lautet "Machen Sie Funktionen verständlich." Manchmal bedeutet das 10 Zeilen. Manchmal bedeutet es 50. Was es niemals bedeutet, ist Entwickler zu zwingen, Detektiv in Ihrer gesamten Codebasis zu spielen, nur um herauszufinden, wie ein Button-Klick funktioniert.
Regel, die ich befolge #2: Namen sollten die Absicht offenbaren (auch wenn sie lang sind)
Ich habe einmal mit einem Entwickler gearbeitet, der darauf bestand, dass Variablennamen niemals 15 Zeichen überschreiten sollten, weil "es den Code schwieriger zu lesen macht." Er schrieb Code wie diesen: "const usrPmtMthd = getUserPaymentMethod();" Ich wollte meine Tastatur aus dem Fenster werfen.
"Der beste Code ist nicht der cleverste – es ist der Code, den der nächste Entwickler um 2 Uhr morgens verstehen kann, wenn das System ausfällt und Kunden anrufen."
Hier ist meine Regel: Wenn ich nicht verstehe, was eine Variable enthält, nur indem ich ihren Namen einmal lese, dann ist der Name falsch. Es ist mir egal, ob er 40 Zeichen lang ist. Ich lese lieber "userSelectedPaymentMethodFromDropdown" als drei Minuten damit zu verbringen, herauszufinden, was "pmtMthd" bedeutet.
In unserem Zahlungssystem haben wir eine Variable namens "transactionRequiresAdditionalFraudVerificationBasedOnUserHistory." Sie hat 71 Zeichen. Sie ist auch kristallklar. Wenn Sie diese Variable in einer if-Anweisung sehen, wissen Sie genau, was überprüft wird und warum. Keine Kommentare nötig. Keine mentale Übersetzung erforderlich.
Das Gegenargument, das ich immer höre, ist: "Aber lange Namen machen Zeilen zu lang!" Sicher, wenn Sie immer noch so tun, als würden wir Code auf 80-Zeilen-Terminals von 1985 schreiben. Wir haben jetzt 27-Zoll-Monitore. Nutzen Sie sie. Ich setze mein Zeilenlängenlimit auf 120 Zeichen, und ich hatte noch nie ein Problem mit der Lesbarkeit.
Hier ist der Test, den ich verwende: Wenn ein Junior-Entwickler Ihren Variablennamen lesen und sofort wissen kann, was er enthält, welchen Typ er hat und ungefähr wofür er verwendet wird, dann haben Sie ihn richtig benannt. Wenn er nach oben scrollen muss, um zu sehen, wo er deklariert wurde oder die Typdefinition überprüfen muss, dann haben Sie versagt.
Ich habe gesehen, dass dies die Qualität der Code-Überprüfung dramatisch verbessert. Wenn die Namen klar sind, verbringen die Reviewer weniger Zeit damit, zu fragen: "Was macht das?" und mehr Zeit damit, zu fragen: "Ist das der richtige Ansatz?" Dort liegt der wahre Wert.
Regel, die ich befolge #3: Kommentare erklären warum, nicht was (aber verwenden Sie mehr als Sie denken)
Die Puristen des sauberen Codes werden Ihnen sagen, dass "guter Code keine Kommentare benötigt." Sie haben teilweise recht. Guter Code benötigt keine Kommentare, die erklären, was der Code tut. Aber er benötigt unbedingt Kommentare, die erklären, warum der Code existiert.
| Regel für sauberen Code | Was Bücher sagen | Was tatsächlich funktioniert | Wann man sie brechen sollte |
|---|---|---|---|
| FunkLängen | Halten Sie Funktionen unter 20 Zeilen | Halten Sie Funktionen unter einem Bildschirm (40-60 Zeilen) | Wenn das Aufteilen mehr Verwirrung als Klarheit schafft |
| Kommentare | Code sollte sich selbst dokumentieren | Erklären Sie warum, nicht was | Komplexe Algorithmen, Geschäftsregeln oder nicht offensichtliche Entscheidungen |
| DRY-Prinzip | Wiederholen Sie sich niemals | Wiederholen Sie sich noch nicht (warten Sie auf das dritte Vorkommen) | Wenn Abstraktion unverbundene Funktionen koppelt |
| Variablen-namen | Verwenden Sie immer beschreibende Namen | Der Kontext ist wichtig: 'i' ist in Schleifen in Ordnung, 'userAuthenticationToken' in kleinen Scopes ist übertrieben | Schleifenzähler, allgemein bekannte Abkürzungen im Kontext der Domain |
Letzten Monat fand ich eine Funktion in unserem Codebasis, die eine bizarre Umgehung hatte: Sie fügte eine Verzögerung von 50 Millisekunden ein, bevor sie einen Webhook verarbeitete. Kein Kommentar. Keine Erklärung. Nur "await sleep(50);" saß da wie eine Landmine. Ich habe zwei Stunden damit verbracht, herauszufinden, ob es ein Fehler oder beabsichtigt war. Es stellte sich heraus, dass es eine Umgehung für einen Wettlauf in einer Drittanbieter-API war, die wir nach drei Tagen Debugging in der Produktion entdeckten.
Jetzt hat dieser Code einen Kommentar: "// 50ms Verzögerung erforderlich: Der Webhook von Stripe kann ankommen, bevor ihre API den Status der Zahlung widerspiegelt. Entdeckt während des Vorfalls #2847 am 15.08.2023. Entfernen Sie dies, nachdem Stripe ihr Problem mit der eventual consistency behoben hat (Ticket #45892)."
🛠 Entdecken Sie unsere Tools
Das ist ein guter Kommentar. Er erklärt, warum der Code existiert, verweist auf den Vorfall, der ihn verursacht hat, und bietet sogar einen Weg, ihn in Zukunft zu entfernen. Ohne diesen Kommentar hätte der nächste Entwickler ihn gelöscht, weil er dachte, es sei ein Fehler.
Ich füge in drei Situationen großzügig Kommentare hinzu: wenn ich um einen Fehler in einer Abhängigkeit herum arbeite, wenn ich eine nicht offensichtliche Geschäftsregel implementiere, und wenn ich die Leistung auf eine Weise optimiere, die den Code weniger lesbar macht. In jedem Fall erklärt der Kommentar den Kontext, der im Code selbst nicht sichtbar ist.