358 lines
9.4 KiB
Markdown
358 lines
9.4 KiB
Markdown
# 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<PingResponse>
|
|
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*
|