Erfahren Sie, wie Sie generierten Code mit der Regel der langweiligen Architektur wartbar halten: klare Ordnergrenzen, konsistente Benennung und einfache Voreinstellungen, die zukünftige Nacharbeit reduzieren.

Generierter Code verändert die tägliche Arbeit. Sie bauen nicht nur Features, Sie steuern ein System, das viele Dateien schnell erzeugen kann. Die Geschwindigkeit ist real, aber kleine Inkonsistenzen potenzieren sich schnell.
Generierte Ausgaben sehen oft isoliert betrachtet gut aus. Die Kosten treten bei der zweiten oder dritten Änderung auf: Sie wissen nicht mehr, wo ein Teil hingehört, beheben dasselbe Verhalten an zwei Stellen oder meiden eine Datei, weil Sie nicht wissen, was sonst noch betroffen ist.
„Clevere“ Strukturen werden teuer, weil sie schwer vorhersehbar sind. Individuelle Muster, versteckte Magie und starke Abstraktion machen am ersten Tag Sinn. In Woche sechs verlangsamt die nächste Änderung, weil Sie den Trick erst wieder lernen müssen, bevor Sie sicher aktualisieren können. Bei KI-unterstützter Generierung kann diese Cleverness auch künftige Generationen verwirren und zu duplizierter Logik oder zusätzlichen Schichten führen.
Langweilige Architektur ist das Gegenteil: einfache Grenzen, einfache Namen und offensichtliche Voreinstellungen. Es geht nicht um Perfektion, sondern darum, ein Layout zu wählen, das ein müder Kollege (oder das zukünftige Ich) in 30 Sekunden versteht.
Ein einfaches Ziel: Mach die nächste Änderung einfach, nicht beeindruckend. Das bedeutet in der Regel einen klaren Ort für jede Art von Code (UI, API, Daten, gemeinsame Hilfsfunktionen), vorhersehbare Namen, die das beschreiben, was eine Datei tut, und möglichst wenig „Magie“ wie Auto-Wiring, versteckte Globals oder Metaprogrammierung.
Beispiel: Wenn Sie Koder.ai bitten, „Team-Einladungen“ hinzuzufügen, möchten Sie, dass die UI in den UI-Bereich kommt, eine API-Route im API-Bereich hinzugefügt wird und Einladungsdaten in der Datenebene liegen, ohne dass ein neues Verzeichnis oder Muster nur für dieses Feature erfunden wird. Diese langweilige Konsistenz hält künftige Änderungen günstig.
Generierter Code wird teuer, wenn er viele Wege bietet, dasselbe zu tun. Die Regel der langweiligen Architektur ist einfach: Mach die nächste Änderung vorhersehbar, auch wenn der erste Build weniger clever wirkt.
Sie sollten diese Fragen schnell beantworten können:
Wähle eine einfache Struktur und halte dich überall daran. Wenn ein Tool (oder ein Kollege) ein fancy Muster vorschlägt, lautet die Standardantwort „nein“, es sei denn, es nimmt wirklich Schmerz weg.
Praktische Voreinstellungen, die langfristig halten:
Stell dir vor, ein neuer Entwickler öffnet dein Repo und muss einen „Abo kündigen“-Button hinzufügen. Er sollte nicht erst eine eigene Architektur lernen müssen. Er sollte einen klaren Feature-Bereich, eine eindeutige UI-Komponente, einen einzigen API-Client-Ort und einen einzigen Datenzugriffspfad finden.
Diese Regel funktioniert besonders gut mit Vibe-Coding-Tools wie Koder.ai: Du kannst schnell generieren, aber du führst die Ausgabe jedes Mal in dieselben langweiligen Grenzen.
Generierter Code wächst oft schnell. Der sicherste Weg, ihn wartbar zu halten, ist eine langweilige Ordnerkarte, bei der jeder erraten kann, wo eine Änderung hingehört.
Eine kleine Top-Level-Struktur, die zu vielen Webapps passt:
app/ Screens, Routing und Seitenzustandcomponents/ wiederverwendbare UI-Teilefeatures/ ein Ordner pro Feature (billing, projects, settings)api/ API-Client-Code und Request-Helperserver/ Backend-Handler, Services und GeschäftslogikDas macht Grenzen offensichtlich: UI lebt in app/ und components/, API-Aufrufe in api/, und Backend-Logik in server/.
Datenzugriff sollte ebenfalls langweilig sein. Halte SQL-Abfragen und Repository-Code nahe beim Backend, nicht verteilt in UI-Dateien. In einem Go + PostgreSQL-Setup ist eine einfache Regel: HTTP-Handler rufen Services auf, Services rufen Repositories auf, Repositories sprechen mit der Datenbank.
Geteilte Typen und Utilities verdienen ein klares Zuhause, aber halte es klein. Lege Cross-Cutting-Typen in types/ ab (DTOs, Enums, gemeinsame Interfaces) und kleine Helfer in utils/ (Datumformatierung, einfache Validatoren). Wenn utils/ sich wie eine zweite App anfühlt, gehört der Code wahrscheinlich in einen Feature-Ordner.
Behandle generierte Ordner als ersetzbar.
generated/ (oder gen/) und vermeide direkte Bearbeitung.features/ oder server/, damit Regenerieren sie nicht überschreibt.Beispiel: Wenn Koder.ai einen API-Client generiert, speichere ihn unter generated/api/ und schreibe dünne Wrapper in api/, um Retries, Logging oder klarere Fehlermeldungen hinzuzufügen, ohne generierte Dateien anzufassen.
Generierter Code lässt sich leicht erzeugen und häufen. Benennung hält ihn einen Monat später lesbar.
Wähle einen Benennungsstil und mische ihn nicht:
kebab-case (user-profile-card.tsx, billing-settings)PascalCase (UserProfileCard)camelCase (getUserProfile)SCREAMING_SNAKE_CASE (MAX_RETRY_COUNT)Nenne nach Rolle, nicht danach, wie es heute arbeitet. user-repository.ts ist eine Rolle. postgres-user-repository.ts ist ein Implementierungsdetail, das sich ändern kann. Verwende Implementierungs-Suffixe nur, wenn es wirklich mehrere Implementierungen gibt.
Vermeide Schubladen wie misc, helpers oder ein riesiges utils. Wenn eine Funktion nur von einem Feature genutzt wird, halte sie nahe bei diesem Feature. Wenn sie geteilt wird, sollte der Name die Fähigkeit beschreiben (date-format.ts, money-format.ts, id-generator.ts) und das Modul klein bleiben.
Wenn Routen, Handler und Komponenten einem Muster folgen, findest du Dinge ohne Suche:
routes/users.ts mit Pfaden wie /users/:userIdhandlers/users.get.ts, handlers/users.update.tsservices/user-profile-service.tsrepositories/user-repository.tscomponents/user/UserProfileCard.tsxWenn du Koder.ai (oder einen beliebigen Generator) verwendest, gib diese Regeln im Prompt an und halte sie bei Änderungen konsistent. Der Punkt ist Vorhersehbarkeit: Wenn du den Dateinamen erraten kannst, bleiben künftige Änderungen günstig.
Generierter Code kann am ersten Tag beeindruckend und am dreißigsten Tag schmerzhaft sein. Wähle Voreinstellungen, die den Code offensichtlich machen, auch wenn er etwas repetitiv ist.
Fang damit an, Magie zu reduzieren. Überspringe dynamisches Laden, reflection-artige Tricks und Auto-Wiring, sofern kein gemessener Bedarf besteht. Diese Features verschleiern, wo Dinge herkommen, und verlangsamen Debugging und Refactoring.
Bevorzuge explizite Imports und klare Abhängigkeiten. Wenn eine Datei etwas braucht, importiere es direkt. Wenn Module verkabelt werden müssen, mach das an einer sichtbaren Stelle (z. B. eine einzige Composition-Datei). Ein Leser sollte nicht raten müssen, was zuerst läuft.
Halte Konfiguration langweilig und zentralisiert. Lege Umgebungsvariablen, Feature-Flags und app-weite Einstellungen in einem Modul mit einem Namensschema ab. Streue keine Config über zufällige Dateien, weil es gerade praktisch war.
Daumenregeln, die Teams konsistent halten:
Fehlerbehandlung ist der Punkt, an dem Cleverness am meisten schadet. Wähle ein Muster und nutze es überall: Gib strukturierte Fehler aus der Datenebene zurück, mappe sie an einem Ort auf HTTP-Antworten und übersetze sie an der UI-Grenze in benutzerfreundliche Meldungen. Wirf nicht drei verschiedene Fehlertypen abhängig von der Datei.
Wenn du eine App mit Koder.ai generierst, fordere diese Voreinstellungen von Anfang an: explizites Module-Wiring, zentralisierte Config und ein Fehlerpattern.
Klare Linien zwischen UI, API und Daten halten Änderungen lokal. Die meisten mysteriösen Bugs entstehen, wenn eine Schicht die Arbeit einer anderen macht.
Behandle die UI (oft React) als Ort zum Rendern von Bildschirmen und für UI-only Zustand: welcher Tab offen ist, Formularfehler, Lade-Indikatoren und einfaches Input-Handling.
Halte Server-Zustand getrennt: abgeholte Listen, gecachte Profile und alles, was mit dem Backend übereinstimmen muss. Wenn UI-Komponenten anfangen, Summen zu berechnen, komplex zu validieren oder Berechtigungen zu entscheiden, verteilt sich Logik über Bildschirme und Änderungen werden teuer.
Halte die API-Schicht vorhersehbar. Sie sollte HTTP-Requests in Aufrufe an die Geschäftslogik übersetzen und Ergebnisse dann in stabile Request/Response-Formen zurückgeben. Vermeide, Datenbankmodelle direkt über das Netzwerk zu senden. Stabile Antworten erlauben, intern zu refactoren, ohne die UI zu brechen.
Ein einfacher Pfad, der gut funktioniert:
Lege SQL (oder ORM-Logik) hinter eine Repository-Grenze, damit der Rest der App nicht „weiß“, wie Daten gespeichert sind. In Go + PostgreSQL bedeutet das meist Repositories wie UserRepo oder InvoiceRepo mit kleinen, klaren Methoden (GetByID, ListByAccount, Save).
Konkretes Beispiel: Rabattcodes hinzufügen. Die UI rendert ein Feld und zeigt den aktualisierten Preis. Die API akzeptiert code und gibt {total, discount} zurück. Der Service entscheidet, ob der Code gültig ist und wie Rabatte kombiniert werden. Das Repository holt und persistiert die nötigen Zeilen.
Generierte Apps können schnell „fertig“ aussehen, aber Struktur hält Änderungen günstig. Entscheide zuerst langweilige Regeln und generiere nur genug Code, um sie zu validieren.
Beginne mit einer kurzen Planungsphase. Wenn du Koder.ai verwendest, ist der Planning Mode ein guter Ort, um eine Ordnerkarte und einige Benennungsregeln zu schreiben, bevor du etwas generierst.
Dann folge dieser Reihenfolge:
ui/, api/, data/, features/) und ein paar Benennungsregeln.CONVENTIONS.md an und behandle es wie einen Vertrag. Sobald die Codebasis wächst, wird das Ändern von Namen und Ordnerstrukturen teuer.Realitätscheck: Wenn eine neue Person nicht erraten kann, wo „Kontakt bearbeiten“ hin soll, ohne zu fragen, ist die Architektur noch nicht langweilig genug.
Stell dir ein einfaches CRM vor: eine Kontaktliste-Seite und ein Kontakt-Edit-Formular. Die erste Version baust du schnell, eine Woche später müssen „Tags“ zu Kontakten hinzugefügt werden.
Behandle die App wie drei langweilige Kästen: UI, API und Daten. Jeder Kasten bekommt klare Grenzen und wörtliche Namen, damit die „Tags“-Änderung klein bleibt.
Eine saubere Struktur könnte so aussehen:
web/src/pages/ContactsPage.tsx und web/src/components/ContactForm.tsxserver/internal/http/contacts_handlers.goserver/internal/service/contacts_service.goserver/internal/repo/contacts_repo.goserver/migrations/Jetzt wird „Tags“ vorhersehbar. Aktualisiere das Schema (neue contact_tags-Tabelle oder eine tags-Spalte), dann bearbeite eine Ebene nach der anderen: Repo liest/schreibt Tags, Service validiert, Handler exponiert das Feld, UI rendert und bearbeitet es. Verstecke kein SQL in Handlern und verlagere keine Geschäftsregeln in React-Komponenten.
Wenn das Produkt später „Filter nach Tag“ verlangt, arbeitest du hauptsächlich in ContactsPage.tsx (UI-Zustand und Query-Parameter) und im HTTP-Handler (Request-Parsing), während das Repo die Abfrage übernimmt.
Für Tests und Fixtures halte die Dinge klein und nahe am Code:
server/internal/service/contacts_service_test.go für Regeln wie „Tag-Namen müssen pro Kontakt einzigartig sein“server/internal/repo/testdata/ für minimale Fixturesweb/src/components/__tests__/ContactForm.test.tsx für FormularverhaltenWenn du das mit Koder.ai generierst, gilt dieselbe Regel nach dem Export: Ordner langweilig halten, Namen wörtlich halten und Änderungen hören auf, sich wie Archäologie anzufühlen.
Generierter Code kann am ersten Tag sauber aussehen und später teuer werden. Der übliche Schuldige ist nicht „schlechter Code“, sondern Inkonsistenz.
Eine teure Gewohnheit ist, dem Generator jedes Mal eigene Struktur erfinden zu lassen. Ein Feature landet mit eigenen Ordnern, eigenem Benennungsstil und Hilfsfunktionen, und am Ende gibt es drei Wege, dasselbe zu tun. Wähle ein Muster, schreib es auf und behandle jedes neue Muster als bewusste Änderung, nicht als Standard.
Eine weitere Falle ist das Vermischen von Schichten. Wenn eine UI-Komponente mit der Datenbank spricht oder ein API-Handler SQL baut, werden kleine Änderungen riskant und betreffen die ganze App. Halte die Grenze: UI ruft API, API ruft Service, Service ruft Datenzugriff.
Zu frühes Überabstrahieren fügt ebenfalls Kosten hinzu. Ein universelles „BaseService“ oder „Repository“-Framework wirkt schick, aber frühe Abstraktionen sind Vermutungen. Wenn die Realität sich ändert, kämpfst du gegen dein eigenes Framework statt zu liefern.
Ständiges Umbenennen und Umorganisieren ist eine leisere Form von Schuld. Wenn Dateien jede Woche verschoben werden, verlieren Leute das Vertrauen in das Layout und schnelle Fixes landen an zufälligen Orten. Stabilisiere zuerst die Ordnerkarte, refactore dann in geplanten Schritten.
Zuletzt: Sei vorsichtig mit „Platform-Code“, der keinen echten Nutzer hat. Geteilte Bibliotheken und selbstgebautes Tooling lohnen sich erst bei wiederholtem, belegtem Bedarf. Bis dahin: direkte Defaults.
Wenn jemand Neues das Repo öffnet, sollte er eine Frage schnell beantworten können: „Wo füge ich das hinzu?“
Gib das Projekt einem Kollegen (oder dem zukünftigen Du) und bitte ihn, ein kleines Feature hinzuzufügen, z. B. „Feld im Signup-Formular hinzufügen“. Wenn er nicht schnell den richtigen Ort findet, erfüllt die Struktur ihre Aufgabe nicht.
Prüfe auf drei klare Zuhause:
Wenn deine Plattform es unterstützt, halte einen Rollback-Pfad bereit. Snapshots und Rollback sind besonders nützlich, wenn du mit Struktur experimentierst und einen sicheren Weg zurück brauchst.
Wartbarkeit verbessert sich am schnellsten, wenn du aufhörst, Stil zu debattieren, und ein paar Entscheidungen triffst, die bleiben.
Schreib eine kurze Menge Konventionen auf, die tägliche Unsicherheit beseitigen: Wo Dateien hingehen, wie sie heißen und wie Fehler und Config gehandhabt werden. Halte es kurz genug, um in einer Minute gelesen zu werden.
Mach dann einen Cleanup-Lauf, um die Regeln durchzusetzen, und hör auf, wöchentlich umzuräumen. Häufiges Umorganisieren macht die nächste Änderung langsamer, auch wenn der Code hübscher aussieht.
Wenn du mit Koder.ai arbeitest (koder.ai), hilft es, diese Konventionen als Startprompt zu speichern, damit jede neue Generierung in derselben Struktur landet. Das Tool kann schnell arbeiten, aber die langweiligen Grenzen halten den Code leicht änderbar.