Architecture interne : patterns, modélisation des données et extensibilité dans Mes Recettes

Vue en couches de l’architecture Mes Recettes (Blazor + Supabase)

Architecture interne : patterns, modélisation des données et extensibilité dans Mes Recettes

Partie 2 sur 3 de la série Mes Recettes : Partie 1 – Aperçu · Partie 3 – Tests & Livraison | English

Vue en couches

Les premières itérations restent légères, mais la conception s’oriente vers une architecture « clean » pragmatique :

PagfMPeSuoSosetdDsruèKt&vrlSgieCurCcRslpeoeeiaSmscdebQpienaLo(ptssAede|auSontvmthcas,)inBela|zor

Composition des composants

App.razorMainLayout → pages (Recipes.razor, Books.razor, Authors.razor) + composants de dialogue pour le CRUD.

Avantages :

  • Style de layout partagé
  • Création/édition via dialogues (rapidité perçue)
  • Espace pour injecter plus tard des préoccupations transverses (chargement, notifications)

Stratégie de modélisation des données

Mappage direct table ↔ modèle via attributs :

ConceptTableRelation
AuteurauthorsM:N avec Books
Livrebooks1:N Recettes, M:N Auteurs
RecetterecettesFK Livre optionnelle
BookAuthorbooks_authorsTable de jonction

Diagramme simplifié :

ChaiflAmdiaUprsTsstE:t_U_nRnaammeeM:N(LlIiVaRiEs_AnU)TEURChMa:minrbNpdaaoRsmtoE:eikCn_EgiTdL1TI:EVNoRpEtionnel)

Approche de validation

  • DataAnnotations assurent cohérence UI + serveur.
  • Tests unitaires valident les bornes (ex. note).
  • Plus tard : couche FluentValidation si règles contextuelles.

Patterns documentés (durcissement futur)

PatternPourquoiQuand l’activer
RepositoryChanger de stockage, mocking aiséQuand la logique grossit
Unit of WorkGrouper transactionsSi modifications multi-entités
Décorateur de cacheRéduire lectures répétéesAprès identification des hotspots
SpecificationRequêtes complexesQuand conditions combinées répétées

Exemple : Repository (différé)

public class SupabaseRepository<T> : IRepository<T> where T : BaseModel, new()
{
    private readonly SupabaseClient _client;
    public async Task<List<T>> GetAllAsync() =>
        (await _client.From<T>().Get()).Models ?? new();
}

Non activé pour éviter l’abstraction prématurée.

Temps réel & réhydratation

Supabase Realtime est pré‑activé (AutoConnectRealtime = true). Une fois abonné :

  1. Écoute INSERT/UPDATE/DELETE
  2. Mise à jour UI optimiste
  3. Réconciliation optionnelle après refetch silencieux

Points d’extensibilité

ExtensionPoint d’ancrage
Mode hors ligneService worker / cache stockage local
RechercheFull‑text PostgreSQL + index
ThèmeService de palette MudBlazor
Journal d’auditTriggers BD → table append-only
AnalyticsBus d’événements minimal

Compromis

DécisionAvantageInconvénient
Modèle direct ↔ tableSimplicité, vitesseCouplage schéma
Service layer minimaleItération rapideInjection transverses plus difficile
Supabase BaaSAuth + Realtime + DB packagésSurface fixée par le fournisseur
100% WASMDéploiement CDN, faible coûtBundle initial plus lourd, pas de prerender

Stratégie de migration (si besoin)

  1. Ajouter un serveur (ASP.NET) pour prerender + endpoints protégés.
  2. Extraire des services métier dédiés.
  3. Ajouter un broker messages si collaboration s’intensifie.
  4. Passer progressivement du client direct aux services médiateurs.

Checklist futur

  • RLS (propriété par utilisateur)
  • Repository/cache seulement si métriques favorables
  • Flags de fonctionnalités simples
  • Suivi dérive schéma BD (diff CI)
  • Budget taille bundle (< 2 Mo compressé)

Source : https://github.com/mongeon/RecettesIndex



Suggestions de lecture :