KI zwingt uns dazu, guten Code zu schreiben
(bits.logic.inc)- Da KI-Agenten ins Zentrum der Code-Erstellung rücken, werden bisher „optionale“ Best Practices wie Tests, Dokumentation und statische Typisierung nun zu Pflichtbestandteilen
- 100 % Code Coverage wird eingefordert, damit jede Codezeile tatsächlich geprüft und durch ausführbare Beispiele untermauert wird
- Verzeichnisstruktur und Dateibenennung werden klar gestaltet, damit LLMs sich leichter durch die Codebasis bewegen können; empfohlen werden klein granulare Dateien
- Schnelle, ephemere und nebenläufig nutzbare Entwicklungsumgebungen werden aufgebaut, damit mehrere Agenten parallel arbeiten können
- Statische Typsysteme und automatisierte Quality-Management-Tools sind entscheidend, um ein Code-Ökosystem zu erhalten, dem KI vertrauen kann
KI und die Notwendigkeit von „gutem Code“
- Lange Zeit galten Tests, Dokumentation, kleine Module und statische Typisierung als Maßstab für guten Code, wurden in der Praxis aber oft ausgelassen
- Da KI-Agenten ihren Code nicht selbst zuverlässig aufräumen können, sind diese Best Practices nun zwingend notwendig
- Damit Agenten nicht in die falsche Richtung laufen, sind klare Guardrails und ihre konsequente Durchsetzung unverzichtbar
- Mit robusten Guardrails konvergieren LLMs nur auf den richtigen Pfad; in unvollständigen Umgebungen verstärken sie dagegen Probleme
100 % Code Coverage
- Teams machen 100 % Code Coverage zur Pflicht, nicht nur zur Bug-Vermeidung, sondern um das Verhalten jedes von Agenten geschriebenen Codes zu verifizieren
- Bei 95 % oder 99,99 % Coverage bleibt unklar, woher ungetesteter Code stammt; bei 100 % lassen sich alle nicht verifizierten Zeilen eindeutig identifizieren
- Coverage-Reports dienen als To-do-Liste für Tests, und ein LLM muss bei Code-Änderungen zwingend ausführbare Beispiele liefern
- Dieser Ansatz hat Nebeneffekte wie das Entfernen unerreichbaren Codes, das Explizitmachen von Edge Cases und effizientere Code Reviews
Namespaces und Dateistruktur
- Agenten erkunden die Codebasis über das Dateisystem, daher fungieren Verzeichnisstruktur und Dateinamen als wichtige Schnittstelle
- Ein klarer Pfad wie ./billing/invoices/compute.ts vermittelt deutlich mehr Information als ./utils/helpers.ts
- Bevorzugt werden sollten kleine, klar definierte Dateien, damit LLMs den gesamten Dateiinhalt in den Kontext laden können und Performance-Einbußen vermieden werden
- Diese Strukturierung führt zu höherer Suchgeschwindigkeit und Genauigkeit der Agenten
Schnelle, ephemere und nebenläufige Entwicklungsumgebungen
- Statt einer einzelnen klassischen Entwicklungsumgebung verlagert sich agentenbasierte Entwicklung hin zu einer Form, in der mehrere Prozesse parallel verwaltet werden
- Fast: Tests und Verifikationsschritte müssen schnell laufen; das Team optimiert darauf, mehr als 10.000 Assertions in unter einer Minute abzuschließen
- Geschwindigkeit wird durch starke Parallelisierung, harte Isolation und eine Caching-Schicht für Third-Party-Aufrufe erreicht
- Ephemeral: Mit dem Befehl
new-feature <name>wird innerhalb von 1 bis 2 Sekunden eine neue Umgebung erzeugt, automatisch konfiguriert und der Agent gestartet- Wenn manuelle Einrichtung nötig ist, sinkt die Nutzung drastisch; vollständige Automatisierung ist daher zentral
- Concurrent: Damit mehrere Entwicklungsumgebungen gleichzeitig laufen können, sind Konfliktvermeidung bei Ports, DBs, Caches usw. erforderlich
- Die Isolation erfolgt per Docker oder über umgebungsvariablenbasierte Konfiguration
End-to-End-Typsysteme und automatisiertes Quality Management
- Möglichst viele Best Practices werden automatisiert, um die Freiheitsgrade von LLMs zu verringern und eine konsistente Qualität zu sichern
- Automatische Linter und Formatter werden strikt konfiguriert, sodass bei jedem abgeschlossenen Arbeitsschritt des LLM automatisch Korrekturen angewendet werden
- Empfohlen wird die Nutzung statisch typisierter Sprachen, insbesondere starker Typsysteme rund um TypeScript
- Mit
UserId,WorkspaceSlugundSignedWebhookPayloadsorgen aussagekräftige Typnamen dafür, dass die Codeabsicht klar ausgedrückt wird
- Mit
- Über OpenAPI wird die Typkonsistenz zwischen Frontend und Backend erhalten
- Das Typsystem und Trigger von Postgres sichern die Datenintegrität, während Kysely einen typsicheren Client erzeugt
- Auch alle Third-Party-Clients sollten präzise Typdefinitionen haben oder entsprechend gekapselt eingesetzt werden
Fazit: Neudefinition von Codequalität im KI-Zeitalter
- Agenten sind nicht ermüdende und hervorragende Coder, aber ihre Leistung hängt von der Qualität ihrer Umgebung ab
- „Guter Code“ ist keine Option mehr, sondern Voraussetzung dafür, dass KI korrekt arbeiten kann
- Das anfängliche Setup mag wie eine Belastung wirken, ist aber eine längst überfällige notwendige Investition
- Mit Unterstützung der Entwicklungsleitung sollte das Ziel sein, eine KI-freundliche Codebasis aufzubauen
1 Kommentare
Hacker-News-Kommentare
Die Falle beim Erreichen von 100 % Coverage ist, dass man in eine selbstwidersprüchliche Verifikation geraten kann, wenn Code und Tests vom selben Agenten geschrieben werden
Wenn der Agent eine fehlerhafte Logik erstellt und auch die Tests, die sie prüfen sollen, falsch schreibt, bestehen die Tests, obwohl der Code in Wirklichkeit fehlerhaft ist
Solche Coverage ist nur dann sinnvoll, wenn Tests vor dem Code geschrieben werden oder wenn Menschen sie streng verifizieren
Andernfalls erzeugt sie nur eine Illusion von Zuverlässigkeit
Entscheidend ist, dass mehrere Menschen mit unterschiedlichen Denkweisen die blinden Flecken der jeweils anderen prüfen
Auch mehrere AI-Modelle sollte man letztlich als einen einzigen „Geist“ betrachten
Gut ist z. B. menschlicher Code mit AI-Tests, AI-Code mit menschlichen Tests oder gegenseitige Code-Reviews
Allerdings führt auch unter Menschen Machtgefälle manchmal dazu, dass nur die Meinung einer Person berücksichtigt wird, und AI verhindert das nicht
Man sollte absichtlich Bugs einbauen und prüfen, ob sie fehlschlagen
Das ist kein reines AI-Problem, bei Menschen gilt dasselbe
Trotzdem ist es positiv, dass dank AI viele Entwickler solide Engineering-Prinzipien lernen
SQLite oder Flugsoftware zielen auf so ein Niveau ab
Das ist allerdings noch keine akademisch validierte Hypothese
Deshalb muss man mit Integrationstests oder automatisierten UI-Tests echte Benutzerszenarien prüfen
Daten aus der Produktionsumgebung oder Tests in einer Shadow-Umgebung helfen ebenfalls
Vor LLMs war das Setup mühsam, aber heute ist der ROI besser
Wie Uncle Bob betont hat, ist es wichtig, in die Strukturierung von Tests zu investieren
LLMs schreiben zwar repetitive Tests, setzen auf Anfrage aber auch das DRY-Prinzip oder Factory-Pattern gut um
Das ist eine Methode, die ich seit gestern ausprobiere: Zuerst die Spezifikation in TLA+/PlusCal schreiben und dann Codex diese Spezifikation exakt implementieren lassen
Ich weise es an, ohne Kreativität nur der Spezifikation zu folgen
Der resultierende Code ist hässlich, aber korrekt, und deutlich schneller als selbst zu übersetzen
Wenn die Optimierung fehlt oder es zu chaotisch wird, korrigiere ich manche Teile
Ich experimentiere besonders mit lock-freien Datenstrukturen, aber Codex will immer noch Locks verwenden, sodass ich das manuell korrigieren muss
Am Ende konzentriere ich mich auf mathematische Logik und die AI übernimmt die Implementierungsdetails
Das ist genau der ideale Ablauf von „erst Spezifikation, dann Code“
Ich kann mich mit Martin Kleppmanns Beitrag identifizieren
Bei aktuellen Modellen funktioniert das tatsächlich gut, und auch die Kosteneffizienz hat sich um das 10- bis 100-Fache verbessert
Das klingt nach Halluzination oder einem Sales Pitch
Wenn reale Produktionsbugs und Wartungsaufwand keinen guten Code erzwingen, kann AI das auch nicht
AI auf dem heutigen Stand macht Code eher noch schlechter
Wenn es nicht einmal Einigkeit über die Länge von Methoden gibt, existiert kein universeller Qualitätsmaßstab
Auch Metriken wie Test-Coverage lassen sich leicht manipulieren und können bei falscher Anwendung sogar schaden
Besonders wenn AI die Tests schreibt, kann sie falsches Selbstvertrauen erzeugen
Ich denke, Softwareentwicklung könnte das einzige wirklich praktische Anwendungsfeld von LLMs sein
Im Vergleich zu anderen Bereichen kann man Feedback-Loops sehr schnell aufbauen
Man plant mit dem LLM, sieht einige Stunden später das Scheitern und das LLM sagt dann: „Deshalb sollte man das nicht so machen“
Das ist wie ein Haus nach US-Elektrostandard zu bauen und dann beim Einbau einer kanadischen Spülmaschine das Problem zu entdecken
Software war relativ sicher, daher war anonyme Entwicklung möglich, aber inzwischen entsteht eine Kultur der verantwortlichen Signatur
Vielleicht werden künftig nur noch die Menschen hoch bezahlt, die High-Risk- und innovative Codebasis schreiben
AI produziert ständig abwegigen Code, wir debuggen ihn, dann kommt der nächste Unsinn heraus, und man landet in einer Endlosschleife
Man muss nur sicherstellen, dass die Stromspezifikation passt
Trotzdem finde ich es beruhigend, dass Unit-Tests noch den Kontakt zur Realität prüfen
Ich nutze LLMs, um RLC-Schaltungen und Inerter zu lernen
Viele sind beeindruckt davon, wie schnell LLMs Code erzeugen, aber Geschwindigkeit oder Menge sind nicht der Qualitätsengpass
Die echte Revolution kommt erst, wenn AI präziseren Code als Menschen schreibt
Der eigentliche Wert entsteht daraus, zu wissen, wie der Code funktioniert
In Meetings voller Engineers, die nur Vermutungen äußern, ist der wertvollste Moment der, in dem jemand den echten Code öffnet und zeigt
„Guter Code“ ist vielleicht einfach Code, der für das begrenzte Arbeitsgedächtnis von Menschen optimiert ist
Modelle können den gesamten Kontext auf einmal sehen und haben diese Einschränkung nicht
Wenn das Kontextfenster 100-mal größer wird, könnte diese Diskussion weniger wichtig werden
Ich mache mir Sorgen, dass sich bei der Forderung nach 100 % Coverage für LLMs falsche Annahmen verfestigen
Aber wenn Menschen den Review machen, kann man wohl immer noch sagen: „Das ist falsch, also löschen wir den Test und schreiben ihn neu“, oder?
Das LLM hilft im Stil eines Interviews sogar beim gemeinsamen Schreiben des PRD, um Umfang und Erwartungen klar zu machen
„Best Practices“ hängen vom technischen Umfeld ab
Jetzt, da das Schreiben von Code einfacher geworden ist, könnte 100 % Coverage für LLMs nützlicher sein
Tests geben LLMs ein klares Ziel und machen die nachfolgende Interaktion sicherer
Jeder Test verweist auf frühere Bug-Tickets und stellt sicher, dass ein Fix erhalten bleibt
Gibt man einem LLM Szenarien, erzeugt es meistens Code ähnlicher Qualität
Anders als kreative Kunst ist Software eine für Automatisierung besonders geeignete Industrie
Nach der Überschrift dachte ich, der Beitrag würde sagen: Damit AI effektiv ist, müssen wir guten Code schreiben
Tatsächlich macht Claude bei unklaren Variablennamen oder unlogischem Code oft Fehler
Wenn eine Variable „iteration_count“ heißt, aber eine Summe enthält, lässt sich AI täuschen
Am Ende hilft sauberer Code sowohl AI als auch Menschen
Weil AI interne Dokumente als Lernressource nutzt, gelten aktuelle Dokumente inzwischen als unverzichtbar
Früher hatte das eine geringe Priorität, heute wirkt es sich direkt auf die Modellqualität aus
Mit der Zeit wird sich aber vermutlich auch das verbessern
Dann steigt die Wahrscheinlichkeit, dass ein LLM es auf Anhieb korrekt implementiert
Dieser Beitrag zeigt das oberflächliche Engineering-Verständnis von Prompt-Firmen
100 % Coverage verifiziert nicht alle Eingabekombinationen
Es bedeutet nur, dass mit einigen Beispielen alle Zeilen einmal ausgeführt wurden
Am Ende braucht man formale Beweise, aber die sind astronomisch teuer und für LLMs nutzlos
Eher könnte das Schaffen einer reaktiven Entwicklungsumgebung mit Tests ein neues goldenes Zeitalter eröffnen
Wenn es Probleme mit der Coverage gibt, kann man später ausbauen
Von Anfang an sollte man die Tests aber so gründlich wie möglich aufsetzen
Es gibt bereits viele Versuche, sie zusammen mit Proof Assistants einzusetzen
Selbst wenn die Spezifikation kleine Fehler enthält, liefern sie meistens brauchbare Ergebnisse