Code-Nostalgie und KI-Coding
KI-Coding ist immer mehr im Kommen. Glaubt man den Propheten, braucht man in kürze gar nicht mehr selbst programmieren zu können. Ich bin da immer etwas skeptischer und versuche meine Gedanken und Erfahrungen etwas in Relation zur Programmiergeschichte zu setzen.
Ich gehe inzwischen seit 30 Jahren mit Computern um. Angefangen habe ich 1995 mit einem Rechner, auf dem DOS und Windows 3.1 lief. Das war vielleicht ein 286er oder 386er, das lässt sich leider nicht mehr so genau rekonstruieren. Jedenfalls habe ich damals nicht wirklich programmiert, aber ich habe in der Kommandozeile die Namen der Spiele eingetippt, die ich spielen wollte.
2003 habe ich angefangen, C zu lernen. Das war auch anfangs total spannend, bis die Speicheradressen und Zeiger kamen. Ich habe & und * im Code verteilt, bis es kompilierte. Und dann hatte ich Segmentation Faults. Rückblickend kann ich klar sagen, dass meine Abstraktionsfähigkeiten einfach noch nicht ausgereicht hatten zu dem Zeitpunkt. Ich habe PHP gemacht, dann Java, Matlab, Python, C++, R. Dazwischen dann noch Skripte in Bash geschrieben, Dokumente in LaTeX gesetzt. Haskell habe ich auch noch gelernt, sowie auch ein Buch über JavaScript gelernt. Für die Promotion habe ich noch die Wolfram Language gelernt und genutzt. Man kann also sagen, dass die Sprachen kamen und gingen.
Während der Masterarbeit habe ich viel mit C++ entwickelt, da ging es um Rechenleistung, es ging um numerische Berechnungen. Ich habe Vorträge von C++ Konferenzen wie Going Native und Cpp Con geschaut. Ich war so richtig drin. Ich habe mich gefreut, dass C++11 (also der 2011er-Standard) nun [](){} als Syntax erlaubt. Und später habe ich mich gefreut, dass C++20 dann auch endlich []<>(){} kann. Während der Promotion habe ich vor allem Datenanalyse und analytische Berechnung gemacht, da habe ich mir R und Wolfram Language gearbeitet. Beide waren neu für mich. Aber sie waren die jeweils besten Sprachen für die Aufgaben.
Handwerker- vs. Leidenschaftsmentalität
Es gibt das Konzept von Craftsman vs. Passion Mindset, das wohl aus dem Buch So Good They Can’t Ignore You1 stammen soll. Die Kernidee ist, dass man sich seinen Beruf nach seiner Leidenschaft (Passion) aussuchen kann. Man findet das heraus, was man machen möchte, was man in der Welt bewegen möchte. Oder aber man identifiziert sich mehr mit der handwerklich guten Ausübung seiner Arbeit, was auch immer sie sein mag.
Ich fühle bei mir klar die Handwerkermentalität. Mir ist es nicht so wichtig, was ich mache, sondern wie ich es tue. Ich habe damals die Webseite für die Schule gemacht. Was genau da für Inhalte und Struktur waren, fand ich nicht so wichtig. Aber ich wollte es gut machen, es sollte hübsch sein, der Code sollte sauber sein. Gut, mit meinem Wissen in 2026 bewerte ich meinen Code von 2005 nicht unbedingt als hübsch und sauber, aber das zeigt nur meinen Lernfortschritt. An der Uni habe ich Hadronenphysik simuliert, nun entwickle ich Software für Maschinenübersetzung. Es sind immer ganz andere Anwendungen, aber meine Motivation ist vor allem darin, etwas gut zu machen.
Habe ich eine Leidenschaft für Physik? Also ich finde es schon interessant und kann Stunden darüber diskutieren. Aber anscheinend war meine Leidenschaft nicht so tief, dass ich trotz des akademischen Systems in Deutschland weiter daran arbeiten wollte. Ich war bereit, die Physik zu verlassen um in der freien Wirtschaft zu arbeiten. Als ich mich beworben hatte, hätte ich nicht glaubhaft behaupten können, eine Leidenschaft für Übersetzung zu haben. Nun habe ich das einige Jahre gemacht und finde das Thema interessant, sehe die Wichtigkeit für die Welt und habe auch Freude daran. Aber es ist sicher nicht das einzige interessante Thema in der Welt.
Was aber an der Uni und jetzt in der Industrie gleich ist, das ist meine Begeisterung für ordentliche, professionelle Arbeit. Ich mag es nicht, wenn man einfach nur irgendwelchen Code zusammenhämmert und sich dann schon in Monaten danach fragt, was man da für einen Schrotthaufen hat. Ich räume dann lieber auf, als mit noch mehr Gewalt noch mehr Dinge anzuschrauben. Wenn ich Code lese und mir der gefällt, dann fühlt sich das gut und befriedigend an. Dabei ist mir schon letztlich egal, was er eigentlich tut.
Das treibt mich auch beim Bleistiftzeichnen an. Also wahrscheinlich hätte ich mit Tuschemarkern, Aquarell-, Öl- oder Acrylfarben ähnlich viel Freude. Aber ich habe irgendwie zu Bleistiften tendiert. Und nun zeichne ich gerne diverse Dinge, freue mich einfach an der Entwicklung meiner Fähigkeiten. Der konkrete Bildinhalt ist mir nicht komplett egal, aber der Fortschritt meiner handwerklichen Fähigkeiten ist das, was mich wirklich glücklich macht.
Andere Leute haben das anders. Die interessieren sich weniger für den Code und mehr für das, was er erreicht. Wenn man ein Programm oder einen Dienst nutzt, dann sieht man den Code dahinter nicht. Gerade bei Banken und Fluggesellschaften, die als Branche nach außen hin sehr seriös und professionell wirken, steckt wohl teilweise extrem alter Code hinter. Und wir nutzen es trotzdem, weil es Implementierungsdetails sind, die für das Ergebnis irrelevant sind.
Softwareentwicklung mit KI
Ich spüre gerade einen massiven Wandel meines aktuellen Berufsfeldes. Früher hat man von Hand den Code geschrieben, heute lässt man die KI das machen. Die Systeme werden immer komplexer und fähiger. Das erste, was ich mal ausprobiert hatte, war ein Skript von ChatGPT erzeugen zu lassen. Es hat ganz gut funktioniert. Aber irgendwie hat mir der Stil nicht gut gefallen.
Mit der Zeit habe ich mehr Erfahrung damit gesammelt. Man muss nämlich die Ausgabe korrigieren, man muss weitere Hinweise geben. Zum Beispiel erzeugen viele Modelle sehr langatmigen Code mit erklärenden Kommentaren. Das sieht man in Lehrbüchern so, weil sie den Code und die Sprache erklären. Ich brauche das aber nicht, meine Kollegen auch nicht. Man kann in den Grundeinstellungen (zum Beispiel AGENTS.md) dann angeben, dass man kompakten Code möchte. Und dann macht das Modell schon direkt einen besseren Job.
Man sollte auch den Planungsmodus ausprobieren. Damit kann man erstmal einen Plan erstellen, was man tun möchte. Und erst, wenn der wirklich sinnvoll ist, lässt man das Modell loslegen. Die Ergebnisse können sich teilweise echt sehen lassen, teilweise erzeugen die Modelle da auch gut aussehenden Quatsch.
KI verschiebt die Gewichtung vom Aufwand allerdings. Früher habe ich mir viele Gedanken gemacht und dann lange programmiert. Mit KI ist es jetzt so, dass ich zuerst iterativ den Plan erstelle. Das dauert recht lange. Aber die eigentliche Implementierung macht das Teil im Hintergrund. Ich muss mir dann den erzeugten Code anschauen. Und den muss ich dann verstehen, weil ich den nicht selbst geschrieben habe. Somit komme ich eher in die Rolle eines Reviewers, der sich die Arbeit einer anderen Person anschaut. Damit bin ich aber eben nicht mehr der ausführende Handwerker, ich bin der Meister, der die Arbeit am Ende abnimmt.
Viele Führungskräfte bemängeln, dass ihnen die eigenständige Arbeit fehlt. In einer Feuerwehr-Dokuserie (»Feuer und Flamme« vom WDR, empfehlenswert!) gibt es immer wieder Zugführer, die dann doch gerne mal wieder einen Schlauch in die Hand nehmen wollen. Aber ihr Job ist nun das Koordinieren und Ausbilden der Nachwuchskräfte.
Fülle an Code
Durch diese Verschiebung von der Arbeit, ist es nun sehr einfach, riesige Mengen Code zu erzeugen. Und gerade die etwas mutigeren Kolleg:innen gehen dann hin und lassen ganz viel Code erzeugen. Sie schauen dann, ob der das tut, was sie wollen. Und dann sind sie zufrieden, weil es ihnen um den Zweck des Codes geht. Ich arbeite nun an einem Projekt, wo ich mit derart erzeugtem Code weiterarbeiten muss. Ich versuche diesen Code zu lesen, aber er liest sich eben so leer wie von einem LLM erzeugter Text. Alles irgendwie korrekt, irgendwie zutreffend, aber auch steril.
Teilweise ergeben Dinge keinen Sinn, weil dem Modell Kontext fehlte. So hatte es in einem Fall noch eine zusätzliche Funktionalität erzeugt, die wir an der Stelle aber gar nicht brauchen. Sie ist aber jetzt im Code drin. In der Konfigurationsdatei steht es auch drin. Damit ist die Option jetzt in der Welt. Sie hat bisher auch nicht gestört, weil der Code gar nicht mehr so genau angeschaut wird.
Und da fange ich an, mich unwohl zu fühlen. Es ist nicht nur Social Media und YouTube, das mit AI Slop vollgepumpt wird. Nun habe ich das auch noch auf der Arbeit, in dem Code, in dem ich arbeite. Und auf eine gewisse Art ist das auch »mein« Code, mit dem ich mich etwas identifiziere und meine handwerkliche Befriedigung ziehe. Da wird nun von KI erzeugter Code reingekippt.
Wenn ich mich mit den Kollegen unterhalte, die den Code geschrieben habe, können sie den Code nicht mehr erklären. Laut Versionskontrollsystem haben sie die Änderungen beigesteuert. Aber sie haben sie ja nicht selbst verfasst. Es gibt also letztlich keinen Owner des Codes mehr.
Ich muss mich nun entscheiden: Wehre ich mich dagegen, bestehe ich auf leserlichem Code, dass es echte Owner gibt, die sich mit den jeweiligen Zeilen identifizieren können? Ich müsste hingehen und all diesen Code lesen. Ich käme auch von der Geschwindigkeit nicht mehr gegen die anderen an, die mit Hilfe von KI viel mehr Code erzeugen. Oder aber ich mache auch einfach mit, nutze KI für mich.
Ich habe da so ein Bild, um die Absurdität von KI-Nutzung zu zeigen: Jemand hat zwei Gedanken, die er mit einer anderen Person teilen möchte. Aber anstelle eine E-Mail mit zwei Sätzen zu schreiben, nutzt er KI um daraus eine Bildschirmseite E-Mail mit tollen Floskeln zu machen. Die Empfängerin schaut auf die Bildschirmseite Text und ist genervt, dass sie trotz ihres vollen Pensums so viel Text lesen soll. Ihre KI fasst die E-Mail zusammen in zwei Stichpunkte. Mit Glück bekommt sie die gleichen zwei Gedanken, die der Absender in seine KI gesteckt hat.
Eine neue Abstraktionsstufe?
Vielleicht sind wir auch wirklich an einer Schwelle, bei der wir die nächste Abstraktionsstufe erreicht haben. Nun schreiben wir nicht mehr in konkreten Programmiersprachen, sondern nur noch in natürlicher Sprache und lassen die KI das dann umsetzen.
Das ist nicht das erste Mal, dass es so einen Schritt gab. Dazu ein Beispiel. Nehmen wir eine einfache Funktion in C, die die Summe aller Zahlen zwischen zwei Werten berechnet:
int sum(int lower, int upper) { int s = 0; for (int i = lower; i < upper; ++i) { s += i; } return s; }
Dann kompiliert man das und führt es aus, das sollte funktionieren. Aber was hat der Compiler jetzt gemacht? Was kommt da für Maschinencode raus? Ist das nicht eigentlich egal?
Wir können uns den einmal anschauen. Hiermit kann man den extrahieren:
❯ gcc -c example.c ❯ objdump -d -M intel example.o
Und so sieht der (in Intel-Syntax) dann aus:
0000000000000000 <sum>: 0: 55 push rbp 1: 48 89 e5 mov rbp,rsp 4: 89 7d ec mov DWORD PTR [rbp-0x14],edi 7: 89 75 e8 mov DWORD PTR [rbp-0x18],esi a: c7 45 fc 00 00 00 00 mov DWORD PTR [rbp-0x4],0x0 11: 8b 45 ec mov eax,DWORD PTR [rbp-0x14] 14: 89 45 f8 mov DWORD PTR [rbp-0x8],eax 17: eb 0a jmp 23 <sum+0x23> 19: 8b 45 f8 mov eax,DWORD PTR [rbp-0x8] 1c: 01 45 fc add DWORD PTR [rbp-0x4],eax 1f: 83 45 f8 01 add DWORD PTR [rbp-0x8],0x1 23: 8b 45 f8 mov eax,DWORD PTR [rbp-0x8] 26: 3b 45 e8 cmp eax,DWORD PTR [rbp-0x18] 29: 7c ee jl 19 <sum+0x19> 2b: 8b 45 fc mov eax,DWORD PTR [rbp-0x4] 2e: 5d pop rbp 2f: c3 ret
Da ist jetzt Vorbereitung am Anfang der Funktion. Interessant ist die Zeile 1c, da wird die eigentliche s += i mit dem add Addition gemacht. In Zeile 1f wird das ++i gemacht. In Zeile 26 wird i < upper mit dem cmp verglichen. Und in Zeile 29 wird dann mit dem jl wieder an den Anfang der Schleife gesprungen, falls nötig.
Aber moderne Compiler können noch viel mehr. Sie nutzen Vektor-Instruktionen (AVX), Loop Unrolling und hochspezialisierte Befehle, die den Code zwar um den Faktor 100 beschleunigen, aber für Menschen völlig unlesbar machen.
Angenommen, man würde ein Programm komplett in dieser Maschinensprache schreiben. Und nun kommt jemand daher und lässt mit einem C-Compiler derartigen Maschinencode erzeugen. Was würde ein »Maschinensprache-Handwerker« davon halten? Würde die Person sich ähnlich unwohl damit fühlen wie ich mit dem KI-generierten Code?
Andererseits ist es schlicht absurd, sich am Maschinencode festzuhalten. Die Zeit ist vorbei. Der Compiler ist heute besser in Assembly als fast jeder Mensch. Er abstrahiert die hässlichen Details der Hardware weg, sodass wir uns auf die Logik in C oder Python konzentrieren können.
Vorteil der Abstraktion
Es gibt ja jenseits der x86_64 Architektur in meinem Laptop noch ARM oder PowerPC. Und die werden dann zu komplett anderem Maschinencode erzeugt. Der oben gezeigte Maschinencode ist nämlich spezifisch für x86_64. Auf einem Mac oder Android (mit ARM) sieht das schon komplett anders aus. Und von daher ist es zwar schön, wenn man ganz tollen x86_64 Maschinencode per Hand schreiben kann. Aber bei der nächsten Generation der CPU muss ich dann die neuen AVX-2 Instruktionen selbst nutzen. Oder wenn Apple von x86_64 auf ARM umstellt, muss ich alles neu schreiben. Das ist furchtbar.
Und so ist C eine super Abstraktion, weil ich nun das gleiche Programm mit einem anderen Compiler auf einer beliebigen Plattform kompilieren kann. Der erzeugte Code ist mir eigentlich egal, weil ich mir den eh nie anschauen werde.
Vergleich zu KI-Coding
Der Unterschied zwischen einem Compiler und einem LLM ist allerdings die Eindeutigkeit und Reproduzierbarkeit. Der C-Code wird so auf Maschinencode abgebildet, sodass er exakt das tut, was im C-Programm steht. Wenn das Programm beim Ausführen nicht funktioniert, dann ist das fast immer ein Fehler im Programm. Fehler in Compilern sind extrem selten. Ich habe mal einen Fehler im Intel-C++-Compiler gefunden, aber für normale Programmierer passiert das wenige Male im Leben, wenn überhaupt. Man kann sich schlicht auf die Compiler verlassen.
Bei der aktuellen KI kann man sich überhaupt nicht blind darauf verlassen. Das liegt zum einen daran, dass die KI eben nur stoachstisch arbeitet. Zum anderen aber auch daran, dass natürliche Sprache einfach nicht so präzise ist, wie eine Programmiersprache. Man hat mit COBOL versucht, eine möglichst natürliche Programmiersprache zu schaffen. Aber so richtig funktionierte das bisher nie.
Und somit bin ich noch nicht überzeugt, dass man sein Programm nur in Design-Dokumenten in natürlicher Sprache schreibt und die KI das komplett eigenständig »kompiliert«. Es hat zwar den Charme, dass sie es dann in jede Programmiersprache umsetzen könnte und damit nochmal abstrakter ist. Aber bis man wirklich alles ganz eindeutig hat, muss man sehr viel Text schreiben. Programmiersprachen sind da präziser. Aber häufig ist diese Präzision dann auch egal, wenn es das nur irgendwie tun soll.
Ich werde weiter mit KI-Werkzeugen Erfahrungen sammeln und schauen, wie sich das entwickelt, gerade auch im Zusammenspiel mit Kolleg:innen. Denn es könnte das Potential haben, die Softwareentwicklung auf eine neue Abstraktionsebene zu heben. Oder aber man erzeugt ganz viel Code, den niemand mehr versteht. Da mir noch nicht klar ist, wie es enden wird, muss ich wohl dabei bleiben.
-
Newport, Cal. So Good They Can’t Ignore You: Why Skills Trump Passion in the Quest for Work You Love. Piatkus, 2016. ↩