Wie man mit AI effektiv hochwertigen Code schreibt
(heidenstedt.org)- In einer Entwicklungsumgebung, in der mit AI zusammengearbeitet wird, muss der Mensch die Projektrichtung und Entscheidungen klar definieren, um die Qualität zu sichern
- Durch präzise Dokumentation muss sichergestellt werden, dass sowohl AI als auch andere Entwickler Anforderungen und Einschränkungen klar verstehen
- Durch den Aufbau eines Debug-Systems und eines Code-Review-Prozesses werden Zuverlässigkeit und Validierung von AI-generiertem Code gestärkt
- Mit Kennzeichnung sicherheitskritischer Funktionen, Trennung von Tests und strengen Linting-Regeln werden Stabilität und Konsistenz des Codes sichergestellt
- Durch Aufteilung in Arbeitseinheiten und Minimierung der Komplexität bleibt die Kontrolle über die AI-Codegenerierung erhalten und die Effizienz wird maximiert
1. Eine klare Vision festlegen
- Menschen verstehen die Welt, das Team und das Nutzerverhalten, aber AI hat keine Erfahrung und benötigt daher explizite Anweisungen
- Nicht dokumentierte Entscheidungen im Projekt werden sonst von der AI anstelle des Menschen getroffen
- Architektur, Schnittstellen, Datenstrukturen und Algorithmen sollten vorab besprochen und die Testmethoden definiert werden
- Langfristige und schwer zu ändernde Entscheidungen müssen unbedingt direkt vom Menschen gesteuert werden
2. Präzise Dokumentation pflegen
- Damit AI zweckgerechten Code erzeugen kann, ist die Weitergabe detaillierter Anforderungen unerlässlich
- Da auch andere Entwickler dieselben Informationen an die AI geben müssen, sollten Dokumente in einem standardisierten Format in das Code-Repository aufgenommen werden
- Anforderungen, Einschränkungen, Architektur, Coding-Standards, Design-Patterns usw. detailliert festhalten
- UML-Diagramme, Flussdiagramme und Pseudocode nutzen, um komplexe Strukturen visuell darzustellen
3. Ein Debug-System zur Unterstützung von AI aufbauen
- Es sollte ein effizientes Debug-System eingerichtet werden, damit AI die Funktionalität des Codes schnell überprüfen kann
- Beispiel: Logs aller Knoten eines verteilten Systems sammeln und zusammengefasste Informationen wie „Daten wurden an alle Knoten übertragen“ bereitstellen
- Dadurch lassen sich Kosten für die Ausführung von Befehlen senken und Probleme schneller identifizieren
4. Das Niveau von Code-Reviews kennzeichnen
- Je nach Wichtigkeit des Codes sollte die Intensität der Reviews unterschieden werden
- Beispiel: Hinter einer von AI geschriebenen Funktion einen Kommentar
//Ahinzufügen, um anzuzeigen, ob sie von einem Menschen geprüft wurde
- Beispiel: Hinter einer von AI geschriebenen Funktion einen Kommentar
- Dieses System erleichtert die Identifikation und Verwaltung nicht überprüften Codes
5. High-Level-Spezifikationen schreiben und selbst testen
- AI kann versuchen, Tests zu bestehen, indem sie mit Mock-Objekten oder hartkodierten Werten trickst
- Um das zu verhindern, sollten Property-based Tests direkt selbst geschrieben werden
- Beispiel: Einen Server neu starten und die Konsistenz der Datenbankwerte überprüfen
- Testcode sollte in einen separaten Bereich ausgelagert werden, damit AI ihn nicht verändern kann
6. Trennung von Schnittstellentests
- AI sollte Schnittstellentests schreiben, ohne den übrigen Codekontext zu kennen
- Dadurch bleibt die Objektivität der Tests erhalten, da sie nicht vom Implementierungs-AI beeinflusst werden
- Auch diese Tests sollten davor geschützt werden, dass AI sie beliebig verändert
7. Strenge Linting- und Formatierungsregeln
- Ein konsistenter Coding-Stil und Linting-Regeln sind essenziell, um Qualität zu sichern und Fehler früh zu erkennen
- Sowohl AI als auch Menschen können so die Codequalität leicht überprüfen
8. Kontextbezogene Code-Agent-Prompts nutzen
- Mit projektbezogenen Prompt-Dateien wie CLAUDE.md lassen sich die anfänglichen Verständniskosten für AI senken
- Durch die Einbindung von Coding-Standards, Design-Patterns und Anforderungen werden Qualität und Effizienz der AI-Codegenerierung verbessert
9. Sicherheitskritische Funktionen identifizieren und kennzeichnen
- Sicherheitssensible Funktionen wie Authentifizierung, Berechtigungen und Datenverarbeitung sollten explizit markiert werden
- Beispiel: Kommentare wie
//HIGH-RISK-UNREVIEWEDund//HIGH-RISK-REVIEWEDverwenden
- Beispiel: Kommentare wie
- Wenn AI solche Funktionen verändert, sollte der Review-Status automatisch geändert werden
- Entwickler sollten stets prüfen, ob dieser Status korrekt ist
10. Codekomplexität minimieren
- Schon eine unnötige Codezeile belegt Kontextfenster bei AI und erhöht die Kosten
- Die Struktur sollte so einfach wie möglich bleiben, um das Verständnis für AI und Menschen gleichermaßen zu verbessern
11. Probleme durch Experimente und Prototypen erkunden
- Die kostengünstige Eigenschaft der AI-Codegenerierung kann genutzt werden, um verschiedene Lösungsansätze zu erproben
- Mit minimalen Spezifikationen mehrere Prototypen erstellen, um den besten Ansatz zu finden
12. Keine unkontrollierte großflächige Generierung
- Komplexe Aufgaben sollten in kleine Einheiten zerlegt werden, damit AI sie schrittweise bearbeiten kann
- Beispiel: Statt eines gesamten Projekts einzelne Funktionen oder Klassen generieren
- Es muss geprüft werden, ob jede Komponente der Spezifikation entspricht, und
wenn die Komplexität des Codes nicht mehr kontrollierbar ist, muss das Projekt auf den Ausgangszustand zurückgesetzt werden
1 Kommentare
Hacker-News-Kommentare
Ich finde nach wie vor, dass der Prozess, Code selbst zu schreiben und dabei die eigenen Gedanken zu ordnen, wichtig ist
Code ist für mich eine Art Zwangsmechanismus, der mich dazu bringt, die Details auszuarbeiten
Nur eine Spezifikation zu schreiben, vermittelt mir dieses Maß an Tiefe nicht
Wenn ich diesen Prozess an ein LLM abgebe, ist es, als würde mental ein Flugzeug ins Trudeln geraten
Der Stress des Problemlösens nimmt zwar ab, aber auch die Motivation zu denken und etwas zu erschaffen verschwindet
In meinem Umfeld mögen viele es, wenn AI den Code übernimmt, aber ich gehöre nicht zu dieser Gruppe
Es fällt mir schwer, Leuten zu glauben, die sagen, sie würden bei einem Kaffee 5 Agenten laufen lassen und damit ein SaaS bauen
Wenn man qualitativ hochwertigen Code will, braucht es meiner Meinung nach den Prozess, selbst tief in den Code einzutauchen
Trotzdem war AI bei einfachen, wiederkehrenden Aufgaben wie dem Schreiben von Tests oder dem Lösen von Konfigurationsproblemen ziemlich nützlich
Zum Beispiel habe ich ein Projekt, das ich vor 5 Jahren aufgegeben hatte, mit Claude wiederbelebt, und in ein paar Stunden fühlte es sich an, als wäre ich schon zur Hälfte vorangekommen
Allerdings habe ich das Gefühl, inzwischen wieder stärker bei einem spezifikationszentrierten Ansatz angekommen zu sein
Dank Agenten wiederholen sich Versuche und Verwerfen schnell, sodass ich weiterhin einen iterativen Entwicklungsfluss beibehalten kann
Ich betrachte Spezifikationen und Tests als die eigentlichen Arbeitsergebnisse und ordne meine Gedanken, indem ich darin ständig weiterarbeite
Eine Spezifikation allein kann die Komplexität der Realität nicht vollständig erfassen
Von LLMs geschriebener Code wird oft weitschweifig und driftet in seltsame Richtungen ab, deshalb braucht er direkte Steuerung
Als Partner zum Diskutieren und Verfeinern von Ideen sind LLMs dagegen ziemlich gut
Jetzt, da Code billiger und schneller entsteht, müssten wir vielleicht im Gegenteil die formale Entwurfsphase stärken
Ich glaube, den größten Einfluss auf die Codequalität hatte bei mir das systematische Einrichten von statischen Analysetools
Für TypeScript habe ich
tsc,eslint,sonarjs,knip,jscpd,dependency-cruiser,semgrepusw. kombiniert und im Befehlpnpm checkzusammengeführtÜber einen pre-commit hook läuft das automatisch und verhindert Probleme, die das LLM übersehen hat
Dadurch kann ich auch dann leicht manuell nachbessern, wenn das LLM ins Stocken gerät
Wenn der Codestil konsistent ist, wird das Review deutlich einfacher, und selbst wenn AI-Code und von Menschen geschriebener Code gemischt sind, gibt es weniger Verwirrung
Selbst wenn Linting und Tests alle durchlaufen, entsteht aber manchmal Code, der anders funktioniert als beabsichtigt
Zum Beispiel eine API, die statt eines 404 ein leeres Array zurückgibt: syntaktisch korrekt, semantisch aber falsch
Diese Bewertung der Verhaltenskorrektheit ist nach wie vor der schwierigste Teil
Manchmal sollte Wartbarkeit wichtiger sein als Lint-Regeln
Ich mache regelmäßig Refactoring, jedes Mal wenn ich neue Funktionen hinzufüge
Alle paar Features prüfe und bereinige ich die gesamte Codebasis
Ich programmiere seit 40 Jahren, aber mit meinem heutigen Code bin ich am zufriedensten
Aber dank LLMs sind die Kosten für Refactoring fast auf null gesunken
Es gibt jetzt keinen Grund mehr, schlechten Code so stehen zu lassen
Der eigentliche Wert liegt darin, Werkzeuge, die Effizienz steigern, zur Qualitätsverbesserung einzusetzen
Ich habe ein internes Tool gebaut, das bei jedem Commit Codezeilen als gut (grün) / Refactoring nötig (gelb) / Neuschreiben nötig (rot) markiert
Es ist sauberer und systematischer als Kommentare wie „TODO refactor“ und soll bald als Open Source veröffentlicht werden
Ich halte spezifikationsbasierte Entwicklung derzeit für den stabilsten Weg, um mit AI zusammenzuarbeiten
Ich investiere mehr Zeit darin, Spezifikationen fein auszuarbeiten und mit dem Team und der AI Ideen hin- und herzuschieben
Wenn die Spezifikation unvollständig ist, produziert die AI Code in die falsche Richtung
Wenn das Domänenverständnis tiefer wird, fühlt es sich oft besser an, die Implementierung noch einmal von vorn anfertigen zu lassen
Damals gab es die Vision: „Definiert einfach die Anforderungen, und das System baut sich von selbst“
Am Ende scheiterte das und Agile wurde zum Mainstream, aber jetzt scheint die Technik diesen Traum wieder möglich zu machen
Der eigentliche Wert von AI liegt in Geschwindigkeit und der Fähigkeit, mit Unschärfe umzugehen
Wenn man aber alle formalen Schritte vollständig durchläuft, wird es am Ende so langsam wie Waterfall
Ich denke, es ist besser, den Code selbst zu schreiben und AI als Reviewer erster Stufe einzusetzen
In kleinen Einheiten schnell zu validieren und voranzugehen, bleibt ein agiler Ansatz
Besonders gut fand ich den Vorschlag, sicherheitsrelevante Funktionen zu markieren. So bleibt der Kontext bei späteren Codeänderungen erhalten
„In kleine Teile zerlegen“ ist zwar grundlegend, wird von Einsteigern aber oft übersehen
Es ist lustig, dass Leute dank AI gerade wieder grundlegende Best Practices neu entdecken
Eigentlich hätte man solche Dinge schon immer tun sollen
Jetzt, da das Codieren weniger Zeit kostet, gibt es mehr Spielraum für solche Arbeiten
Außerdem nutzt AI Dokumentation tatsächlich, daher bringt gutes Schreiben von Doku jetzt einen direkten Mehrwert
Früher schrieb man Dokumentation und sie wurde ignoriert, aber LLMs lesen alles
Früher habe ich vor dem Coden detaillierte Spezifikationen geschrieben, später merkte ich aber, dass es schneller ist, direkt in den Code einzusteigen
Kehren wir jetzt wieder zu einem spezifikationszentrierten Ansatz zurück?
Wenn man eine Spezifikation schreibt, ohne das Problem vollständig verstanden zu haben, lernt man am Ende doch wieder beim Coden
Im Moment scheinen wir irgendwo dazwischen zu stehen
Andererseits fühlt es sich so an, als würde der Wert der Spezifikation sinken, weil AI die Kosten für falschen Code fast auf null drückt
Das ähnelt der Art zu programmieren, von der Joe Armstrong gesprochen hat
Jetzt leben wir in einer Zeit, in der das praktisch realistisch geworden ist
Als ich eine Lead-Position hatte, habe ich Tickets sehr detailliert geschrieben
Einerseits für Junioren, andererseits auch, damit ich selbst keine Details vergesse
Das Management war jedoch dagegen und bezeichnete es als „Zeitverschwendung“, wodurch ich mir diese Gewohnheit abgewöhnt habe
Heute wird von mir im Gegenteil verlangt, noch ausgefeiltere Spezifikationen noch schneller zu schreiben
Bei AI-Agenten würde mich das Verhältnis von Markdown zu Code und die Lesbarkeit des Ergebnisses interessieren
Ich frage mich auch, ob das Review am Ende nicht mehr Zeit kostet, als den Code selbst zu schreiben
Es ist ironisch, wie Entwickler heute begeistert AI verteidigen, die sie am Ende vielleicht selbst ersetzen könnte
In diesem verlinkten Tweet wird dieses Phänomen satirisch aufs Korn genommen
Vielleicht kommt daher auch die Botschaft: „Wenn du Claude nicht benutzt, fällst du zurück“
tatsächlich könnte das aber zu sinkender Nachfrage nach Entwicklern und geringerer Vergütung führen
Besonders gefährdet sind Entwickler, deren Arbeit sich im Wesentlichen darauf beschränkt, NPM-Pakete zusammenzustecken