Code ist billiger geworden
(htmx.org)- Durch die Verbreitung von AI-Coding-Tools sind die Kosten für das Schreiben von Code stark gesunken, doch in der Praxis sind die Kosten, den erzeugten Code zu verstehen, gestiegen
- LLMs sind nicht deterministisch, bewahren den Quelltext nicht auf und ihr Ausgabebereich erstreckt sich auf allgemeine Software; daher können sie nicht mit Compiler-Ausgaben gleichgesetzt werden
- LLMs erzeugen Code weit schneller, als Menschen ihn verstehen können; empfohlen wird daher ein inkrementeller Einsatz, um groß angelegte Änderungen zu vermeiden, die niemand versteht
- Das zentrale Risiko, wenn Code billig wird, ist Komplexität (complexity), die mit der Systemgröße mindestens geometrisch zunimmt, während LLMs produktive Coder ohne Angst vor Komplexität sind
- Als Lösung wird der subtraktive Engineer (subtractive engineer) vorgestellt, der eher entfernt und vereinfacht, statt Code hinzuzufügen, und so die Kunst des Computerprogrammierens bewahrt
Das Zeitalter des billigen Codes
- Im vergangenen Jahr hat AI in sehr kurzer Zeit große Mengen Code in recht guter Qualität erzeugt, wodurch die Kosten der Code-Erzeugung stark gesunken sind
- Gegen die Behauptung „Coding war von Anfang an nicht das Problem“ wird eingewandt, dass Coding sehr wohl Teil des Problems war und dieser Teil durch AI-Coding-Tools stark reduziert wurde
- Es wird die Frage aufgeworfen, was der Bedeutungsverlust des reinen Codings für Entwickler bedeutet, die früher stolz auf ihre Coding-Fähigkeiten waren
Steigende Verständniskosten (Understanding is Expensive(er))
- Wenn Code nicht mehr mühsam aus der Hand eines Programmierers entsteht, sondern in Massen erzeugt wird, dann existiert das Verständnis dieses Codes zunächst nicht
- Falls Verständnis nötig ist, muss es nach dem Schreiben des Codes durch Lesen des Codes erarbeitet werden
- Allgemein gilt das Lesen von fremdem Code als schwieriger als das Schreiben des eigenen
- Die AI-freundliche Sicht „Compiler-Ausgaben versteht man doch auch nicht“ wird als category error bezeichnet
- Compiler sind deterministisch, LLMs hingegen per Design nicht deterministisch
- Compiler-Workflows bewahren den ursprünglichen Quellcode, LLM-Workflows tun das meist nicht
- Compiler-Ausgaben sind auf die enge Domäne von Maschinencode beschränkt, LLM-Ausgaben nicht auf allgemeine Software begrenzt
- In den meisten Fällen, besonders bei mission-critical Software, müssen Entwickler auch LLM-erzeugten Code auf der Basisebene verstehen
- LLMs können Code in einem Tempo produzieren, mit dem niemand mithalten kann; dadurch entsteht die Gefahr, dass die Erzeugungsgeschwindigkeit das Verständnis überholt
- Daher wird ein inkrementeller Einsatz empfohlen, statt riesige Änderungslisten auf einmal erzeugen zu lassen
- Für mechanisches Refactoring kann das geeignet sein, beim Einführen neuer Semantik in eine Codebasis ist es jedoch äußerst riskant
Die Falle des Zauberlehrlings (The Sorcerer's Apprentice Trap)
- Die Szene „The Sorcerer's Apprentice“ aus Disneys Film Fantasia wird als passende Metapher für das AI-Zeitalter herangezogen
- Der Lehrling belegt einen Besen mit Magie, um sich die Mühe des Putzens zu ersparen, doch der Besen arbeitet immer heftiger weiter und die Lage gerät außer Kontrolle
- Am Ende erscheint der Zauberer (Sorcerer) wieder, gewinnt die Kontrolle zurück, tadelt die Torheit des Lehrlings und beseitigt das Chaos
- Die Lehre daraus ist, dass man nicht der Lehrling, sondern der Zauberer sein muss — und der Zauberer muss den Code verstehen
Komplexität bleibt schlecht (Complexity: Still Bad)
- Menschen haben ein schlechtes Gespür für geometrische und exponentielle Kurven und halten Dinge wie den Zinseszins (compound interest) fast für ein Märchen
- Das zentrale Risiko, wenn Code billig wird, ist Komplexität (complexity), die mit der Größe eines Systems mindestens geometrisch, oft sogar exponentiell wächst — so die Behauptung, ohne Beweis
- Schon vor LLMs gab es produktive Coder (prolific coder)
- Ein produktiver Coder ohne Angst vor Komplexität stapelt immer weiter Code auf bestehende Probleme, bis das System in einen nicht mehr reparierbaren Stillstand kollabiert, in dem jede Änderung ebenso viele Bugs erzeugt, wie sie behebt
- LLMs sind zugleich produktive Coder und frei von Angst vor Komplexität, was sie gefährlich macht
Der subtraktive, begrenzende Engineer (The Subtractive, Constraining Engineer)
- Als Antwort auf die Risiken von LLM-generiertem Code wird der subtraktive, begrenzende Engineer (subtractive, constraining engineer) vorgeschlagen
- Dieser Engineer sagt „Nein“, prüft LLM-Ausgaben sorgfältig, schlägt Vereinfachungen vor und hält entschlossen die Kontrolle
- Stolz ist er nicht auf den Code, den er selbst geschrieben hat, sondern auf den Code und die Schichten im System, die er entfernt oder gar nicht erst hineingelassen hat
- Diese Haltung ähnelt eher der eines Bildhauers (sculptor) als der eines Builders
- Die Haltung des Builders bleibt auf der Ebene des Systemdesigns weiterhin sinnvoll
- Gute Engineers müssen in der Lage sein, Komponenten wirksam zu kombinieren und daraus Systeme zu bauen
- Doch auch auf dieser Ebene ist eine subtraktive Denkweise hilfreich, die unnötige Komponenten und Systemgrenzen entfernt, um Deployment und Interaktionen zu vereinfachen
- Der subtraktive Engineer ist ein anderer Typ als die Mehrheit früherer Coder; er passt zu einer Haltung, die lieber „Nein“ sagt und bestehende Systeme verfeinert, statt heroische Rewrites anzustreben
- Dieser Ansatz erkennt die doppelte Realität an, dass Code billig geworden ist und Komplexität weiterhin der Apex Predator bleibt, und bietet einen produktiven Weg, die Kunst des Computerprogrammierens zu bewahren
1 Kommentare
Lobste.rs-Meinungen
Peter Naurs Text Programming as Theory Building von 1985 scheint heute mehrere erneute Lektüren wert zu sein
Die Formulierung „LLMs können keine Angst vor Komplexität haben“ halte ich eher für übertrieben
Das Fehlverhalten selbst gibt es tatsächlich. Wenn man Anweisungen breit formuliert, fügen LLMs Ebenen hinzu, erfinden Abstraktionen und produzieren oft Code, der im Verhältnis zum Problem überdimensioniert ist. Dieses Verhalten ist aber leicht zu beobachten, leicht zu reviewen und überraschend leicht in eine andere Richtung zu lenken. Man muss nur den gewünschten Softwarestil mit Dateien wie
AGENTS/CLAUDE.mdausrichtenMan sollte die kleinste mögliche Änderung verlangen, fragen, was man löschen kann, und fragen, ob die jeweilige Abstraktion ihren Preis wert ist. Man kann auch nach Invarianten, Kopplungspunkten und kognitiver Last fragen und einen zweiten Durchgang verlangen, der Cleverness entfernt; in der Regel folgt das Modell diesem Druck. Wenn man das in den Prompt aufnimmt, kann man es sogar von Anfang an vermeiden
Das Risiko liegt nicht darin, dass ein LLM Komplexität grundsätzlich nie respektieren könnte, sondern darin, dass es bereitwillig die Form von Code erzeugt, die der umgebende Prozess belohnt. Teams, die Menge belohnen, bekommen Menge; Teams, die Einfachheit belohnen, können in der Regel auch das bekommen
Die heutigen Modelle sind besser als die meisten Menschen und werden weiter besser werden. Wenn der Code nicht gut ist, sollte man die AI-Labore mit Feedback unter Druck setzen. Zum Beispiel halte ich die GPT-Reihe für ziemlich schlecht beim Schreiben guter Dokumentation
Deshalb ist „unmöglich“ vielleicht nicht die beste Formulierung, aber ich denke schon, dass es standardmäßig mehrere Biases in Richtung Komplexität gibt
Außerdem gibt es einen Bias zugunsten von Aktion statt Nichtstun. Gute Programmierer nutzen viel mehr Kontext als Manager, die nur eine bestimmte Anfrage stellen, und schlagen auch Alternativen vor. LLMs könnten das theoretisch ebenfalls, aber aktuelle LLMs sind nicht besonders gut darin, die richtigen Fragen zu stellen, selbst wenn es Code zur Fragestellung während der Planung oder zur Erkennung von Wiederholungen gibt. Solche Trainingsdaten sind wahrscheinlich auch nicht häufig
In gewisser Weise ist Prompt Engineering eher ein schrecklicher Hack rund um dieses ganze Problemcluster
Andererseits musste ich ein LLM schon überreden und beruhigen, nachdem ich Antworten bekommen hatte wie: „Das würde ich für ein einmonatiges Projekt nicht empfehlen. Warum diesen Zustand nicht einfach committen und als Demo stehen lassen?“ — obwohl ich wusste, dass beides in weniger als einer Stunde erledigt wäre. Wenn man aber sagt: „Ja, mach ruhig etwas komplett Neues. Wie, findest du selbst heraus“, dann versucht es das immerhin; in diesem Sinne könnte man sagen, dass es keine Angst hat
Scherz beiseite, ich stimme zu. Das deckt sich auch mit meiner Erfahrung
Der Aussage „Die Kosten, Code zu verstehen, sind höher geworden“ stimme ich im Allgemeinen nicht besonders zu
Bei gedankenlos erzeugtem LLM-Code mag das zutreffen, aber mit der richtigen Führung kann ein LLM auch leicht lesbaren Code mit sauber getrennten Schichten erzeugen. Natürlich trifft in diesem Fall der Mensch die meisten Architekturentscheidungen, aber meiner Meinung nach sollte das ohnehin so sein
Umgekehrt habe ich erlebt, dass LLMs sehr gut darin sind, Code zu verstehen, den jemand ohne große Vertrautheit geschrieben hat. Man kann Claude Code eine tiefgehende Analyse eines bestimmten Codes durchführen und ein Markdown-Dokument erstellen lassen, das jeden Teil erklärt und sogar vorschlägt, in welcher Reihenfolge ich mit dem Review oder dem Verständnis beginnen sollte
Das ist wirklich wertvoll
„Menschen verstehen exponentielle Kurven im Allgemeinen nicht gut. Deshalb glauben sie an Märchen wie Zinseszins“ — soll das heißen, Zinseszins sei ein Märchen? Verstehe ich da etwas falsch?