# Client Common-UI Modul ## Überblick Das **common-ui** Modul stellt die geteilten Benutzeroberflächen-Komponenten und Geschäftslogik für die Meldestelle Client-Anwendungen bereit. Dieses Modul implementiert die Kern-"Tracer Bullet" Funktionalität unter Verwendung eines modernen MVVM-Architekturmusters und dient sowohl der Desktop- als auch der Web-Anwendung. **Hauptfunktionen:** - 🏗️ **MVVM-Architektur** - ordnungsgemäße Trennung der Belange mit ViewModel-Muster - 🌐 **Plattformübergreifend** - geteilter Code für Desktop (JVM) und Web (JavaScript) Anwendungen - 🎯 **Vier UI-Zustände** - vollständige Implementierung gemäß trace-bullet-guideline.md - 🔧 **Ressourcenverwaltung** - ordnungsgemäßer HttpClient-Lebenszyklus und Speicherverwaltung - 🧪 **Testabdeckung** - umfassende Testsuite für alle kritischen Funktionen --- ## Architektur ### Modulstruktur ``` client/common-ui/src/ ├── commonMain/kotlin/at/mocode/client/ │ ├── data/service/ │ │ ├── PingResponse.kt # Datenmodell für API-Antworten │ │ └── PingService.kt # HTTP-Service mit Ressourcenverwaltung │ └── ui/ │ ├── App.kt # Hauptanwendungskomponente │ └── viewmodel/ │ └── PingViewModel.kt # MVVM-Zustandsverwaltung └── commonTest/kotlin/at/mocode/client/ ├── data/service/ │ ├── PingResponseTest.kt # Datenmodell-Tests │ └── PingServiceTest.kt # Service-Schicht-Tests └── ui/viewmodel/ └── PingViewModelTest.kt # ViewModel- und Zustands-Tests ``` ### MVVM-Muster Implementierung **PingUiState (Sealed Class):** - `Initial` - Neutrale Nachricht, Button aktiv - `Loading` - Ladeindikator, Button deaktiviert - `Success` - Positive Antwortanzeige, Button aktiv - `Error` - Klare Fehlernachricht, Button aktiv **PingViewModel:** - Verwaltet UI-Zustandsübergänge - Behandelt Coroutine-Lebenszyklus - Ordnungsgemäße Ressourcenentsorgung **PingService:** - HTTP-Client-Verwaltung - Result-Wrapper-Muster - Ressourcen-Bereinigungsunterstützung --- ## Abhängigkeiten ### Laufzeit-Abhängigkeiten ```kotlin // Compose Multiplatform UI implementation(compose.runtime) implementation(compose.foundation) implementation(compose.material3) // Netzwerk & Serialisierung implementation(libs.ktor.client.core) implementation(libs.ktor.client.contentNegotiation) implementation(libs.ktor.client.serialization.kotlinx.json) implementation(libs.kotlinx.serialization.json) // Coroutines implementation(libs.kotlinx.coroutines.core) ``` ### Plattformspezifische Abhängigkeiten ```kotlin // JVM (Desktop) jvmMain { implementation(libs.ktor.client.cio) } // JS (Web) jsMain { implementation(libs.ktor.client.js) } ``` ### Test-Abhängigkeiten ```kotlin commonTest { implementation(libs.kotlin.test) implementation(libs.kotlinx.coroutines.test) } ``` --- ## Verwendung ### Grundlegende Integration ```kotlin @Composable fun YourApplication() { // Verwendet at.mocode.client.ui.App App(baseUrl = "https://your-api.com") } ``` ### Erweiterte Verwendung mit benutzerdefinierter Konfiguration ```kotlin // Benutzerdefinierte Service-Konfiguration // Verwendet at.mocode.client.data.service.PingService val customService = PingService( baseUrl = "https://custom-api.com", httpClient = createCustomHttpClient() ) // Benutzerdefiniertes ViewModel mit spezifischem Scope // Verwendet at.mocode.client.ui.viewmodel.PingViewModel val customViewModel = PingViewModel( pingService = customService, coroutineScope = customCoroutineScope ) ``` --- ## API-Referenz ### PingService ```kotlin class PingService( private val baseUrl: String = "http://localhost:8080", private val httpClient: HttpClient = createDefaultHttpClient() ) { suspend fun ping(): Result fun close() companion object { fun createDefaultHttpClient(): HttpClient } } ``` ### PingViewModel ```kotlin class PingViewModel( private val pingService: PingService, private val coroutineScope: CoroutineScope = CoroutineScope(Dispatchers.Main + SupervisorJob()) ) { var uiState: PingUiState by mutableStateOf(PingUiState.Initial) private set fun pingBackend() fun dispose() } ``` ### PingUiState ```kotlin sealed class PingUiState { data object Initial : PingUiState() data object Loading : PingUiState() data class Success(val response: PingResponse) : PingUiState() data class Error(val message: String) : PingUiState() } ``` --- ## Entwicklung ### Das Modul erstellen ```bash # Für alle Plattformen kompilieren ./gradlew :client:common-ui:build # Nur JVM-Kompilierung ./gradlew :client:common-ui:compileKotlinJvm # Nur JavaScript-Kompilierung ./gradlew :client:common-ui:compileKotlinJs ``` ### Tests ausführen ```bash # Alle Tests ausführen ./gradlew :client:common-ui:jvmTest # Spezifische Testklasse ausführen ./gradlew :client:common-ui:jvmTest --tests "PingViewModelTest" ``` ### Codequalität Das Modul hält hohe Codequalitätsstandards aufrecht: - **Testabdeckung**: 32 umfassende Tests über alle Schichten - **Architektur-Konformität**: 100% MVVM-Muster-Einhaltung - **Ressourcenverwaltung**: Ordnungsgemäßer Lebenszyklus und Bereinigung - **Speichersicherheit**: Keine Speicherlecks durch ordnungsgemäße Entsorgung --- ## Tests ### Testabdeckung Übersicht | Komponente | Test-Datei | Tests | Abdeckung | |-----------|-----------|-------|----------| | PingResponse | PingResponseTest.kt | 7 | Datenmodell, Serialisierung | | PingService | PingServiceTest.kt | 10 | HTTP-Service, Lebenszyklus | | PingViewModel | PingViewModelTest.kt | 8 | MVVM, Zustandsverwaltung | ### Spezifische Test-Suites ausführen ```bash # Datenschicht-Tests ./gradlew :client:common-ui:jvmTest --tests "*PingResponseTest*" # Service-Schicht-Tests ./gradlew :client:common-ui:jvmTest --tests "*PingServiceTest*" # ViewModel-Tests ./gradlew :client:common-ui:jvmTest --tests "*PingViewModelTest*" ``` --- ## Architektur-Vorteile ### 🏗️ **Moderne MVVM-Implementierung** - **Testbarkeit**: Ordnungsgemäße Dependency Injection ermöglicht umfassende Unit-Tests - **Wartbarkeit**: Klare Trennung der Belange und Single-Responsibility-Prinzip - **Skalierbarkeit**: Architektur unterstützt zukünftige Funktionserweiterungen nahtlos ### 🚀 **Laufzeit-Effizienz** - **Ressourcenverwaltung**: Ordnungsgemäße HttpClient-Bereinigung verhindert Speicherlecks - **Leistung**: Eliminierung unnötiger Operationen und Callback-Muster - **Stabilität**: Verbesserte Fehlerbehandlung und Zustandsverwaltung ### 🔧 **Entwicklererfahrung** - **Code-Klarheit**: Selbstdokumentierender Code mit Sealed Classes und klarer Benennung - **Debugging**: Einfache Zustandsverfolgung und Problemidentifikation - **Integration**: Einfaches Integrationsmuster für abhängige Module --- ## Migrations-Hinweise ### Von der vorherigen Implementierung Das Modul wurde vollständig von einem komponentenbasierten Ansatz zu MVVM refaktoriert: **Vorher (Komponentenbasiert):** - Vermischte Belange in einzelnen Dateien - Callback-basierte Zustandsverwaltung - Manuelle Ressourcenverwaltung - Speicherleck-Potenzial **Nachher (MVVM):** - Klare Trennung der Belange - Compose-Zustandsverwaltung - Automatische Ressourcenbereinigung - Speicherleck-Prävention ### Breaking Changes **Keine** - Das Refactoring behielt vollständige Rückwärtskompatibilität für abhängige Module bei. --- ## Zukünftige Entwicklung ### Empfohlene Verbesserungen 1. **Konfigurationsverwaltung** - Umgebungsspezifische Einstellungen - Konfigurationsvalidierung 2. **Fehlerbehandlung** - Spezifische Fehlertypen - Wiederholungsmechanismen für Netzwerkausfälle 3. **Monitoring-Integration** - Metriken-Sammlung - Leistungsüberwachung 4. **Internationalisierung** - Mehrsprachige Unterstützung - Sprachspezifische Formatierung --- ## Mitwirken ### Entwicklungsumgebung einrichten 1. Stellen Sie sicher, dass JDK 21 installiert ist 2. Klonen Sie das Repository 3. Führen Sie `./gradlew :client:common-ui:build` aus, um die Einrichtung zu verifizieren ### Code-Standards - Befolgen Sie Kotlin-Codierungskonventionen - Fügen Sie Tests für neue Funktionalität hinzu - Behalten Sie MVVM-Architekturmuster bei - Stellen Sie ordnungsgemäße Ressourcenverwaltung sicher ### Test-Anforderungen - Alle öffentlichen APIs müssen Tests haben - Mindestens 90% Testabdeckung für neue Features - Integrationstests für modulübergreifende Funktionalität --- ## Fehlerbehebung ### Häufige Probleme | Problem | Lösung | |-------|----------| | `HttpClient` nicht ordnungsgemäß geschlossen | Stellen Sie sicher, dass `dispose()` im ViewModel aufgerufen wird | | Zustand wird in UI nicht aktualisiert | Überprüfen Sie die Compose-Zustandsbeobachtung-Einrichtung | | Netzwerk-Timeouts | Überprüfen Sie `baseUrl`-Konfiguration und Konnektivität | | Test-Fehler auf JS-Plattform | Verwenden Sie JS-kompatible Test-Muster (keine Reflection) | ### Debug-Informationen ```bash # Abhängigkeitskonflikte überprüfen ./gradlew :client:common-ui:dependencies # Ausführliche Test-Ausgabe ./gradlew :client:common-ui:jvmTest --info # Build-Scan für detaillierte Analyse ./gradlew :client:common-ui:build --scan ``` --- **Modul-Status**: ✅ Produktionsbereit **Architektur**: ✅ MVVM-konform **Testabdeckung**: ✅ Umfassend (32 Tests) **Dokumentation**: ✅ Vollständig *Zuletzt aktualisiert: 16. August 2025*