Code lesen statt Code schreiben: Die unterschätzte Senior-Disziplin
Joel Spolsky warnte schon 2000 davor, Code lieber neu zu schreiben als zu lesen. Mit LLMs wird seine Diagnose zur drängenden Frage für jedes Team.
(Bild: Gorodenkoff/Shutterstock.com)
- Golo Roden
Im April 2000 veröffentlichte Stack-Overflow-Gründer Joel Spolsky einen Aufsatz mit dem Titel „Things You Should Never Do, Part I“. Anlass war die Entscheidung von Netscape, den Code des damaligen Browsers von Grund auf neu zu schreiben, statt den vorhandenen weiterzuentwickeln.
Spolskys These: Diese Entscheidung sei der schlimmste strategische Fehler, den eine Softwarefirma machen könne. Sie beruhe auf einem fundamentalen Missverständnis darüber, was Programmierarbeit eigentlich ist. Programmiererinnen und Programmierer schrieben lieber neu, weil das Lesen fremden Codes mühsam sei und sich das Schreiben produktiv anfühle. Doch dieser Eindruck täusche. Die Verlockung, neu anzufangen, sei eine der teuersten Versuchungen der Branche.
Über 25 Jahre später hat dieser Text nichts von seiner Aktualität verloren. Im Gegenteil. Mit dem Auftauchen von Large Language Models (LLM) hat sich die Asymmetrie zwischen Schreiben und Lesen so verschoben, dass die Frage akut wird, ob wir die eigentliche Senior-Disziplin der Softwareentwicklung systematisch unterschätzen. Das Tippen ist nicht das, was Teams in den nächsten Jahren ihren Atem rauben wird. Das Lesen ist es. In diesem Beitrag möchte ich zeigen, warum das so ist, woher die Asymmetrie kommt, wie sie sich durch generative KI verschärft und wie aus einer beiläufigen Begleitfähigkeit eine eigenständige Disziplin werden müsste.
Der eigene Code wird nach drei Wochen zu fremdem Code
Beim Schreiben hat man alles gleichzeitig im Kopf: die Anforderung, das Datenmodell, die geplante Architektur, die Stelle, an der man gerade arbeitet, die Annahmen, die man trifft, die Trade-offs, die man eingeht. Diese mentale Gesamtsicht macht das Schreiben schnell. Sie ist gleichzeitig das, was beim Lesen fehlt.
Wer drei Wochen später denselben Code wieder vor sich hat, ohne den Kontext mitzubringen, muss diese Gesamtsicht rekonstruieren. Variablennamen geben Hinweise, Tests sagen mehr, ein Pull-Request-Kommentar liefert im Bestfall den fachlichen Anlass, eine Commit-Message mit Glück die letzte Begründung. Die eigentliche Intention, das gedachte Modell, die verworfenen Alternativen, all das ist verloren. Rekonstruieren kostet Zeit und Konzentration, und beides ist teurer als das Schreiben.
Videos by heise
Spolskys Anekdote ist deshalb so anschaulich, weil sie diese Asymmetrie auf Organisationsebene zeigt. Bei Netscape stand man vor einer alten Codebasis, die niemand mehr durchschauen wollte. Die Verlockung lag nahe, das Ganze einfach neu zu schreiben. Das Ergebnis ist bekannt: drei Jahre Stillstand, ein verlorener Browser-Markt, eine Firma im Niedergang. Der vermeintlich einfachere Weg war der teuerste.
Auf individueller Ebene zeigt sich dasselbe Muster täglich. Es zeigt sich in Stack-Overflow-Antworten, die statt der Frage einen anderen Lösungsansatz vorschlagen. Es zeigt sich in Kolleginnen und Kollegen, die Refactorings vorschlagen, ohne den vorhandenen Code wirklich verstanden zu haben. Es zeigt sich in der eigenen Versuchung, ein Modul lieber zu ersetzen als zu verbessern. Lesen ist und bleibt unbequem.
LLMs kippen die Bilanz endgültig
Ein modernes LLM erzeugt mehrere Hundert Zeilen Code in der Zeit, in der eine Person diese Zeilen einmal überfliegen kann. Generieren ist billig geworden. Token sind billig, Wartezeiten kurz, und das mentale Modell für die Aufgabe ist auf das Formulieren eines Prompts geschrumpft. Der Aufwand auf der Schreibseite ist faktisch zusammengebrochen.
Auf der Leseseite hat sich nichts geändert. Verstehen kostet noch immer das, was es immer gekostet hat: konzentrierte Aufmerksamkeit, Zeit, Geduld. Die menschliche Verarbeitungsgeschwindigkeit für Code liegt grob bei einigen Zeilen pro Minute, je nach Komplexität deutlich darunter. Diese Größenordnung lässt sich nicht durch Werkzeuge beschleunigen, weil sie an der menschlichen Kognition selbst hängt.
Das Resultat ist eine groteske Verschiebung. Wo früher eine Tagesarbeit etwa hundert Zeilen Code produzierte, die ein Reviewer in einer halben Stunde durchgehen konnte, kann heute eine Stunde Promptarbeit Tausende Zeilen erzeugen. Die zu verstehende Menge wächst dramatisch, die Geschwindigkeit des Verstehens bleibt konstant. Was früher ein Engpass beim Schreiben war, wird zum Engpass beim Verstehen.
Diese Verschiebung wird in vielen Diskussionen ignoriert. Man feiert die Produktivität auf der Generierungsseite und schweigt über die Bilanz, die sich auf der Leseseite auftut. Was nicht gelesen wird, wird nicht verstanden. Was nicht verstanden wird, wird nicht zuverlässig betrieben. Die Schulden verschieben sich nur in die Zukunft, sie verschwinden nicht.
Sichtbar wird das spätestens dort, wo Code-Review-Prozesse, die für die Geschwindigkeit der Vor-LLM-Ära konzipiert waren, plötzlich mit Pull-Requests konfrontiert sind, deren Umfang ein menschlicher Reviewer in einem ganzen Tag nicht durchdringen könnte. Die Reaktion ist meistens nicht eine vertiefte Auseinandersetzung, sondern ein verkürztes Daumen-hoch. Damit verlagert sich der Code-Review von einem inhaltlichen zu einem zeremoniellen Schritt, und genau in dieser Verlagerung entstehen die Probleme, die später teuer werden.
Die Abhängigkeitsspirale
Eine ambitionierte Schule propagiert, die Beschäftigung mit Code werde überflüssig: Mit genug Skills, Harness-Engineering und einer präzisen Markdown-Spezifikation lasse sich die Arbeit vollständig auf die Spec-Ebene verlagern. Der generierte Code sei eine Implementierungsfrage, die niemand mehr ansehen müsse. Diese Vorstellung wird mit Anlauf gegen eine Wand laufen.
Wer Code nur generiert, ohne ihn zu lesen, hat von Anfang an fremden Code vor sich. Reviewen geht nicht, Fehler suchen geht nicht, beides setzt Verstehen voraus. Mit jeder weiteren Generierung wächst die Codebasis schneller, als sie sich durchdringen lässt. Die Lücke zwischen „vorhanden“ und „verstanden“ öffnet sich in atemberaubender Geschwindigkeit, und mit ihr die Anzahl der Stellen, an denen man später fragen muss, was hier eigentlich passiert.
Die einzige verbliebene Instanz, die diesen Code noch erklären, prüfen oder reparieren kann, ist die KI selbst. Damit ist man ironischerweise auf genau das System angewiesen, das die Lage herbeigeführt hat. Aus einem Werkzeug wird eine Abhängigkeit, aus einer Beschleunigung eine Falle. Wer keine eigene Verstehenskompetenz aufbaut, hat nur noch eine externe und entscheidet über diese externe Kompetenz nicht mehr selbst.
Dieses Muster ist nicht neu, neu ist nur seine Geschwindigkeit. Ein Team besitzt eine unzugängliche Codebasis nicht mehr. Im klassischen Fall geschah die Unzugänglichkeit über Jahre, durch personelle Wechsel und unzureichende Dokumentation. Im KI-gestützten Fall kann das innerhalb weniger Monate geschehen, weil die Generierungsgeschwindigkeit die Aufnahmegeschwindigkeit hoffnungslos übersteigt.
Der typische Auslöser ist nicht spektakulär. Ein Bug taucht in Produktion auf, niemand im Team versteht den betroffenen Code, also befragt man die KI. Die KI liefert eine Erklärung und einen Fix, beides plausibel, beides ungeprüft. Im günstigen Fall stimmt es. Im weniger günstigen baut man neue Schulden auf alte und merkt es erst, wenn der nächste Bug genau in dieser Schicht entsteht. Aus Reparatur wird Übermalung.
Was zunächst wie eine Befreiung wirkt, ist also eine Verlagerung der Last. Statt selbst zu schreiben, formuliert man Prompts. Statt selbst zu verstehen, fragt man die KI. Beides scheint produktiv. Beides erodiert die Souveränität über die eigene Codebasis.
Lesen heißt nicht, Syntax zu parsen
Wenn vom Lesen des Codes die Rede ist, meinen viele zunächst nur das oberflächliche Erfassen: Welcher Funktionsaufruf folgt auf welchen, welche Variable wird wo gesetzt, welche Rückgabewerte gehen wohin. Das ist die syntaktisch-mechanische Ebene. Sie ist notwendig, aber bei Weitem nicht hinreichend.
Auf einer zweiten Ebene fragt das Lesen, was der Code semantisch tut. Welche Zustandsänderung wird ausgelöst, welche Invariante soll erhalten bleiben, welche Fehlerfälle werden abgedeckt, welche stillschweigend ignoriert. Hier beginnt das eigentliche Verstehen, weil hier die Wirkung des Codes zur Sprache kommt und nicht mehr nur seine Form.
Auf einer dritten Ebene fragt das Lesen nach der Intention. Warum wurde diese Lösung gewählt und nicht eine andere, welche Trade-offs wurden bewusst eingegangen, welche Annahmen liegen zugrunde. Diese Ebene ist im Code selten explizit dokumentiert. Sie muss aus Strukturen, Tests, Kommentaren und Commit-Historie rekonstruiert werden, und genau diese Rekonstruktion macht den Unterschied zwischen oberflächlicher und tiefer Vertrautheit mit einem Modul aus.
Auf einer vierten Ebene fragt das Lesen nach der Geschichte. Wie ist dieser Code geworden, was war ein bewusster Schnitt, was ein kompromissbedingter Workaround, welche Stelle ist organisch gewachsen und welche wurde später angeklebt? Wer hier nicht lesen kann, repariert Symptome statt Ursachen und verschiebt die eigentliche Arbeit auf den nächsten Bug. Ein typisches Beispiel ist eine Validierung, die ursprünglich einer bestimmten Geschäftsregel gehorchte, später wegen einer Sonderanforderung gelockert wurde, wieder verschärft, dann wieder gelockert. Wer diese Bewegung nicht in der Historie liest, baut die nächste Lockerung als vermeintlich saubere Lösung ein und tritt in eine Falle, die andere bereits dreimal gesehen haben.
Senior-Niveau heißt, alle vier Ebenen gleichzeitig im Blick zu haben. Wer nur die erste beherrscht, ist Werkzeugbenutzer. Wer alle vier integriert, ist Entwickler im eigentlichen Sinne. Diese Integration entsteht nicht durch das Schreiben von noch mehr Code, sondern durch das Lesen von Code, den andere geschrieben haben.
Eine Disziplin ohne Lehrplan
In jedem Programmierbuch wird das Schreiben geübt. Tutorials sind Schreibtutorials, Hochschulkurse sind Schreibkurse, Bootcamps sind Schreibbootcamps. Wer einsteigt, bekommt zuerst ein Hello-World-Programm, dann immer komplexere eigene Programme. Das Lesen kommt nirgendwo systematisch vor.
Auch in der dualen Ausbildung zur Fachinformatikerin oder zum Fachinformatiker ist das Lesen kein eigenes Lehrziel. Im Studium der Informatik begegnet man Code in der Regel als Aufgabe, nicht als Quelle. Selbst in Fortbildungen erfahrener Entwicklerinnen und Entwickler ist das Lesen kein Thema, das systematisch trainiert wird. Es wird stillschweigend vorausgesetzt, ohne dass es jemals vermittelt würde.
Code-Reviews wären die naheliegende Praxis, in der Lesen geübt würde. In der Realität reduzieren sie sich häufig auf Stilfragen, Konventionsverstöße und kleine Korrekturen. Die tieferen Ebenen der Intention und der Geschichte werden selten berührt. Das liegt nicht an der Praxis selbst, sondern an der fehlenden Schulung darin, was ein gutes Review eigentlich leisten könnte und welche Fragen es zu stellen hätte.
So entsteht ein blinder Fleck. Eine Disziplin, die einen großen Teil des beruflichen Alltags ausmacht, wird in der Ausbildung wie eine selbstverständliche Begleitfähigkeit behandelt. Niemand wundert sich, dass Juniors Schwierigkeiten beim Lesen haben. Niemand zieht den Schluss, dass man es ihnen beibringen müsste. Damit wird ein Defizit normalisiert, das in seiner ökonomischen Wirkung erheblich ist.
Lesen lässt sich üben
Lesen lässt sich systematisch trainieren, sofern man die Bereitschaft mitbringt. Eine erste Übung besteht darin, sich eine Open-Source-Codebasis vorzunehmen, die man nicht selbst geschrieben hat, und sie über mehrere Wochen zu erkunden, ohne etwas zu ändern. Ziel ist nicht, einen Beitrag zu leisten, sondern die Codebasis zu verstehen. Diese Form des absichtslosen Lesens ist ungewohnt und fühlt sich zunächst unproduktiv an, sie ist aber das eigentliche Trainingsfeld.
Eine zweite Übung ist das Nachvollziehen fremder Pull Requests. Man liest die Diskussion mit, versucht die Änderung zu verstehen, bevor man die Begründung kennt, und vergleicht das eigene Verständnis mit dem, was die Beteiligten geschrieben haben. Diese Übung schärft die Intentionsebene des Lesens, weil sie zwingt, die Frage nach dem Warum vor der Antwort zu formulieren.
Eine dritte Übung ist das bewusste Unterscheiden zwischen drei Lesemodi: scannend, wenn man eine Stelle suchen will; verstehend, wenn man eine Funktion in ihrer Wirkung erfassen will; kritisch, wenn man eine Änderung verantworten muss. Wer immer im selben Modus liest, kann keinen davon richtig. Die meisten Entwicklerinnen und Entwickler scannen unbewusst, auch wenn sie eigentlich kritisch lesen müssten. Genau dort entstehen die teuren Fehler.
Mit LLMs kommt eine vierte Übung hinzu, die in den nächsten Jahren an Bedeutung gewinnen wird: das Prüfen generierten Codes. Es genügt nicht, einen Vorschlag der KI durchzulesen und zu nicken. Echtes Prüfen heißt, die generierte Lösung mit der eigenen Vorstellung zu vergleichen, Annahmen zu hinterfragen, Randfälle gegenzuprüfen, alternative Implementierungen zu durchdenken. Genau das, was eigentlich für jeden Pull Request gelten sollte. Bei generiertem Code ist es zwingend, weil hier kein menschlicher Autor existiert, der für seine Entscheidungen einsteht.
Eine fünfte Übung wird oft übersehen: das Wiederlesen des eigenen Codes nach längerer Pause. Sechs Monate genügen, um die ursprüngliche mentale Gesamtsicht weitgehend zu verlieren. Wer dann die eigene Implementierung erneut liest und ehrlich notiert, an welchen Stellen die Intention nicht mehr ohne externe Hilfe rekonstruierbar ist, lernt zwei Dinge gleichzeitig: Was damals besser zu dokumentieren gewesen wäre und wie es sich anfühlt, fremden Code vor sich zu haben. Diese Übung ist ernüchternd und nützlich zugleich.
Lesen ist also keine angeborene Fähigkeit. Es ist eine erlernbare Disziplin. Wer sie systematisch übt, wird auf eine Weise besser, die kein Schreibtraining ersetzen kann. Und wer sie nicht übt, wird sich in den kommenden Jahren in einer Codebasis wiederfinden, die schneller wächst, als sie zu verstehen ist.
Die Dauerwährung der Softwareentwicklung heißt Verstehen
Der Reflex, beim Anblick fremden Codes lieber selbst neu anzusetzen, ist menschlich und alt. Joel Spolsky hat ihn vor über 25 Jahren beschrieben und vor seinen Folgen gewarnt. Was sich seitdem geändert hat, ist die Geschwindigkeit, mit der dieser Reflex Schaden anrichten kann. Mit LLMs ist das Schreiben so billig geworden, dass die Kosten des Nichtlesens nicht mehr in Jahren, sondern in Wochen sichtbar werden.
Wer Code nur erzeugt, ohne ihn zu durchdringen, baut Schulden auf, die irgendwann eine andere Person begleichen muss. Diese Person sitzt vor einem Bildschirm und liest. Sie ist die wertvollste Person im Team, weil sie die einzige ist, die noch entscheiden kann, was mit dieser Codebasis weiter geschieht. Wer das systematisch trainiert, baut sich einen Vorsprung auf, der auf Promptebene allein nicht zu erzeugen ist. Das Tippen ist die Einstiegsdisziplin. Das Lesen ist die, die bleibt.
(rme)