In vielen meiner Projekte schreiben inzwischen Coding Agents einen großen Teil der Software. Ob das Ergebnis anschließend richtig ist muss zwar weniger und weniger tatsächlich in Frage gestellt werden. Dennoch entscheiden bei mir Tests (auf echter Hardware), Reviews und am Ende ich selbst, ob der Code so freigegeben werden kann. Diese Verschiebung ist das eigentliche Thema, was uns alle, die in der gleichen Zunft unterwegs sind seit 1-2 Jahren umtreibt.

Wie wir hierher gekommen sind

In den 90ern hieß das Problem Software-Krise. Die Rettung sollte von überall kommen, nur nicht aus dem Code: schwere Methodiken, CASE-Werkzeuge, grafische Programmierung, Spezifikationssprachen. Das Ziel war immer dasselbe, das Problem von seiner Implementierung wegzuabstrahieren. Erfolg korrelierte in den wenigen Studien der Zeit mit etwas anderem: Assertions, Versionskontrolle, Unit-Tests.

Ab den 2000ern drehte sich das schließlich um. „The code is the design.” Open Source, Patterns, Agile und CI organisierten sich um die Einsicht, dass der Code die Abstraktionsebene ist.

Jetzt kippt es zum zweiten Mal. Codeproduktion ist Massenware. Übrig bleiben da nur noch Review, Verständnis und Verantwortung. Der Output übersteigt, was ein einzelner oder ein Team prüfen kann. Produzieren ist billig, Inspizieren hingegen teuer.

Dabei habe ich mindestens vier Umkehrungen in den letzten Jahren festgestellt:

  • Programmierer wird Programm-Manager, auch für ein Team aus Agenten.
  • Generalwissen bringt die Maschine mit. Bezahlt wird Spezialwissen.
  • Schlau reicht nicht mehr. Gefragt ist das Urteil, was hier angemessen ist.
  • Wir hatten primitive Systeme unter Kontrolle. Jetzt sind wir die Stelle, an der die Verantwortung für KI-Output landet.

Der letzte Punkt ist in regulierter Software der entscheidende. IEC 62304 kennt kein „das hat der Agent so gebaut”. Der Hersteller haftet, und das ist ein Mensch mit Namen. Wer das ernst nimmt, baut seine Arbeit um den Inspect-Teil herum. Mein HIL-Prüfstand aus dem letzten Artikel ist genau das: eine Maschine, die den Agenten kontrolliert, nicht eine, die ihm beim Schreiben hilft.

Eine Umkehrung ist wirklich neu. Zum ersten Mal erklären Werkzeuge selbst, wie man sie benutzt. „Wie setze ich diesen Agenten für X ein?” Frag den Agenten. Die Selbsteinschätzung stimmt nicht immer. Ehrlicherweise tat das die Dokumentation früher aber auch nicht :-)

„as appropriate” ist heute die ultimative Abstraktion geworden

Während man noch vor dem Aufkommen von LLMs in der täglichen Entwicklungsarbeit noch galt, eine präzise Spezifikation aufzustellen, seine Werkzeuge zu meistern, eine gute Architektur aufzustellen und möglichst testgetrieben zu entwickeln, reicht heute ein as appropriate: Write me some unit-tests for these modules, as appropriate. Oder make use of the Visitor pattern as appropriate. Diese Abstraktion funktioniert aber nur solange der Mensch vor der Tastatur überhaupt solche Abstraktionen kennt. Wer das nicht weiß, bekommt irgendetwas. Gleichzeitig bedeutet hier aber auch je mehr Wissen man selbst einbringt, desto weniger Kreativität ist notwendig. Das gilt tatsächlich für beide Seiten des Prompts.

Für die Praxis folgt daraus etwas Unbequemes. Die Qualität dessen, was ein Agent baut, hängt an der Qualität der Abstraktionen im Projekt. Ein gewachsenes C++-Projekt mit einkopierten Abhängigkeiten und einer Architektur, die nur in zwei Köpfen existiert, gibt dem Modell nichts, woran es sich halten kann. Dieselbe Codebasis mit sauberem Dependency-Graph, klaren Modulgrenzen und benannten Mustern ist für einen Agenten ein anderes Projekt. Kein Feature ist anders. Die Abstraktion ist es.

Abstraktion muss die Codegenerierung überleben

Eine verbreitete These: Sprachfeatures braucht niemand mehr, die KI erzeugt beliebigen Code. Wozu Reflections in C++26, wenn das Modell jede instrumentierte Klasse auf Zuruf schreibt?

Mit KI ohne Reflection kann man jede instrumentierte Klasse definieren. Man kann nicht den Begriff der instrumentierten Klasse definieren. Der erste Weg liefert 40 Klassen, die beim nächsten Refactoring in 40 Richtungen auseinanderlaufen. Der zweite liefert eine Abstraktion, die im Projekt bleibt.

Instanziierung löscht Abstraktion. Jeder kennt das aus Template-Code im Debugger, generierter Code ist nicht anders. Ein Modell kann die Struktur aus dem expandierten Code zurücklesen. Das kostet bei jedem Durchlauf Kontext und geht regelmäßig schief. Die Struktur muss deshalb im Projekt persistieren: in Sprachfeatures, Bibliotheken, Modulen, dokumentierten Entscheidungen. Agenten mit begrenztem Kontextfenster unterliegen derselben Beschränkung wie Entwickler mit begrenztem Arbeitsgedächtnis. Gute Abstraktionen helfen beiden aus demselben Grund.

Für Programmiersprachen bedeutet das: Der etablierte Platz wiegt plötzlich schwer. Modelle lernen neue Sprachen über Ähnlichkeit zu bekanntem. Was eine neue Sprache interessant macht, neue Idiome, fällt ihnen am schwersten. Für C++ ist das eine gute Nachricht. Für ein Produkt mit 15 Jahren Lebensdauer erst recht.

Was bleibt

Dijkstra wollte eine Ebene, auf der man absolut präzise sein kann. Koenig nannte es selektive Ignoranz, Liskov das Verbergen irrelevanter Details. Es ist das einzige Prinzip, das sich nicht abnutzt, wenn die Intelligenz am anderen Ende der Tastatur zunimmt. Es skaliert mit.

Zwei Konsequenzen für meine eigenen Projekte. Erstens: in die Inspect-Seite investieren. Tests auf Hardware, Sanitizer in der CI, Reviews, die mit dem Output mithalten. Zweitens: Architektur ist nicht mehr nur Pflege fürs Team, sondern Voraussetzung dafür, dass Agenten überhaupt sinnvoll arbeiten. Wer ein Legacy-Projekt mit Blick auf KI modernisieren will, fängt nicht beim Prompt an, sondern beim Dependency-Graph. Genau das ist mein Thema unter Softwarearchitektur & Technical Leadership.