Files
meldestelle/docs/clients/visionen/MP-20.md
T
stefan 114236c8d9 feat(MP-27): backend consolidation, gateway routing & service dockerfiles
Summary
- Backend Services (Entries, Results, Scheduling) haben Dockerfiles.
- Docker Compose Orchestrierung steht (DB + Gateway + Services).
- Gateway Routing für `entries-service` implementiert (StripPrefix, Path Rewrites).
- Health-Checks und 409-Conflict-Demo Endpunkt verifiziert.

Verification
- `docker compose up --build` -> Success
- `curl http://localhost:8081/api/entries` -> 200 OK (routed through Gateway)

Ref: MP-27
2025-12-08 11:39:43 +01:00

189 lines
5.1 KiB
Markdown

## Frontend-Architektur
# Frontend-Architektur
**Architektur-Stil:** Feature-First, Clean Architecture, Kotlin Multiplatform (KMP)
## 1. Management Summary
Das Frontend wird als **modulare Kotlin Multiplatform (KMP) Anwendung** entwickelt. Ziel ist eine strikte Trennung von
technischer Basis (`shared`) und fachlichen Funktionen (`features`). Die Architektur ist **"Offline-Ready"** konzipiert:
Durch die konsequente Nutzung des Repository-Patterns kann die Datenquelle später transparent von "Online-Only" (API)
auf "Local-First" (Datenbank + Sync) umgestellt werden, ohne die Benutzeroberfläche (UI) anpassen zu müssen.
## 2. Die Modul-Struktur (Gradle)
Die Anwendung ist nicht monolithisch, sondern in fachliche Module geschnitten ("Feature-First").
- **`:clients:app` (Der Container)**
- **Rolle:** Der Einstiegspunkt ("Main").
- **Aufgabe:**
Initialisierung von Koin (Dependency Injection).
Globales Theming (Material3).
High-Level Navigation (Routing zwischen Features).
Verbindet alle Feature-Module.
- **`:clients:shared` (Das Fundament)**
- **Rolle:** Die gemeinsame Bibliothek für alle Features.
- **Inhalt:**
**DI (Dependency Injection):** Zentrale Koin-Module (NetworkModule, CoreModule).
**Network:** Konfigurierter HttpClient (Singleton).
**Domain Core:** Basis-Modelle (Resource<T>, ApiError, User).
**UI Kit:** Gemeinsame Komponenten (LoadingSpinner, ErrorView), Typography, Colors.
- **Regel:** Hier liegt keine Fachlogik eines spezifischen Features (keine Pferdedaten, keine Nennungen).
- **`:clients:*-feature` (Die Fachlichkeit)**
- **Beispiele:** `:clients:auth-feature`, `:clients:registry-feature`, `:clients:events-feature`.
- **Rolle:** Kapselt einen kompletten fachlichen Bereich.
- **Inhalt:** Eigene Screens, ViewModels und spezifische Use-Cases.
## 3. Die Schichten-Architektur (Innerhalb eines Moduls)
Jedes Modul (besonders `shared` und die Features) folgt einer strikten 3-Schichten-Architektur. Das garantiert
Testbarkeit und Austauschbarkeit.
### 1️⃣ Presentation Layer (UI)
- **Technologie:** Compose Multiplatform.
- **Komponenten:** `Screen` (Composable Functions) und `ViewModel` (State-Holder).
- **Verantwortung:**
Zeigt Daten an (Reagiert auf State).
Nimmt User-Input entgegen.
**Weiß NICHT**, woher die Daten kommen (Netzwerk oder DB).
Nutzt Repositories via Koin Injection (`koinInject()`).
### 2️⃣ Domain Layer (Die Logik)
- **Komponenten:** `Repository Interface`, `Models`.
- **Verantwortung:**
Definiert **WAS** getan werden kann (z.B. `checkSystemStatus()`).
Ist komplett unabhängig von Frameworks (reines Kotlin).
Nutzt `Resource<T>` Wrapper (`Success`, `Error`, `Loading`) für den State-Transport.
### 3️⃣ Data Layer (Die Umsetzung)
- **Komponenten:** `Repository Implementation`, `API-DTOs`, `Database-Entities`.
- **Verantwortung:**
Entscheidet **WIE** Daten geholt werden.
**Aktuell (Online):** Ruft Ktor Client auf.
**Zukunft (Offline/LAN):** Prüft lokale SQLite DB, synchronisiert im Hintergrund.
Mappt rohe API-Daten (DTOs) in saubere Domain-Modelle.
### 4. Technische Kern-Konzepte
**💉 Dependency Injection (Koin)**
Wir nutzen Koin als "Klebstoff".
- Module exportieren ihre Funktionalität via `val myModule = module { single { ... } }`.
- Die `clients:app` sammelt alle Module ein und startet den Container.
- **Vorteil:** Repositories und der HTTP-Client müssen nicht manuell herumgereicht werden.
**🌐 Networking (Ktor)**
Ein zentraler `HttpClient` im `NetworkModule` (`clients:shared`).
- Konfiguriert mit JSON-Serialization.
- Zentrale Base-URL Steuerung (via `AppConfig` umschaltbar für LAN/Dev/Prod).
- Timeout- und Logging-Handling an einer Stelle.
**🔄 Datenfluss (Unidirectional Data Flow)**
1. **UI:** Trigger Event (Button Click).
2. **ViewModel/Scope:** Ruft Repository auf (`launch { repo.getData() }`).
3. **Repository:** Liefert `Resource.Loading` -> `Resource.Success(data)`.
4. **UI:** Rendert den neuen State.
### 5. Strategie für Offline & LAN-Fähigkeit (Zukunft)
Die aktuelle Architektur ist **vorbereitet** für die Offline-Anforderungen der großen Turniere.
**Die Transition (Schritt-für-Schritt):**
1. **Phase 1 (Jetzt):** PingRepositoryImpl ruft direkt httpClient.get() auf.
2. **Phase 2 (Offline):**
Wir fügen **SQLDelight** (lokale DB) hinzu.
Die `PingRepositoryImpl` wird geändert (ohne dass die UI es merkt!):
```Kotlin
fun getData() {
val localData = db.dao.getAll()
if (localData.isEmpty()) {
val remote = api.getAll()
db.dao.insert(remote)
return remote
}
return localData
}
```
3. **Phase 3 (Sync):** Ein Hintergrund-Worker (`WorkManager` oder `Coroutine`) synchronisiert lokale Änderungen mit dem
Server, sobald das LAN verfügbar ist.
### 6. Zusammenfassung für Entwickler
Wenn du ein neues Feature (z.B. "Pferde anzeigen") baust:
1. **Domain:** Erstelle Horse Model und HorseRepository Interface.
2. **Data:** Erstelle HorseRepositoryImpl. Injiziere den HttpClient.
3. **DI:** Registriere das Repository im Koin-Modul.
4. **UI:** Erstelle HorseListScreen. Injiziere das Repository.
5. Fertig.
Diese Struktur ist sauber, skalierbar und bereit für den professionellen Einsatz beim OEPS. ✅