Tippe den Code selbst
(haskellforall.com)- Das direkte Eintippen von Code und das anschließende Rekonstruieren aus dem Gedächtnis prüfen Verständnis und Erinnerung strenger als bloßes Kopieren
- Freecoding ist die Fähigkeit, Code Zeichen für Zeichen zu schreiben, während man Syntax, Typen und Namen im Kopf behält, und bleibt auch im Zeitalter von Tools wichtig
- Syntax ist kein störendes Rauschen, das höherstufiges Denken behindert, sondern komprimiert präzise Bedeutung und ermöglicht dadurch Denken auf höherer Ebene
- Wenn man Typen und Schemata nur locker bei Bedarf nachschlägt, wird das Systemdesign unscharf; wer das Typmodell nicht versteht, greift eher zu Ausweichmanövern wie
as any - Fehlen Namensgedächtnis und Verständnis für vorhandene Vorarbeiten, erzeugen Agenten leicht doppelte Implementierungen, und auch die Prüfung von Ausgaben und Tests wird schwieriger
Warum man Code selbst tippen sollte
- Zed Shaws Kurse „Learn X the hard way“ rieten dazu, Beispiele nicht per Copy-and-paste zu übernehmen, sondern selbst einzutippen; in jüngerer Zeit empfiehlt er noch stärker, Übungen nach Abschluss zu löschen und anschließend aus dem Gedächtnis neu zu erstellen
- Das Phänomen, dass aktives Erzeugen von Inhalten das Verständnis stärker fördert als passiver Konsum derselben Inhalte, wird in der kognitiven Psychologie als Generation Effect bezeichnet
- Wie Richard Feynman sagte: „What I cannot create, I do not understand“ — das Rekonstruieren von Code aus dem Gedächtnis prüft zugleich Verständnis und Erinnerung
- Auch im Zeitalter des Agent Coding heißt das nicht, dass man keine Entwickler-Tools verwenden sollte, aber man sollte gelegentlich die Fähigkeit trainieren, Code auf Zeichenebene ohne den Komfort von Tools zu schreiben
- Diese Übung zielt darauf ab, die Details des Programmierens — etwa Syntax, Typen und Namen — im Kopf zu behalten, damit man „freecoding“ betreiben kann
Freecoding und Detailwissen im Kopf
- Freecoding ist die Fähigkeit, Code direkt aus dem Gedächtnis zu schreiben; dafür muss man grundlegende Elemente wie Syntax, Typen und Namen im Kopf behalten
-
Syntax und Struktur
- Man muss mit Keywords, Satzzeichen und Sprachkonstrukten vertraut sein
- Es geht nicht um reines Auswendiglernen von Grammatik, sondern um die Fähigkeit, sich die Form von Code präzise vorzustellen
-
Typen und Schemata
- Man sollte mit Typsystemen und Datenmodellen vertraut und sicher im Umgang sein
- Wenn man bei Tabellen, Spalten, Relationen und Typstrukturen eines Projekts jedes Mal erst nachschlagen muss, wird Systemdesign auf höherer Ebene schwierig
-
Namen
- Man sollte Funktions-, Methoden-, Klassen-, Import-, Datei- und Paketnamen präzise abrufen können
- Wenn sich Projekte und Abhängigkeiten ändern, muss auch dieses Wissen aktuell gehalten werden
- Wenn man den im Kopf entworfenen Code nicht mit einer gewissen Präzision eintippen kann, hat man ihn in Wahrheit meist nicht klar verstanden, sondern verwechselt das mit Verständnis
- Englisch ist keine so präzise Sprache wie Code; das passt auch zu dem separaten Text A sufficiently detailed spec is code, wonach eine hinreichend detaillierte Spezifikation letztlich Code wird
Syntax ermöglicht Denken auf höherer Ebene
- Auch wenn IDEs oder Coding-Agenten die Syntax korrigieren können, bleibt die Fähigkeit wichtig, Syntax selbst zu beherrschen
- Wenn jemand schon Schwierigkeiten hat, Klammern richtig zu setzen, kann man auch daran zweifeln, ob diese Person die logischen Prämissen und Schlussfolgerungen anderer flüssig verbinden kann
- Die Haltung, Details zu ignorieren, kann mit funktionalem Analphabetismus zusammenhängen: Man kommuniziert eher nach Stimmung als über klar abgegrenzte Wortbedeutungen
- Beispielhafte LLM-Prompts wirken oberflächlich plausibel, enthalten bei genauerem Lesen aber gleichzeitig widersprüchliche Anweisungen
- „Schlage keine externen Tools oder Alternativen vor, die nicht zu den oben aufgelisteten skills gehören“
- „Wenn die Aufgabe Fähigkeiten erfordert, die über die verfügbaren skills hinausgehen, dann sage das“
- Die Fähigkeit, kleine Fragen von Grammatik, Rechtschreibung und Struktur präzise zu behandeln, ist nicht von der Fähigkeit zu trennen, das große Ganze korrekt zu verstehen
- Syntax ist kein Detail, das höherstufiges Denken behindert, sondern ein mentales Werkzeug, das höheres Denken komprimiert und überhaupt erst ermöglicht
- Typnotation kann präziser und knapper sein als eine Erklärung in natürlicher Sprache
x ist ein Array von Objekten, und jedes Objekt hat eine erforderliche Eigenschaft `domain`, die einen String speichert, sowie eine optionale Eigenschaft `port`, die eine Zahl speichertx : { domain: string, port?: number }[]
Typen und Schemata sind zentrale Hinweise für Systemdesign
- Fred Brooks sagt in The Mythical Man-Month, dass die Struktur meist auch ohne Flussdiagramm klar wird, wenn man die Tabellen sieht
- Wer eine Datenbank nutzt, sollte die Tabellen, Spaltennamen und Relationen des Projekts in- und auswendig kennen
- Statt diese Informationen nur lose bei Bedarf nachzuschlagen, sollte man sie vorab erfassen und im Kopf behalten, damit effektives Systemdesign auf Systemebene möglich wird
- Ohne diese Anstrengung wird das Datenbankschema leicht ebenso verworren wie das Denken selbst — mit redundanten, ähnlichen Daten in einer denormalisierten Struktur
- Erfahrungen mit stark typisierten Sprachen wie Rust oder Haskell machen die Vorteile eines starken mentalen Modells von Typen besonders sichtbar
- Das Training eines präzisen „mentalen Type Checkers“ oder „mentalen Borrow Checkers“ hilft auch dann, wenn man mit schwächer typisierten Sprachen arbeitet
- Wer diese Muskeln für abstraktes Schlussfolgern nicht nutzt, übersieht leicht selbst Grundlagen der Datenmodellierung wie unmögliche Zustände unrepräsentierbar machen
- Wer nicht versteht, wie Typen ineinandergreifen, verteilt in TypeScript schnell
as anyim Code - Wenn man schon die Unbequemlichkeit scheut, im Normalfall über Typen nachzudenken, ist der Ausnahmefall des Debuggens von Typfehlern noch schwerer zu ertragen
- Das heißt nicht, dass Haskeller oder Rustaceans immer besseren Code schreiben, aber bei sonst gleichen Bedingungen hilft Typ-Souveränität
Wer wiederverwenden will, muss sich Namen merken
- Häufig genutzte Funktions-, Methoden-, Klassen-, Import-, Paket- und Dateinamen aus dem Projekt oder seinen Abhängigkeiten sollten leicht abrufbar sein
- Das ist eine spezielle Form des allgemeineren Prinzips, mit bereits vorhandener Arbeit — also Prior Art — vertraut zu sein
- Viele verlassen sich auf Coding-Agenten, weil sie wiederverwendbare vorhandene Lösungen für die gewünschte Funktion nicht kennen; dadurch lassen sie den Agenten das Rad neu erfinden
- Wer die Existenz von SaaS boilerplate projects nicht kennt, nimmt leicht an, ein Agent müsse das Scaffolding von Grund auf erzeugen
- Für diesen Zweck gebaute und bewährte Open-Source-Projekte zu klonen ist oft schneller, billiger und verlässlicher, als einen Agenten um dieselbe Arbeit zu bitten
- Wenn jemand vorhersagt, ein LLM könne in ein paar Jahren einen ganzen Browser bauen, kann man entgegnen, dass das heute schon möglich ist, indem man Chromium forkt — und dass Anpassung und Wartung dann sogar leichter sind
- Auch bei der Wiederverwendung von Code innerhalb desselben Projekts oder Unternehmens ist das Erinnern von Namen wichtig
- Wer nicht weiß, wonach er suchen soll, kann nicht auf der Arbeit von Kolleginnen und Kollegen aufbauen
Für die Prüfung von Agent-Ausgaben braucht es menschliches Verständnis
- Agenten können beim Auffinden von Namen und beim Erzeugen von Code helfen, aber damit entsteht ein neues Problem: Kann man die Ergebnisse überhaupt sinnvoll prüfen?
- Wer bestehende Funktionen nicht kennt, kann schwer beurteilen, ob ein Agent Funktionalität doppelt implementiert
- Wenn man Code schlechter versteht als der Agent, lässt sich auch die Qualität seiner Ausgabe kaum zuverlässig bewerten
- Man kann einen Agenten zwar bitten, Tests zu generieren, doch wenn man die erzeugten Tests nicht genau prüft, können die Tests selbst zu bedeutungslosem Code werden
- Ein reales Beispiel waren Tests, die den Implementierungscode gar nicht aufriefen, sondern nur direkt
someoderincludesauf Arrays und Strings anwendeten und damit bloß die erwarteten Werte bestätigtendescribe("abort detection logic", () => { it("detects aborted stopReason in messages", () => { const messages = [ { role: "assistant", stopReason: "aborted", content: [] }, ]; const isAborted = messages.some((m: any) => m.stopReason === "aborted"); expect(isAborted).toBe(true); }); it("detects abort in error string", () => { const error = "The operation was aborted"; const isAborted = error.includes("abort"); expect(isAborted).toBe(true); }); it("does not false-positive on normal errors", () => { const error = "Network timeout"; const isAborted = error.includes("abort"); expect(isAborted).toBe(false); }); it("does not false-positive on normal stop reasons", () => { const messages = [ { role: "assistant", stopReason: "stop", content: [] }, ]; const isAborted = messages.some((m: any) => m.stopReason === "aborted"); expect(isAborted).toBe(false); }); }); - In der Softwareentwicklung gibt es viel alltägliche Reibung; wenn man sich entscheidet, schon die kleine Reibung des Erinnerns von Namen nicht zu überwinden, wird man auch die größere Reibung bei der Prüfung von Tests nicht überwinden
- Coding-Agenten nehmen die Anweisungen der Nutzerinnen und Nutzer als zentralen Kontext; intellektuell bequeme Nutzer können Agenten daher in eine ähnlich bequeme Richtung lenken
Beharrlichkeit und Können lassen sich nicht trennen
- Eustress ist nützlicher Stress; wer sich dazu drängt, Neues und Schwieriges zu tun, entwickelt Toleranz gegenüber kleinen Unannehmlichkeiten und kann dadurch auch größere überwinden
- Wer Unbequemlichkeit immer meidet, gerät in einen Teufelskreis aus Hilflosigkeit und Frustration
- Wer in einem Bereich Präzision, Gedächtnis und strukturelles Denken trainiert, verbessert damit auch Fähigkeiten in anderen Bereichen
- So wie LLMs aus Trainingsdaten verallgemeinern, verallgemeinern auch Menschen Gewohnheiten und Fähigkeiten aus einem Bereich auf andere Bereiche
- Softwareentwicklung bedeutet ihrem Wesen nach, die eigene Komfortzone regelmäßig zu verlassen; dazu passt auch der verwandte Text Software engineers are not (and should not be) technicians
1 Kommentare
Lobste.rs-Meinungen
Stimme voll und ganz zu. Nachdem man eine Übungsaufgabe beendet hat, ist es wirklich wichtig, das gerade Gemachte zu löschen und es nur aus dem Gedächtnis noch einmal zu machen
Wenn man nicht weiterkommt, kann man sich Hinweise ansehen, aber es gibt kaum etwas Wichtigeres als die Gewohnheit, den eben durchlaufenen Prozess so weit wie möglich aus dem Gedächtnis zu rekonstruieren.
Commit-Messages und Dokumentation sollte man selbst tippen
Programmierer hassen solches Schreiben oft und sagen schnell: „Das kann doch ein LLM schreiben“, aber wenn man es selbst schreibt, begegnen sich User Experience und Implementierungsentscheidungen an einem Ort. Dann entstehen Überlegungen wie: „Um X zu tun, übergibt man
-Y… Moment, ist das wirklich das Beste?“ oder „Hiermit behebt Y X … aber ginge das nicht auch mit Z?“Bei der Stelle „Wenn dir das Ausbalancieren von Klammern schwerfällt, zweifle ich daran, wie flüssig du die logischen Prämissen und Schlussfolgerungen anderer verbinden kannst“ musste ich lachen, fühlte mich aber kurz ertappt
Zu meiner Verteidigung: Manchmal werden Funktionen einfach viel zu groß.
Auch Vibe-Coding-Müll, den man nicht versteht, zu reparieren, ist in der Praxis eine gute Lernmethode. Man tippt viel und arbeitet in einem realen Kontext statt im luftleeren Raum.
Ich habe es dann von Hand neu geschrieben und als Gelegenheit genutzt, mein in den letzten acht Monaten eingerostetes Programmiergefühl wiederzubeleben. Mit dem Rewrite bin ich zufrieden, und es funktioniert tatsächlich besser. LLMs sind weiterhin nützlich, um Dinge zu erklären oder Blockaden zu lösen, aber das Gefühl, die gesamte Codebasis selbst zu kennen, ist deutlich besser.
Ich verstehe nicht ganz, warum der Prompt „Schlage niemals externe Tools oder Alternativen vor, die nicht in den aufgelisteten Fähigkeiten enthalten sind. Wenn eine Aufgabe Fähigkeiten erfordert, die über die für die Aufgabe verfügbaren Fähigkeiten hinausgehen, dann sage das“ aus zwei widersprüchlichen Anweisungen bestehen soll
Zu sagen „Mit den bereitgestellten Fähigkeiten kann ich das nicht“ ist mit beiden Anweisungen konsistent. Wenn der letzte Satz gelautet hätte „Sage, welche Fähigkeiten erforderlich sind“, dann gäbe es einen Konflikt, aber so wie er jetzt dasteht, sehe ich keinen Widerspruch.
Der zweite Satz liest sich für mich nicht so, als solle das Modell die Existenz nötiger externer Tools oder Alternativen nur implizit durch Verneinung andeuten, sondern als Aufforderung, ihre Existenz konstruktiv zu bejahen.
Die Aussage „Menschen, die sich nicht funktional klar ausdrücken können, tun sich fast ausnahmslos auch schwer damit, orthografisch oder grammatikalisch korrekte Sätze zu schreiben“ wirkt wie ein ziemlich hartes Vorurteil gegenüber Menschen mit Legasthenie oder einfach Menschen, die anders denken
Natürlich wurde damit nicht umgekehrt behauptet, dass mangelnde Rechtschreibung oder Grammatik automatisch bedeutet, funktional unklar zu sein, aber so oder so ist das keine besonders inklusive Formulierung.
Konstruktiver betrachtet könnte man an Node-Editoren denken. Node-basierte Systeme haben in ihren aktuellen Umsetzungen zwar viele Probleme, aber wenn sie gut gemacht sind, können sie die Art des Programmierens so steuern, dass bestimmte Syntaxfehler von vornherein ausgeschlossen werden. Wenn ein Node zum Beispiel einen String erwartet, kann man ihm keine Zahl übergeben. Nicht, weil Einschränkungen erst zur Build-Zeit oder Laufzeit erzwungen würden, sondern weil man dort eine Zahl gar nicht erst „sagen“ kann. Dinge wie falsche Schleifenbereiche, Fehler bei der Anzahl von Argumenten oder unausgeglichene Klammern kann man ebenfalls strukturell unmöglich machen.
Nur weil man Software mit Werkzeugen schreibt, die bestimmte Einschränkungen strukturell erzwingen, heißt das nicht, dass man diese Einschränkungen nicht versteht. Es bedeutet nur, dass man sich weniger Sorgen machen muss, versehentlich genau diese Art von Fehlern einzugeben. Wenn es frustrierend ist, dass ein Tool sich nicht um Syntaxdetails wie die Anzahl der geschweiften Klammern einer Funktion oder die Einrückung eines Logikblocks kümmert, bedeutet das auch nicht, dass man nicht versteht, warum diese Syntax wichtig ist.
Ich habe Node-Systeme als Beispiel gewählt, weil sie die „hinwerfen und vergessen“- oder hirnabschaltenden Vibe-Coding-Elemente von LLMs aus der Gleichung herausnehmen und Syntaxprobleme isoliert sichtbar machen. Wenn man LLMs herausnimmt, wird das Argument mit dem Fokus auf Syntax ziemlich schwach.
Dem Rest des Artikels stimme ich zu, aber Syntaxfähigkeiten als grundlegenden Indikator für das Codeverständnis oder die Fähigkeit, guten Code zu schreiben, zu betrachten, halte ich für einen sehr falschen Weg.
Ich verstehe auch, dass das als wohlmeinendes Feedback gemeint ist, und ich möchte nicht defensiv wirken. Ich hatte eigentlich versucht, es so zu formulieren, dass es nicht wie so eine wenig inklusive Behauptung klingt, aber ich bin offen für andere Formulierungen oder einen anderen Aufbau, die dasselbe besser vermitteln.
Den Punkt selbst möchte ich allerdings nicht ganz streichen. Der Kern dessen, was ich sagen will, ist, dass bei Menschen, die anfangen, mentales Unbehagen erfahrungsbezogen zu vermeiden, meist Rechtschreibung und Grammatik als Erstes zusammenbrechen. Es dürfte Möglichkeiten geben, die Aussage so anzupassen, dass Menschen mit Legasthenie dadurch nicht benachteiligt werden.