Module-first-Ansatz

Die App wird nach thematischen/geschäftlichen Domänen geschnitten, nicht nach technischen Schichten. Statt „alle Controller hier, alle Stores dort“ wird gruppiert, was zu einem Feature gehört und als Modul definiert. Module kapseln Controller, Stores, Modelle und Repositories; der zentrale Context stellt sie bereit, steuert Navigation und hält die UI schlank. Das erleichtert Erweiterungen, hält Abhängigkeiten gering und sorgt für konsistente, testbare Datenflüsse.

Idee #

  • Fachlich geschnittene Einheiten: Features werden als Module gedacht und implementiert. Jedes Modul bündelt Controller, Stores, Modelle und Repositories für seinen Fachbereich.
  • Klare Grenzen: UI konsumiert Module über den zentralen Controller, statt quer über einzelne Services zu greifen. Das erhöht Übersicht, Testbarkeit und Austauschbarkeit.

Struktur #

  • Konfiguration: Die aktive Modullandschaft ist in @configs/moduleConfig definiert. Routen stehen in @configs/routeConfig.
  • Bereitstellung: Der ContextController erzeugt und lädt Module beim App‑Start. Über den Provider providers/ContextControllerProvider.tsx stehen sie global zur Verfügung.
  • Zugriff in der UI: Screens greifen per useContextControllerProvider() auf modules zu, z. B. modules.core.controllers.authController oder zugehörige Stores/Repos.

Lebenszyklus #

  • Beim Start liest der ContextController moduleConfig, initialisiert Module (Controller, Stores, Repos) und setzt loaded, sobald alles bereit ist.
  • Der Provider gate’t das Rendering bis loaded true ist. Erst dann nutzt die UI die modularen APIs.

Navigation und Routen #

  • Routen verweisen logisch auf Module (z. B. Auth‑Bereich unter app/auth/).
  • Navigation läuft bevorzugt über den zentralen routeController (injizierte Expo‑Router‑Funktionen), der modulübergreifend Guards, Tracking und Regeln anwenden kann.

Kommunikation zwischen Modulen #

  • Inter‑Modul‑Aufrufe erfolgen über den ContextController bzw. klar definierte Controller‑APIs.
  • Stores liefern nur beobachtbaren Zustand; fachliche Abhängigkeiten werden über Controller‑Schnittstellen gekapselt, nicht über direkte Store‑Kopplung.

Vorteile #

  • Isolation: Änderungen bleiben im Modul; geringere Seiteneffekte.
  • Skalierbarkeit: Neue Features entstehen als neue Module ohne Berührung mit bestehenden.
  • Wartbarkeit: Einheitliche Orte für Logik (Controller), Zustand (Stores), Datenzugriff (Repositories).
  • Ownership: Teams können Module unabhängig warten und deployen (Backendschnittstellen via Directus bleiben stabil).

Neues Modul hinzufügen (High‑Level) #

  • 1. Konfiguration: Eintrag in @configs/moduleConfig (Name, Controller/Store/Repo‑Wiring).
  • 2. Routen: Dateien/Ordner in app/<modul>/ anlegen; falls nötig gemeinsames Layout _layout.tsx.
  • 3. Implementierung: Controller (Use‑Cases, Navigation), Stores (MobX‑State), Repositories (Directus‑Zugriff), Modelle (Typen).
  • 4. Integration: Über useContextControllerProvider() in Screens auf modules.<modul>.* zugreifen.
  • 5. Tests: Controller/Repos modular testen; UI als observer‑Komponenten gegen Mock‑Controller laufen lassen.

Kurzbeispiel Zugriff (konzeptionell) #

// In einem Screen
const { modules, routeController } = useContextControllerProvider();

await modules.core.controllers.authController.onPressLogin();
routeController.navigateToNext("(home)");

What are your feelings

Updated on Oktober 8, 2025