Abstract
Wir schreiben heute mehr Code in kürzerer Zeit als jemals zuvor. KI‑Systeme agieren dabei wie ständig verfügbare Juniorprogrammierer: Sie produzieren in Minuten tausende Zeilen Code – aber wer übernimmt dabei die Verantwortung für die Software-Architektur?
Das eigentliche Problem ist daher oft nicht „schlechter KI‑Code“, sondern die wachsende Schwierigkeit für Menschen, den Überblick zu behalten und fundierte Architekturentscheidungen zu treffen.
Dieser Artikel diskutiert eine Idee, um schnell ein mentales Modell von vorhandenem Code aufzubauen, Architekturprobleme früh zu erkennen und Änderungen gezielt vorzunehmen – ohne parallel eine statische Dokumentation pflegen zu müssen.
1. Wir schreiben mehr Code als je zuvor
KI beschleunigt die Softwareentwicklung. Was wir dadurch erleben, ist als Jevons-Paradoxon oder Rebound-Effekt bekannt. Als Compiler für Sprachen wie C entwickelt wurden, wurde Softwareentwicklung auf einmal deutlich schneller. Aber anstatt einfach früher Feierabend zu machen, haben wir komplexere Denkmodelle entwickelt, sodass wir eine neue Sprache wie C++ brauchten. Dieser Übergang passiert immer wieder – von HTML zu React, SQL zu ORM und von Java zu Kotlin.
Mit KI passiert gerade genau das Gleiche. Das Schreiben von Code wird einfacher und die Denkmodelle werden komplexer. Dadurch werden die Kosten nicht geringer, sondern sie verschieben sich – vom Schreiben zum Verstehen.
In klassischen Projekten war das Verhältnis oft ausgewogener: Code entsteht in einem Tempo, in dem Menschen nebenbei ein mentales Modell aufbauen. Bei KI‑generiertem Code kippt dieses Verhältnis. Der Code ist da – das mentale Modell muss folgen.
Das merkt man besonders im Team: Die Zeit, die früher „nebenbei“ in Orientierung geflossen ist (Pair Programming, Code Reviews, gelegentliche Diskussionen über Struktur), wird plötzlich zur eigenen Arbeitspaket‑Kategorie. Man muss Architektur verstehen bevor man sie ändern kann – und diese Reihenfolge lässt sich nicht wegoptimieren.
2. Zwei Arten, KI beim Programmieren einzusetzen
Der Einsatz von KI ist nicht einheitlich. In der Praxis sieht man zwei Pole, zwischen denen sich die meisten Arbeitsweisen bewegen.
2.1 Zielorientiertes „Vibe Coding“
Hier beschreiben Entwickler einfach nur das gewünschte Ergebnis. Die KI liefert die komplette Umsetzung. Der Code wird überhaupt nicht gelesen. Wenn etwas nicht funktioniert, dann muss die KI das fixen.
Das kann erstaunlich gut funktionieren. Der Benchmark ist heute nicht mehr, ob die KI das Spiel Snake in einem Aufruf programmieren kann – sondern einen kompletten Fortnite-Klon.
Das ist ohne Frage beeindruckend, doch dieses Modell stößt an seine Grenzen, wenn es darum geht, diese Software weiterzuentwickeln. Denn ohne Anweisungen zur Software-Architektur tendieren heutige KIs dazu, viel Code in einzelne Dateien zu schreiben. Das führt zu:
- sehr große Klassen und Dateien
- unklare Schichten (UI ↔ Domäne ↔ Infrastruktur verschwimmt)
- flache, schwer wartbare Strukturen
- Abhängigkeiten, die „überallhin“ reichen
Dadurch kommt dann auch die KI irgendwann ins Schlingern, wenn es darum geht den Code zu ändern.
Das wird sich mit neueren Modellen natürlich immer mehr verbessern und vielleicht werden wir irgendwann an den Punkt kommen, wo wir einer KI so sehr vertrauen, wie wir heute einem Compiler vertrauen.
2.2 Architekturgetrieben mit KI‑Unterstützung
Am anderen Ende stehen Teams, die KI bewusst als Beschleuniger einsetzen, aber Architektur als menschliche Aufgabe behandeln:
- kleine, gezielte Prompts
- klare Grenzen (Module, Pakete, Verantwortlichkeiten)
- explizite Anforderungen an Wartbarkeit und Struktur
- konsequentes Nachziehen von Abhängigkeiten, wenn das System wächst
Hier hilft KI vor allem beim Implementieren innerhalb von Leitplanken. Die Leitplanken selbst müssen aber sichtbar und überprüfbar bleiben. Und genau hier taucht die zentrale Frage auf:
Doch wie behalten wir zuverlässig die Struktur im Blick, unabhängig davon, ob wir sie selbst entworfen haben oder eine KI?
3. Wenn es das doch nur geben würde …
Mehr als einmal wollte ich meinen Code umbauen – aber um nichts kaputt zu machen, musste ich erst (wieder) verstehen, wie die Methoden sich gegenseitig aufrufen. Ich habe die Fenster so angeordnet, dass ich einen Screenshot machen konnte, um die Aufrufe mit Pfeilen einzuzeichnen. Jedes Mal habe ich mir gewünscht, dass das automatisch geht. Deshalb habe ich einen kleinen Prototyp gebaut, um zu testen, ob das möglich ist – und wie gut es funktioniert.
4. UML ist die Lösung, aber nicht so wie wir es kennen
Dieses Zeichnen von Methodenaufrufen und Abhängigkeiten zwischen Klassen erinnert sehr stark an UML. Und das ist auch kein Zufall: Verbindungen zwischen Klassen, ihre Beziehungen und die Paketstruktur sind genau das, was wir brauchen, um vorhandenen Code schneller zu verstehen. In der Praxis scheitert UML in vielen Teams aber nicht am Inhalt, sondern an der Dynamik:
- Diagramme sind Momentaufnahmen.
- Sie müssen aktiv mit dem Code synchron gehalten werden.
- Selbst bei automatischer Generierung bleibt Pflegearbeit: Was ist relevant? Was ist Noise? Was gehört ins Diagramm?
UML ist damit oft eher Dokumentation als Navigation. Um wirklich beim Verständnis von KI-generiertem Code zu helfen, brauchen wir etwas, das …
- immer synchron ist
- uns interaktiv Fragen beantworten kann
Dieser Vergleich macht es deutlich:
- Statisches UML‑Diagramm ist wie eine Papierkarte. Sie kann korrekt sein. Oder sie kann veraltet sein. Und es gibt nur genau einen Maßstab.
- Interaktive Visualisierung ist wie Google Maps. Es ändert sich, wenn die Welt sich ändert. Ich kann an die Stelle zoomen, die mich gerade wirklich interessiert. Verschiedene Ansichten helfen genau die Information zu bekommen, die ich gerade brauche.
Der entscheidende Perspektivwechsel ist daher nicht „UML ersetzen“, sondern „Diagramme als lebendes System“ denken:
- direkt aus dem vorhandenen Code abgeleitet
- mit Interaktion, die Exploration unterstützt
5. Abhängigkeiten als gemeinsame Sprache
Doch wie sieht das nun konkret aus? UML-Klassendiagramme zeigen normalerweise nur Klassen, Methoden, Vererbung. Aber um Code wirklich zu verstehen, brauchen wir mehr. Methoden rufen andere Methoden auf – Parameter können vom Typ einer anderen Klasse sein.
Deswegen verwende ich Abhängigkeit als gemeinsame Sprache, die auf allen Ebenen funktioniert. Welchen anderen Teil brauche ich, damit dieser Teil funktioniert?
Der Abhängigkeitsgraph, der dabei entsteht, funktioniert wirklich wie eine geistige Landkarte. Strukturen, die nahe beieinander stehen, haben wahrscheinlich auch eine gemeinsame Bedeutung. Und wenn das nicht der Fall ist, dann ist der Code an dieser Stelle nicht sauber.
Das bringt mich zu ein paar Beobachtungen, die ich beim Testen meines Prototyps schon gemacht habe:
Code ist nicht mehr eine Sammlung von Dateien – sondern eine zweidimensionale Struktur. Ich habe einen Klassennamen gelesen und dachte mir: “Ach ja, das ist die ganz unten rechts”. Und ich wusste auch, welche anderen Klassen dort in der Nähe stehen. Dadurch hatte ich schneller einen Kontext dieser Klasse.
Ein anderer Moment war, als ich angefangen habe, Code umzubauen, weil mir das Diagramm an der Stelle “nicht gefallen hat”. Die Visualisierung wirkte „unruhig“. Also habe ich aufgeräumt. Nicht um eine Architektur-Vorgabe zu erfüllen – sondern aus Ästhetik.
Da wurde mir klar, dass so eine Software nicht das nächste Architekten-Tool ist, sondern ein alltägliches Werkzeug für Programmierer, die einfach nur ihre Tasks erledigen wollen, ohne dabei große Diagramme im Kopf zu bauen und bewusst auf saubere Architektur zu achten.
Dieses Werkzeug schafft mentale Entlastung, wenn man Code erweitern möchte, ohne bestehende Funktionalität zu gefährden. Und es verleitet zu sauberer Architektur – ohne mit dem Zeigefinger zu drohen.
6. Interaktive Abhängigkeitsvisualisierung als Denkwerkzeug
Aber was ist jetzt mit den zwei Punkten Aktualität und Exploration?
Die Aktualität kann dadurch sichergestellt werden, dass das Diagramm direkt aus dem Quellcode erzeugt wird – oder bei einer JVM-Sprache aus den Class-Dateien, um Java-, Kotlin- und Groovy-Projekte direkt mit einem Streich zu erfassen.
Bei der Exploration besteht die Schwierigkeit darin, automatisiert ein gut lesbares Diagramm zu erstellen. Das ist nicht trivial, aber es gibt einen entscheidenden Vorteil. Denn ein sauberes Programm hat auch einen einfachen und ruhigen Abhängigkeitsgraphen. Wenn also der Layout-Algorithmus überfordert ist, eine Stelle sauber darzustellen, liegt das ziemlich sicher daran, dass diese Stelle Potenzial hat, aufgeräumt zu werden.
Aber wir wollen ja nicht nur Diagramme, die gut aussehen, sondern eine andere Art Code zu erkunden:
- Zoomen: Vom Paket‑Überblick über Methoden bis zum Code, ohne das Werkzeug zu wechseln.
- Fokussieren: Nur relevante Teilbereiche öffnen, um kognitive Last zu senken.
- Filtern: Bestimmte Beziehungstypen sichtbar machen, um konkrete Fragen zu beantworten.
Dadurch werden Muster sichtbar, die im Code oft erst spät auffallen – und dann teuer sind.
Praktisch heißt das: Man kann in wenigen Minuten Fragen beantworten, die sonst eine halbe Stunde „Springen durch Dateien“ kosten:
- Wo ist der natürliche Einstiegspunkt in dieses Modul?
- Welche Klassen sind „Zentralen“, an denen sich alles bündelt?
- Welche Abhängigkeit erklärt, warum eine Änderung plötzlich überall Tests bricht?
- Wo endet Domänenlogik und wo beginnt Infrastruktur?
- Welche Teile kann ich isoliert verstehen, ohne das ganze System zu lesen?
6.1 Muster, die visuell „sofort“ auffallen
Einige Beispiele, die in Abhängigkeitsbildern sehr schnell ins Auge springen:
- God Classes / God Modules: Ein Knoten mit zu vielen Kanten. Ein Baustein, der „alles weiß“.
- Zyklische Abhängigkeiten: Kreise, die sich wie Knoten in einem Kabel anfühlen – oft schwer zu entwirren, sobald Features darauf aufbauen.
- Talking to Strangers: Zugriff auf Klassen, die nicht durch eine Variable oder einen Parameter mit dieser Klasse verbunden sind. Ein wichtiger Bestandteil von “Clean Code”.
- Schichtenbruch: Richtungen drehen sich um. Abhängigkeiten laufen „von innen nach außen“, obwohl es umgekehrt gedacht war.
Im Editor sieht man diese Probleme oft nicht, weil der Blick lokal ist: Datei für Datei, Klasse für Klasse. Eine Visualisierung wirkt wie eine Vogelperspektive.
6.2 Visuelles Feedback als sanfte Leitplanke
Ein interessanter Effekt ist, dass sich Architekturentscheidungen weniger wie „Regeln“ anfühlen und mehr wie „Ästhetik“:
Wenn ein Diagramm nach einer Änderung unruhiger wird, fragt man automatisch: Ist die neue Verbindung an dieser Stelle wirklich nötig? Kann eine Schnittstelle helfen? Ist das Konzept sauber geschnitten?
Umgekehrt erzeugt ein ruhigeres Bild eine Art Bestätigung: Weil es weniger unnötige Kopplung signalisiert.
Das ersetzt keine Architekturprinzipien – aber es sorgt trotzdem für sauberen Code.
7. Vom Verständnis zur Handlung: Refactoring mit weniger Risiko
Und wenn man mal Änderungen vornehmen muss, werden diese auch leichter.
- Man erkennt oft gute Stellen, um Pakete oder Klassen zu schneiden, wenn sie zu groß geworden sind. Häufig findet sich nämlich die fachliche Zugehörigkeit im Abhängigkeitsgraphen wieder.
- Man bekommt eine natürliche Reihenfolge für Änderungen an der gesamten Codebasis. Ich konnte dadurch z. B. eine Portierung von Java nach Kotlin von den “Rändern” beginnen – also immer zuerst die Pakete, die keine weiteren Abhängigkeiten zu Java mehr haben.
Ob Änderungen anschließend manuell umgesetzt werden oder mit Unterstützung von KI, ist zweitrangig. Entscheidend ist, dass vorher ein gemeinsames Verständnis entsteht. KI kann dann sehr gut innerhalb eines klaren Plans arbeiten: „Diese Abhängigkeit muss weg“, „dieser Teil wird extrahiert“, „diese Richtung ist erlaubt“.
Damit wird KI weniger zum autonomen Code‑Erzeuger und mehr zum Werkzeug, das eine bereits verstandene Architektur sauber nachzieht.
Fazit
Die Menge an Code, mit der wir täglich arbeiten, wächst – unabhängig davon, ob sie von Menschen oder von KI geschrieben wird. Architekturverständnis wird damit immer wichtiger. Der Engpass liegt immer häufiger im mentalen Modell: Was hängt wie zusammen, und welche Änderung hat welche Folgen?
Interaktive Abhängigkeitsvisualisierung liefert dafür eine praktische Antwort: eine Landkarte, die aus dem realen Code entsteht, die Exploration erlaubt und die Architektur als lebendes Feedback‑System erlebbar macht.
Die Erfahrung mit meinem Prototyp ist bisher auf jeden Fall vielversprechend und ich bin gespannt, wohin sich das noch entwickelt.