Files
TravelMateAdmin/ARCHITECTURE.md
Van Leemput Dayron f9690045ea feat: Implement Database Service and ViewModels for Messages and Support Requests
- Added DatabaseService to handle database operations for messages and support requests.
- Created IDatabaseService interface to define the contract for database operations.
- Developed ViewModels for Dashboard, Messages, and Support pages to manage data and commands.
- Implemented XAML views for Dashboard, Messages, and Support, including data binding and UI elements.
- Created SQL script for setting up the database schema and inserting test data.
2026-01-12 18:04:10 +01:00

8.9 KiB

Architecture de TravelMate Admin

🏗️ Pattern MVVM (Model-View-ViewModel)

Cette application utilise strictement le pattern MVVM avec CommunityToolkit.Mvvm pour une séparation claire des responsabilités.

┌─────────────────────────────────────────────────────────┐
│                         VIEW                             │
│                    (XAML + Code-behind)                  │
│  DashboardPage │ MessagesPage │ SupportPage             │
└─────────────┬───────────────────────────────────────────┘
              │ Data Binding
              ▼
┌─────────────────────────────────────────────────────────┐
│                      VIEWMODEL                           │
│              (Business Logic + State)                    │
│  DashboardVM │ MessagesVM │ SupportVM                   │
└─────────────┬───────────────────────────────────────────┘
              │ Calls
              ▼
┌─────────────────────────────────────────────────────────┐
│                       SERVICE                            │
│                  (Data Access Layer)                     │
│                   DatabaseService                        │
└─────────────┬───────────────────────────────────────────┘
              │ SQL Queries
              ▼
┌─────────────────────────────────────────────────────────┐
│                    DATABASE                              │
│              MariaDB / MySQL                             │
│         messages │ support_requests                      │
└─────────────────────────────────────────────────────────┘

📂 Structure des Dossiers

/Models

Responsabilité : Représentation des données métier

  • Message.cs : Représente un message de demande
  • SupportRequest.cs : Représente une demande support

Caractéristiques :

  • POCOs (Plain Old CLR Objects)
  • Propriétés avec getters/setters
  • Propriétés calculées (FullName, StatusText, etc.)
  • Pas de logique métier

/Services

Responsabilité : Couche d'accès aux données

  • IDatabaseService.cs : Contrat du service
  • DatabaseService.cs : Implémentation avec MySqlConnector

Caractéristiques :

  • Méthodes asynchrones (Task)
  • Gestion des connexions MySQL
  • Gestion des erreurs avec try/catch
  • Logs de débogage

Méthodes principales :

Task<List<T>> GetAllAsync()
Task<List<T>> GetFilteredAsync(bool? isDone)
Task<int> GetPendingCountAsync()
Task<int> GetDoneCountAsync()
Task<bool> UpdateStatusAsync(int id, bool done)
Task<bool> TestConnectionAsync()

/ViewModels

Responsabilité : Logique de présentation et état de l'UI

  • DashboardViewModel.cs : Gestion du dashboard
  • MessagesViewModel.cs : Gestion de la liste des messages
  • SupportViewModel.cs : Gestion des demandes support

Caractéristiques :

  • Hérite de ObservableObject (CommunityToolkit.Mvvm)
  • Utilise [ObservableProperty] pour les propriétés bindables
  • Utilise [RelayCommand] pour les commandes
  • Injection de dépendance via constructeur

Exemple de propriété observable :

[ObservableProperty]
private bool isLoading;
// Génère automatiquement IsLoading avec INotifyPropertyChanged

Exemple de commande :

[RelayCommand]
public async Task LoadMessagesAsync()
{
    // Logique de chargement
}
// Génère automatiquement LoadMessagesCommand : ICommand

/Views

Responsabilité : Interface utilisateur

  • DashboardPage.xaml/.cs
  • MessagesPage.xaml/.cs
  • SupportPage.xaml/.cs

Caractéristiques :

  • XAML pour la structure UI
  • Code-behind minimal (uniquement OnAppearing)
  • Data Binding vers le ViewModel
  • Converters pour la présentation

/Converters

Responsabilité : Conversion de données pour l'affichage

  • BoolConverters.cs :
    • BoolToStatusTextConverter : bool → "Marquer comme fait"
    • BoolToColorConverter : bool → Color

/Configuration

Responsabilité : Configuration de l'application

  • AppSettings.cs : Paramètres de connexion DB

🔄 Flux de Données

1. Chargement des Données

User Opens Page
      ↓
OnAppearing() appelé
      ↓
LoadCommand.Execute()
      ↓
ViewModel appelle Service
      ↓
Service exécute requête SQL
      ↓
Données retournées au ViewModel
      ↓
ViewModel met à jour ObservableCollection
      ↓
INotifyPropertyChanged déclenché
      ↓
UI se met à jour automatiquement

2. Action Utilisateur (Changer statut)

User clique sur Button
      ↓
Command bindée exécutée
      ↓
ViewModel.ToggleStatusCommand
      ↓
Service.UpdateStatusAsync(id, !done)
      ↓
SQL UPDATE exécuté
      ↓
Success → ViewModel met à jour l'objet local
      ↓
INotifyPropertyChanged → UI refresh

🧩 Injection de Dépendances

Configuration dans MauiProgram.cs :

// Services (Singleton car un seul pour toute l'app)
builder.Services.AddSingleton<IDatabaseService, DatabaseService>();

// ViewModels
builder.Services.AddSingleton<DashboardViewModel>();  // Singleton = même instance
builder.Services.AddTransient<MessagesViewModel>();   // Transient = nouvelle instance

// Views
builder.Services.AddSingleton<DashboardPage>();
builder.Services.AddTransient<MessagesPage>();

Pourquoi Singleton vs Transient ?

  • Singleton : Dashboard (état partagé, chargé une fois)
  • Transient : Pages de liste (rafraîchies à chaque visite)

🎨 Navigation

Gestion via AppShell.xaml :

<TabBar>
    <ShellContent Title="Dashboard" Route="DashboardPage" ... />
    <ShellContent Title="Messages" Route="MessagesPage" ... />
    <ShellContent Title="Support" Route="SupportPage" ... />
</TabBar>

Navigation programmatique :

await Shell.Current.GoToAsync("//MessagesPage");

🔐 Sécurité

Actuellement :

  • Mot de passe en clair dans AppSettings.cs

Pour la Production :

  • Utiliser variables d'environnement
  • Chiffrer la chaîne de connexion
  • Utiliser Azure Key Vault ou équivalent
  • Implémenter authentification utilisateur
  • Logger les actions sensibles

📊 Performance

Optimisations actuelles :

  • Connexions fermées automatiquement (using)
  • Requêtes asynchrones (async/await)
  • Filtres côté base de données (WHERE clause)
  • Tri côté base de données (ORDER BY)

Optimisations futures possibles :

  • Pagination pour grandes listes
  • Mise en cache des données
  • Connection pooling (déjà géré par MySqlConnector)
  • Lazy loading

🧪 Testabilité

Architecture testable grâce à :

  • Interface IDatabaseService (mockable)
  • ViewModels découplés des Views
  • Injection de dépendances
  • Logique métier dans ViewModels

Exemple de test unitaire (potentiel) :

[Test]
public async Task LoadMessages_ShouldPopulateCollection()
{
    // Arrange
    var mockService = new Mock<IDatabaseService>();
    mockService.Setup(s => s.GetAllMessagesAsync())
               .ReturnsAsync(new List<Message> { /* ... */ });
    var vm = new MessagesViewModel(mockService.Object);

    // Act
    await vm.LoadMessagesCommand.ExecuteAsync(null);

    // Assert
    Assert.That(vm.Messages.Count, Is.GreaterThan(0));
}

🚀 Extensibilité

Pour ajouter une nouvelle entité :

  1. Model : Créer NewEntity.cs
  2. Service : Ajouter méthodes dans IDatabaseService et DatabaseService
  3. ViewModel : Créer NewEntityViewModel.cs
  4. View : Créer NewEntityPage.xaml/.cs
  5. DI : Enregistrer dans MauiProgram.cs
  6. Navigation : Ajouter dans AppShell.xaml

📝 Conventions de Code

  • Naming :

    • ViewModels : *ViewModel.cs
    • Pages : *Page.xaml/.cs
    • Services : *Service.cs avec interface I*Service.cs
  • Async :

    • Toujours utiliser async/await
    • Suffixe Async pour les méthodes
  • MVVM :

    • Pas de logique dans code-behind (sauf OnAppearing)
    • Tout passe par le ViewModel
    • Binding bidirectionnel quand nécessaire

Cette architecture garantit :

  • Maintenabilité
  • Testabilité
  • Séparation des responsabilités
  • Réutilisabilité
  • Extensibilité