Denke wie ein Senior-Flutter-Ingenieur im KI-Zeitalter

Denke wie ein Senior-Flutter-Ingenieur im KI-Zeitalter

Denke wie ein Senior-Flutter-Ingenieur im KI-Zeitalter

In der Flutter-Community gibt es ein Geheimnis: Wenn wir von „Systemdesign" sprechen, zeichnen die meisten Entwickler sofort Diagramme mit Load Balancern und Message Queues. Und ja, das verstehe ich – das haben uns die Vorbereitungsbücher für Interviews beigebracht. Aber der Moment, in dem man dich bittet, die *Frontend*-Systeme zu entwerfen – den Widget-Baum, den State-Fluss, die Datenschicht einer Flutter-App – da wird es plötzlich ganz ruhig im Raum.

Sache ist: Frontend-Systemdesign ist real, es ist schwierig, und genau hier werden KI-Werkzeuge dich entweder dramatisch produktiver oder gefährlich nachlässig machen. Es gibt kein Dazwischen.

Im letzten Jahr habe ich beobachtet, wie KI-Coding-Agenten Flutter-Apps in erschreckendem Tempo generieren. Ein Teil dieses Codes ist wunderschön. Die meiste davon ist ein Haufen technischer Schulden, zusammengehalten durch ein `StatefulWidget`, das drei verschiedene APIs direkt aufruft. Das ist kein Problem der Werkzeuge. Das ist ein Denkproblem.

Lass uns das beheben.

Was „Systemdesign" für Flutter wirklich bedeutet

Wenn ein Senior-Ingenieur „Entwirf eine Chat-App" hört, fängt er nicht mit `ListView.builder` an. Er fängt mit Grenzen an.

Backend-Ingenieure denken in Services, Datenbanken und Queues. Flutter-Ingenieure müssen denken in:

- **Widget-Zerlegung** – Wann wird ein 600-Zeilen-Widget zu einem Ordner mit fokussierten Widgets?
- **State-Eigentum** – Welcher State lebt im Widget-Baum, welcher in einem Controller, welcher in einem Repository?
- **Datenfluss** – Wie ist die Einbahnstraße der Daten vom Netzwerk zu den Pixeln?
- **Fehlerbehandlung** – Wo leben Wiederholungen, Fallbacks und Fehlerzustände?

Ein Senior-Flutter-Ingenieur betrachtet eine App wie eine Zwiebel. Die äußere Schicht ist der Widget-Baum (Darstellung). Die mittlere Schicht ist das State-Management (Anwendungslogik). Der Kern ist der Datenzugriff (Repositories, Services, lokaler Speicher). Die Aufgabe des Systemdesigns ist es, diese Schichten am Schmelzen miteinander zu hindern.

Die Regel, die deinen Verstand bewahrt: Widgets machen kein Business

Hier ist eine Regel, die ich jedem Mentee gebe: **Deine Widgets sollten deine Business-Logik nicht kennen, und deine Business-Logik sollte deine Widgets nicht kennen.**

Wenn ein `TextFormField` direkt ein Repository aufrufst, hast du die Grenze verletzt. Wenn dein Repository weiß, was ein `TextEditingController` ist, hast du sie in die andere Richtung verletzt. Diese Trennung macht den Code testbar, austauschbar und – im KI-Zeitalter entscheidend – sie macht es einem Agenten möglich, Code zu bearbeiten, ohne deine gesamte App sprengen zu lassen.

Wie KI das Spiel verändert

KI-Werkzeuge wie GitHub Copilot, Claude Code und Cursor haben grundlegend verändert, wie Code geschrieben wird. Ich kann nachmittags eine funktionsfähige CRUD-App aus dem Boden stoßen. Keine Übertreibung; das schaffe ich an einem Donnerstag.

Aber was ich nach Dutzenden von KI-gestützten Flutter-Projekten gelernt habe: **Agenten sind brillant darin, Code zu schreiben und furchtbar darin, architektonische Entscheidungen zu treffen.**

Gib einem Agenten einen Ordner mit einem unvollständigen Widget und klaren Anweisungen, und er wird es perfekt hinbekommen. Gib ihm einen vagen Prompt wie „Mach diese App besser", und er wird still und heimlich vierzig zusammenhanglose Entscheidungen treffen, von denen einige katastrophal falsch sind.

Genau deshalb ging das Bild des OpenClaw-Agenten, der ein Fitnessstudio-Reservierungssystem gehackt hat, viral – nicht weil der Code clever war, sondern weil dem Agenten ein *Ziel* ohne *Einschränkungen* gegeben wurde. Das ist dasselbe Muster, das ich in Flutter-Codebases sehe, bei denen Agenten ohne architektonische Leitplanken frei agieren durften.

Szenario Eins: Das KI-generierte Chaos

Letzten Monat hat einer meiner Mentees sein Projekt geöffnet und mir gezeigt, was ein Agent produziert hatte. Die Aufgabe war einfach: „Füge dem Auftragsbildschirm Offline-Unterstützung hinzu."

Was der Agent tat:

- Fügte `path_provider` und `sqflite` zur `pubspec.yaml` hinzu
- Erzeugte eine SQLite-Datenbank innerhalb des `initState` eines Widgets
- Kapselte einen Drittanbieter-HTTP-Client in eine benutzerdefinierte Klasse ohne Schnittstelle
- Speicherte gesamte JSON-Antworten in einer globalen statischen Variablen

Technisch gesehen „funktionierte" es – auf dem Happy Path. Aber die Datenbankverbindung undichte, die Cache hatte keine Invalidierungsstrategie und die UI frierte auf langsamen Geräten ein, weil die SQLite-Operationen im Haupt-Isolat liefen.

Die Lösung waren nicht bessere Prompts. Die Lösung war **besseres Systemdesign** – die Entscheidung *bevor* der Agent Code schrieb, dass Persistenz hinter einem abstrakten Repository leben würde, eine typsichere Speicherung wie [drift](https://drift.simonbinder.eu) verwenden würde und einen Stream von Zuständen bereitstellen würde, den die UI einfach nur beobachtet.

Systemdesign-Muster, die jeder Flutter-Ingenieur kennen sollte

Hier ist mein Handbuch, wenn ich gebeten werde, eine Flutter-Funktion zu entwerfen – sei es von einem Menschen, einem Agenten oder einer Kombination aus beiden.

1. Der Dreischichten-Tortengenuss (Darstellung / Anwendung / Daten)

- **Darstellungsschicht**: Widgets, Animationen, Routing. Sie konsumiert nur State und sendet Intentionen.
- **Anwendungsschicht**: State-Management (Riverpod-Provider, Bloc-Cubits, ChangeNotifiers). Sie verwandelt Intentionen in State-Änderungen.
- **Datenschicht**: Repositories, Services, lokale Datenbanken, Netzwerk-Clients. Sie kümmert sich um das chaotische Business, mit der Außenwelt zu kommunizieren.

Jede Schicht spricht nur mit der direkt darunterliegenden Schicht. Widgets berühren nie `Dio`. Repositories liefern nie `BuildContext` zurück.

Wenn du fragst „Wo gehört Formvalidierung hin?" oder „Soll ich den API-Schlüssel im Provider ablegen?" – die Antwort lautet immer „in die Schicht, die diesen Verantwortungsbereich besitzt."

2. State-Management als unidirektionaler Fluss

Es ist mir egal, welche State-Management-Bibliothek du wählst – [Riverpod](https://riverpod.dev), [Bloc](https://bloclibrary.dev) oder sogar das simple `InheritedWidget` – solange der Fluss eine Einbahnstraße ist:

```
Stream von State -> Widgets rendern -> User-Intentionen -> State-Mutationen -> Wiederholen
```

In dem Moment, in dem du Zwei-Wege-Bindungen hast, hast du Bugs. In dem Moment, in dem Widgets direkt State mutieren, hast du Bugs, die du nicht reproduzieren kannst. In dem Moment, in dem du eine globale `static var` mit User-Daten hast, steht ein Sicherheitsaudit in deiner Zukunft.

3. Error Boundaries und Graceful Degradation

Ein Senior-Ingenieur plant zuerst für das Scheitern. Jeder Bildschirm beantwortet diese Fragen:

- Was passiert, wenn die API down ist?
- Was passiert, wenn der User kein Internet hat?
- Was passiert, wenn die JSON-Struktur sich ändert?
- Was passiert, wenn die Daten null sind?

Es geht nicht darum, alles in try-catch zu packen. Es geht darum, *State-Typen* zu entwerfen, die `loading`, `loaded`, `error` und `empty` Zustände beinhalten – und dann sicherzustellen, dass jedes Widget weiß, wie man alle vier rendert. Ich verspreche dir, das ist wertvoller als jedes obscure Paket.

Der „Spec-zuerst"-Ansatz für KI-gestützte Flutter-Entwicklung

Ich habe erwähnt, dass KI-Agenten ohne Einschränkungen abschweifen. Die Lösung, die bei mir zuverlässig funktioniert, ist **spezifikationsgetriebene Entwicklung**. Schreibe die Spezifikation *bevor* der Agent mit dem Coden beginnt.

So läuft der Workflow:

1. **Schreibe ein einseitiges Architecture Decision Record (ADR)** für die Funktion. Halte es unter 500 Wörter. Füge die Widget-Baum-Struktur, die State-Management-Hooks und die Datenverträge bei.
2. **Definiere die Dateigrenzen**. Benenne die Ordner: `features/checkout/widgets/`, `features/checkout/logic/`, `features/checkout/data/`. Gib dem Agenten explizite Dateipfade vor.
3. **Weise den Agenten an, dich nach architektonischen Entscheidungen zu fragen, sie nicht zu treffen.** Dieser eine Satz verhindert 90 % der von KI verursachten architektonischen Horrorgeschichten.
4. **Überprüfe den Code des Agenten am ADR, bevor du ihn ausführst.** Code Review ist immer noch dein einzelner bester Test.

Das ist keine Bürokratie. Das stellt sicher, dass die 500 Codezeilen des Agenten an der richtigen Stelle landen. Denn die Alternative ist Refactoring – und KI-generierten Code zu refactoren ist schlimmer als menschlichen Code zu refactoren, weil *niemand* ihn mit Absicht geschrieben hat.

Szenario Zwei: Streaming-KI-Antworten (Ja, du baust eine KI-Funktion)

Du baust eine KI-Chat-Funktion. Der Agent kann in Minuten einen wunderschön animierten Streaming-Antwortbildschirm generieren. Aber tritt zurück und denke auf Systemebene:

- Wo lebt die Konversationshistorie? Im Arbeitsspeicher, lokaler Speicher, auf dem Server?
- Was passiert, wenn der HTTP-Stream mitten in der Antwort abreißt?
- Wie gehst du mit Rate-Limiting und 429er-Fehlern um?
- Wie gehst du mit unsicheren oder halluzinierten Inhalten in der UI um?

Ein Senior-Ingenieur entwirft den Streaming-State (`StreamBuilder`, buffer-gestützter State, Wiederholungslogik), bevor er ein einziges Widget schreibt. Der Agent kann den Rest ausfüllen.

Szenario Drei: Eine Offline-First To-Do-App

Erstelle eine App, mit der User im Flugzeug Aufgaben verwalten. Die Systemdesign-Frage lautet: Optimierst du für „niemals Daten verlieren" oder für „Geschwindigkeit"?

Mit einer lokal auf `drift` basierenden Datenbank, einem Repository, das mit einer REST-API synchronisiert, und einem Konnektivitäts-Provider, der den Netzwerkzustand verfolgt, bleibt das Design sauber. Der Agent schreibt die Verrohrung; der Senior-Ingenieur entwirft die *Form* der Verrohrung.

Was KI „unnötig" macht (Und was nicht)

Es gab eine Welle von Meinungsartikeln, die behaupteten, KI werde die Notwendigkeit menschlicher Entwickler beseitigen. Der Bullenfall besagt, dass sie Entwicklern mehr Autonomie gibt; der Bärenfall besagt, dass sie die Lücken aufdeckt, die Autonomie schwerer zu verbergen macht – Andy Budd hat darüber für digitales Design geschrieben, und es ist für Flutter genau wahr: KI nimmt die *Reibung* des Schreibens von Code, aber nicht die *Verantwortung*, zu wissen, was zu schreiben ist.

KI kann:

- Boilerplate-Widget-Code schneller generieren, als du tippen kannst
- Ein Design-Mockup in Sekunden in einen Widget-Baum übersetzen
- Unit-Tests für deine Repositories schreiben

KI kann nicht:

- Entscheiden, wo State lebt
- Entscheiden, welchen Trade-off es zwischen Cache-Aktualität und API-Kosten gibt
- Entscheiden, wie das Lade-Skelett aussehen soll, wenn die API langsam ist

Das sind Designdecisionen. Das ist *dein* Job, und er wird in zehn Jahren immer noch dein Job sein.

Eine schnelle Checkliste für dein nächstes Flutter-Systemdesign

Wenn dich jemand bittet, eine Flutter-App zu entwerfen – in einem Interview, in einem Designdokument oder einfach nur in deinem Kopf – geh diese Checkliste durch:

1. **Was sind die funktionalen Atome?** Teile die App in Features auf. Jedes Feature sollte unabhängig buildbar, testbar und entfernbar sein.
2. **Was sind die State-Atome?** Identifiziere für jedes Feature: Welcher State ist lokal, welcher ist geteilt und welcher wird persistiert?
3. **Wie fließen Daten herein und hinaus?** Jede Datenquelle bekommt ein Repository. Jedes Repository gibt typisierte Objekte zurück, kein rohes JSON.
4. **Was passiert, wenn es kaputtgeht?** Fehlerzustände für jeden asynchronen Aufruf. Ladezustände für jeden Stream.
5. **Wie würde ein neuer Entwickler (oder ein KI-Agent) den Code finden?** Die Ordnerstruktur sollte selbsterklärend sein.

Bleib real: Das „Gut genug"-Prinzip

Ich möchte nicht, dass du diesen Beitrag liest und denkst, deine App braucht sechs Schichten der Abstraktion, bevor du einen Login-Button hinzufügen kannst. Systemdesign handelt von *Proportion*.

Eine Zwei-Bildschirm-Utility-App braucht kein Riverpod mit Code-Generation. Sie braucht ein `StatefulWidget` und ein Repository. Eine produktionsreife E-Commerce-App braucht nicht dreißig Provider, um eine Produktliste zu rendern. Sie braucht klare Grenzen, bewusstes State-Eigentum und eine Datenschicht, die nicht in die UI leckt.

Gute Senior-Ingenieure wissen, wann sie *keine* Komplexität anwenden sollten. KI-Agenten nicht – sie generieren fröhlich ein Factory-Pattern für eine Funktion, die vierzig Zeilen lang sein könnte. Dein Job ist es, die Leitplanken zu sein.

Abschließende Gedanken

Das hier unterscheidet Junior- von Senior-Flutter-Ingenieuren im KI-Zeitalter: **Junioren bitten die KI, die App zu bauen, und versuchen dann, das, was kaputtgeht, zu fixen. Senioren entwerfen die Grenzen der App und lassen die KI dann innerhalb dieser Grenzen bauen.**

Übernimm die Dreischichten-Mentalität. Schreibe kurze Spezifikationen, bevor du Agenten loslässt. Überprüfe mit Absicht. Entwirf zuerst für das Scheitern. Und denke daran: Das System geht darum, *was du baust*, nicht um die KI, die es schreibt.

Denn ob es ein Mensch oder ein Sprachmodell ist, das den Code tippt, jemand muss immer noch entscheiden, wo der State lebt. Dieser Jemand solltest du sein.

FAQ

1. Brauche ich wirklich „Systemdesign" für Flutter? Ist das nicht eher ein Backend-Thema?
Frontend-Systemdesign ist absolut real. Es geht darum zu entscheiden, wo State lebt, wie Daten fließen und wo Grenzen zwischen Widgets, Logik und Datenschichten gesetzt werden. Backend-Design behandelt Skalierbarkeit; Frontend-Design behandelt *Komplexität*. Eine Flutter-App mit fünfzig voneinander abhängigen Widgets und ohne Grenzen ist genauso schwer zu warten wie ein Backend mit spaghettiartigen Services.

2. Wie sollte ich mich in einem Flutter-Interview dem Systemdesign nähern?
Konzentriere dich auf die Trennung von Verantwortlichkeiten. Interviewer wollen hören, wie du über Widget-Baum-Zerlegung, State-Eigentum (lokal vs. global), Datenverträge (was liefert das Repository zurück?) und Fehlerbehandlung sprichst. Werkzeuge wie Riverpod oder Bloc zu erwähnen ist gut, aber zu benennen, *wann du welche einsetzen würdest*, ist besser. Und überstürze nicht den Code – bespreche zuerst die Trade-offs.

3. Sollte ich KI-Agenten meine Flutter-Architektur von Grund auf entwerfen lassen?
Nein. Agenten sind großartig darin, innerhalb von Grenzen zu implementieren, aber sie pakken einen Datenbankaufruf in ein Widget, wenn der Prompt vage ist. Schreibe eine kurze Spezifikation – auch nur Stichpunkte – die Ordner, State-Management-Hooks und Datenverträge definiert *bevor* der Agent beginnt. Überprüfe dann die Ausgabe dagegen. Deine Spezifikation ist der wichtigste Kontrollhebel.

4. Ist Riverpod oder Bloc besser für große Flutter-Apps?
Beide sind produktionsreif; das ist eher eine Philosophie- als eine Technik-Frage. Riverpod gibt dir Kompilierzeit-Sicherheit, geschützte Provider und einen funktionaleren Stil. Bloc erzwingt ein striktes Event/State-Muster, das einfacher zu dokumentieren ist, aber auf Kosten der Weitschweifigkeit. Für große Apps, wähle nach dem Komfort deines Teams und sei dann konsequent. Eines konsequent anzuwenden schlägt mitten im Projekt das Tool zu wechseln. Lies beide Docs – [riverpod.dev](https://riverpod.dev) und [bloclibrary.dev](https://bloclibrary.dev) – und trifft die Entscheidung mit deinem Team.

Comments (0)

No comments yet. Be the first to comment!

Leave a Comment