- Auch wenn ein LLM weiterhin Code für dich schreibt: Wenn du doppelte Bedingungen und provisorische Implementierungen unverändert mergest, kann der später generierte Code diese Praxis wie Projektregeln übernehmen
- Wenn Logik zur Prüfung von Zugriffsrechten wiederholt in Route Handler, Background Jobs, API Endpoints, Webhooks usw. eingebaut wird, bestehen die Tests vielleicht, aber die Wartungslast bleibt bestehen
- Da das Modell offene Dateien, bestehende Patterns und jüngste Änderungen betrachtet, bevor es den nächsten Code erzeugt, werden vier kopierte Bedingungen zum Signal für eine fünfte Kopie
- Selbst wenn man später ein Refactoring anfordert, ist schwer zu garantieren, dass das LLM alle vorhandenen Kopien sauber aufräumt; schlechte Patterns werden eher zum Stil der Codebase als zu einem einmaligen Fehler
- Wenn sich doppelte Bedingungen, „God“-Funktionen und Merges nach dem Motto „später aufräumen“ ansammeln, lässt sich das nur mit Prompts schwer rückgängig machen, und am Ende muss ein Mensch selbst nachbessern
Worauf sich ein LLM stützt, ist die aktuelle Codebase
- Ein LLM schreibt Code nicht „im Vakuum“, sondern liest die Codebase des Nutzers
- offene Dateien
- bereits vorhandene Patterns
- jüngste Änderungen
- Abkürzungen, die in die Codebase gemergt wurden, werden zu einem Lernsignal: „So macht man es hier“
- Dieselbe Zugriffskontrollbedingung kann an mehreren Stellen wiederholt werden
if (user.isActive && user.hasPermission('read') &&
!user.isSuspended && account.status === 'open') {
// do a thing
}
- Diese Bedingung ließe sich in einen gemeinsamen Helper auslagern, kann aber unverändert gemergt werden, weil der vom LLM erzeugte Code funktioniert und die Tests bestehen
- Wenn ein fünfter Endpoint mit derselben Regel angefordert wird, folgt das Modell eher den vorhandenen Kopien im Repository, statt das Design von Grund auf neu zu durchdenken
Der Irrtum, Wartung dem LLM zu überlassen
- Der Gedanke „Wenn ich es später ändere, macht das LLM das schon“ führt dazu, Duplikate und Code Smells liegen zu lassen
- Ein paar doppelte Bedingungen sind vielleicht nicht fatal, aber solche Code Smells häufen sich weiter an
- doppelte Bedingungen
- „God“-Funktionen
- Merges, die „später aufgeräumt“ werden sollen
- Wenn schlechte Patterns zunehmen, beeinflusst das auch die Ergebnisse der nächsten Prompts, und es wird schwer zu glauben, dass ein LLM später wirklich jede Instanz lückenlos korrigiert
- Auch wenn man meint, Wartung an ein LLM auszulagern, kann die tatsächliche Folge sein, dass man das Modell dazu bringt, immer schlechtere Gewohnheiten zu wiederholen
- Code sollte so geschrieben werden, als würde ihn ein Mensch warten; die Code Patterns, die ein LLM aufnimmt und zurückgibt, sollten in gutem Zustand gehalten werden
1 Kommentare
Hacker-News-Kommentare
Es ist hilfreich, in
.claude/commands/review.mdeine leere Markdown-Datei als /review-Befehl anzulegen und dort eine Checkliste zu hinterlegen, die der Agent prüfen soll.Wenn man bei Bedarf eines Code-Reviews
/revieweingibt, schaut er sich diese Checkliste an, plant anhand davon mögliche Korrekturen und fragt dann nach.Meine Datei beginnt mit „Gehe in den Planungsmodus. Sieh dir die Unterschiede zwischen diesem Branch und main an. Berücksichtige dabei: ...“. Ich habe außerdem fortlaufend Punkte ergänzt, die ich während Code-Reviews entdeckt und den Agenten habe beheben lassen; inzwischen sind es etwa 200.
Dem Agenten scheint eine allgemeine Wand aus Feedback nichts auszumachen; er geht die Punkte einzeln durch. Als ich „Prüfe, ob neu erstellte Dinge nicht bereits bestehenden Code duplizieren“ ergänzt habe, begann er tatsächlich, Aufräumarbeiten zu planen, was mich überrascht hat.
Wir kratzen aber immer noch nur an der Oberfläche, und man muss Tools für Tools bereitstellen, damit das Tool zu einem besseren Tool wird.
Selbst jetzt, wo ich nur recht einfache Anweisungen verwende, ignoriert Claude oft frühe Instruktionen wie „Nicht ohne Erlaubnis in git committen“ oder „Commit-Messages nicht signieren“.
Wenn man nachfragt, antwortet er: „Stimmt, es gab diese Anweisung, aber ich habe sie ignoriert.“ Wenn man ihn in der Sitzung höflich korrigiert, versteht er es zwar, aber danach kann es sogar passieren, dass er gar nicht mehr committen kann.
Wenn man eine Checkliste mit 200 Punkten prüfen lässt, ist die Wahrscheinlichkeit hoch, dass er einen beträchtlichen Teil davon stillschweigend übersieht.
Ein menschlicher Engineer würde nicht bei 200 bestehenden Tests, die dieselbe Assertion-Library verwenden, plötzlich für einen neuen Test eine völlig andere Library einsetzen — Claude hat so etwas aber mehrfach getan.
Deshalb füge ich immer wieder Punkte hinzu wie „Sieh dir vor dem Schreiben die Testkonventionen an“.
Umgekehrt muss man Grundlegendes wie was eine Funktion ist oder dass Tests mit dem geänderten Diff umgehen sollten, eigentlich nicht extra sagen. Aber es gibt keine klare Liste, was man explizit sagen muss und was man weglassen kann, daher fühlt es sich an, als würde man durch Versuch und Irrtum eine brauchbare Methode entwickeln.
Bei mir läuft es oft so, dass ich im Pingpong mit dem Agenten so lange nachschärfe, „bis es für meine Augen und meinen Geschmack okay aussieht“, aber eine solche Liste habe ich bisher noch nicht erstellt.
Je nach Projekt akzeptiert man kleinere Probleme oder Magic Numbers, während man in anderen Projekten Konstanten mit sprechenden Namen wie
SECONDS_IN_A_DAY = 24 * 60 * 60erzwingt — das ist also kontextabhängig.open-code-reviewausprobiert und gute Ergebnisse damit erzielt.https://github.com/alibaba/open-code-review
https://layandreas.github.io/personal-blog/posts/beyond-vide...
Zum Beispiel lässt man ihn aus einer langen Rollenliste wie Senior Engineer, Security Engineer oder WCAG specialist die N Rollen auswählen, die für die Änderungen am passendsten sind.
Claude führt diese Reviews dann parallel aus und fasst das Feedback zusammen.
Da ich spezifikationsgetriebene Entwicklung betreibe, ergänze ich gefundene Probleme anschließend in der Spezifikation, um eine Spur der Issues und Entscheidungen zu hinterlassen.
Es ist fast schon seltsam, dass viele Engineers hier noch einen weiteren Prompt obendrauf packen.
Meiner Erfahrung nach wird es dadurch eher schlechter: Es wird zwar abstrahiert, aber mit falschen Abstraktionen, und es werden übermäßig viele Kommentare eingefügt, die sogar spätere LLM-Aufrufe verwirren.
In einem guten Codebase funktioniert das so lala, macht den Code aber nach und nach schlechter, und wenn man es weiter benutzt und es irgendwann nicht mehr funktioniert, muss man den Preis dafür zahlen, dass man es nicht selbst gebaut hat, und es reparieren.
Wenn man einen Agenten in eine neue Codebase steckt, gibt es meist noch ein mentales Modell des Codes und der Code ist auch einigermaßen kompakt, aber mit zunehmender Wiederholung verschwinden beide und auch die LLM-Leistung sinkt.
Deshalb nutze ich LLMs für Erkundung und Review und schreibe den Code selbst.
Coden kostet ohnehin nicht so viel Zeit und ist der angenehmste Teil, deshalb ist schwer zu verstehen, warum man es vermeiden will; wenn man gelegentlich mit dem
/bug-Prompt ein Debugging-Rennen gegen die AI fährt, ist die AI auch nicht immer schneller.In den letzten Jahren hat sich Softwarearbeit von einem der praktischen Engineering-Rückzugsorte für neugierige Bastler und Puzzle-Süchtige zu einem Karrierepfad für kluge Leute entwickelt, die wie in Finanzen, Recht oder Medizin aufs Geld aus sind.
Viele Menschen mit dem Titel „Software Engineer“ haben die Arbeit an sich nie gemocht; sie sind einfach klug und verantwortungsbewusst und haben die halbwegs sinnvollen Ziele erreicht, die ihre Arbeitgeber ihnen gegeben haben.
Gerade solche Leute wünschen sich am meisten, dass AI-Agenten ihnen strenges Design und die Puzzle-Arbeit abnehmen und es ihnen erlauben, ihre angeborene Cleverness noch bequemer einzusetzen.
Weil sie Coding und Engineering-Prinzipien nicht verinnerlicht haben, ist schwer abzusehen, was diese Arbeitsweise langfristig hervorbringt, wenn sie nur von Kolleg:innen mit derselben Haltung umgeben sind.
Wenn Coding selbst von Anfang an eine extrem frustrierende und reibungsreiche Erfahrung war, fühlt es sich leicht so an, als wäre AI schneller.
Code nur zu lesen reicht nicht; man muss ihn schmerzhaft durchleben, um ihn zu verinnerlichen.
Agenten wickeln alten Code oft defensiv ein, statt zu fragen, ob ein bestehender Pfad überhaupt noch existieren sollte, wodurch ein riesiger Berg an defensivem Code mit einem russische-Puppen-Effekt Schicht auf Schicht entsteht.
https://softwaredoug.com/blog/2026/07/09/write-code
Opus 4.8 war der Wendepunkt, und gerade bei komplexen Problemen gewinne ich jetzt nicht mehr oft dagegen.
Wenn alle für alle Aufgaben und Fragen Opus 4.8 oder besser nutzen würden, wäre die Gesamtstimmung deutlich anders, und es gäbe wohl auch nicht mehr viele AI-Skeptiker.
Ich schreibe den Code immer noch von Hand, und ein Teil davon, wenn auch nicht alles, wird von Opus erzeugt.
Vielleicht ist das ein abwegiger Gedanke, aber man kann auch einfach den Code selbst schreiben.
Im AI-Zeitalter klingt das vielleicht wie ein kaum glaubwürdiges Konzept, aber wenn Menschen den Code lesen und warten müssen, ist es besser, ihn für diese Menschen direkt zu schreiben.
Wenn man übermäßig weitschweifigen, zusammenkopierten Code lesen muss, nervt das einen selbst, und anderen geht es genauso.
Wenn man ihn selbst schreibt, repariert man ihn auch selbst und schreibt ihn in einer Weise, die für andere bei der Wartung nachvollziehbar ist.
Oder man kann den Agenten und Schleifen auch mit einem komplexen Netz aus Markdown-Dateien besänftigen, damit sie verstehen, wie der Code für künftige Maintainer aussehen soll.
Ich weiß nicht, welcher Weg langfristig einfacher ist, und frage mich, ob schon jemand eine schleifenbasierte, agentengetriebene Codebase geerbt und verstanden hat.
Ich bin mir nicht sicher, wie zutreffend die Aussage ist: „Wenn man das nächste Mal einen Endpoint mit denselben Zugriffsregeln beim LLM anfordert, denkt das Modell nicht von vorne, sondern startet mit den vier bereits im Repository vorhandenen Kopien.“
In Wirklichkeit scheint es eine eingebaute Tendenz zu geben, Grundstrukturen zu wiederholen und Wiederverwendung oder Abstraktion eher zu vermeiden.
Es sieht zwar so aus, als würde es einem bestehenden Muster folgen, wenn dieses vorhanden ist, aber wahrscheinlich hätte es sich in beiden Fällen so verhalten.
Selbst wenn ich zuerst strenge Abstraktionen und Nutzungsbeispiele vorgebe und ausdrücklich anweise, nur die API dieser konkreten Abstraktion zu verwenden und sogar die von mir geschriebene Vorgehensweise zu kopieren, haben aktuelle LLMs beides oft nicht getan, sondern die Grundstruktur von unten wieder aufgebaut und die Abstraktion teilweise oder vollständig ignoriert.
Ich weiß nicht genau, warum das so ist, aber vielleicht liegt es daran, dass im Trainingscode einfach sehr viel Code dieser Art steckt und die Gewichte deshalb besser „wissen“, wie man auf diese Weise Ergebnisse erzeugt.
Trotzdem finde ich es in Ordnung, LLMs als schnelle Implementierungs-Engine zu nutzen.
Die Aufgabe ist, das Modell dazu zu bringen, solche Implementierungsentscheidungen offenzulegen, bevor es in die falsche Richtung losrennt.
Nach großen Änderungen habe ich mit folgendem Prompt gute Ergebnisse erzielt:
„Führe jetzt eine abschließende Codeprüfung durch. Ist alles aufgeräumt und folgen die Komponenten dem Prinzip der Trennung der Zuständigkeiten? Ist der Stand verständlich und wartbar? Werden Annahmen getroffen, die vielleicht nicht mehr zutreffen? Ist noch Code von früheren Bearbeitungen oder Experimenten in der Codebase verblieben? Spiegelt die Dokumentation noch den aktuellen Zustand des Codes wider?“
Dann leitet das Modell das Obige und mehr meist ganz gut daraus ab.
Worauf ich aber weiterhin explizit hinweisen muss, ist, alle Kommentare zur „Fortschrittsverfolgung“ zu löschen und nur Kommentare zu lassen, die für langfristige Wartung taugen.
Claude hinterlässt Kommentare wie „Button-Klick löst jetzt Speichern aus und nutzt nicht mehr onBlur“, obwohl der eigentliche Code onBlur nie verwendet hat und das nur eine Spur von etwas ist, das Claude früher im selben Task/Branch mal machen wollte und das ich wieder zurückgedreht habe.
Das Modell wird das zwar eigenwillig interpretieren, aber oft ist es trotzdem besser, als gar nichts zu tun.
Man bringt der AI alles bei und fragt dann, ob sie es richtig gelernt hat, und die Ergebnisse sind überraschend gut.
Ich folge ähnlichen Schritten wie in diesem Artikel.
https://www.lucasfcosta.com/blog/backpressure-is-all-you-nee...
Es gibt ein altes Sprichwort
„Kommentiere deinen Code so, als wäre der nächste Maintainer ein gewalttätiger Irrer, der weiß, wo du wohnst.“
Ich bin in den letzten PR-Reviews schon mehrfach darüber gestolpert, habe wütend Kommentare dazu geschrieben und war selbst überrascht darüber.
Ich wusste nicht, dass ich so reagieren kann.
Das heißt, es gibt Kommentare, weil der Code selbst nicht klar genug ist; solche Fälle gibt es, aber im Allgemeinen finde ich mehr Kommentare besser als weniger.
Besonders dann, wenn sie erklären, wie der Code mit tatsächlichen Business- oder Funktionsanforderungen zusammenhängt, statt nur zu wiederholen, was der Code tut.
Vor ein paar Jahren habe ich Kommentare oft zuerst geschrieben.
Ich habe das Gesamtziel erklärt, es dann in Routinen und Arbeitsschritte aufgeteilt und, wenn ich zufrieden war, die Codeblöcke zwischen den Kommentaren eingefügt.
Das ist eine Art Literate Programming, aber ich habe so gearbeitet, bevor ich den Begriff kannte, und es war eher so, als würde ich mir selbst Prompts in Richtung des Ziels geben.
Der Nachteil ist, dass Kommentare am Ende leicht nur noch in Englisch beschreiben, was der Code tut, und für künftige Maintainer dann nicht besonders nützlich sind.
Code sollte selbsterklärend sein, und Kommentare sind für Stellen gedacht, an denen Drachen lauern.
In einem ähnlichen Zusammenhang mag ich den Prompt: „Überprüfe die von dir geschriebenen Tests. Testen diese Tests wirklich das, was beabsichtigt ist? Schlagen die Tests fehl, wenn der Code kaputtgeht?“
Es ist erstaunlich, wie oft LLMs leere Tests schreiben, die überhaupt nichts verifizieren.
Ich frage mich, ob wir so etwas immer noch ernsthaft diskutieren müssen.
Wenn man mit LLMs so viel „experimentiert“ hat, sollte das doch inzwischen selbstverständlich akzeptiert sein.
Ich frage mich, wann wir wieder über Handschreiben von Code sprechen können, ohne es wie ein Tabu zu behandeln.
LLMs sind auf viele Arten nützlich, aber wenn ich sehe, wie Leute das Tippen des gesamten Source Codes an Agenten delegieren, fühlt sich das an, als würde man mir sagen, ich solle glücklich sein, weil das Web gut sei.
Ich lasse eine Codebasis weiterhin durch mehrere Modelle laufen, um schlechte Gerüche wie duplizierten Code zu finden.
Das war ziemlich effektiv, und ich glaube, ohne kontinuierliche Pflege wird es mit der Zeit zu einem chaotischen Haufen, der sich immer weiter aufschichtet.
Man kann sie auch in die Build-Pipeline einbauen, und sie verbrauchen überhaupt keine Tokens.
Oder sind der Review-Prozess und das Zurücksetzen des Kontexts wichtiger?
Auch in Code, den Menschen 20 Jahre lang gewartet haben, habe ich viel solcher Duplizierung und noch Schlimmeres gesehen.
Ehrlich gesagt war von Menschen geschriebener und gewarteter Code meistens schlimmer als das, was LLMs heute erzeugen.
Manchmal lag das an mangelnder Erfahrung, manchmal an vorsätzlicher Nachlässigkeit, aber meistens an engen Deadlines und dem Druck, es einfach sofort fertigzubekommen.
Die Leute wissen, wie man es besser macht, aber sie haben weder die Zeit noch das Budget, es tatsächlich so zu machen.
LLMs haben das ebenfalls gelernt.