17 KiB
Architecture de la solution Omika
Ce document décrit la structure initiale de la solution .NET Omika, son organisation en projets, les dépendances entre eux, et les conventions retenues pour la suite (migration HFSQL, application mobile, API, futur Windows).
Portée : phase d'architecture. Les modèles métier détaillés et la connexion HFSQL réelle ne sont pas encore développés (voir les sections dédiées).
1. Vue d'ensemble
┌────────────────────────────────────────────────────────────┐
│ Omika.App │
│ Application Avalonia (code partagé UI / ViewModels) │
│ Cibles : Android · iOS · Windows (desktop) │
└───────────────┬─────────────────────────────┬──────────────┘
│ │
▼ ▼
Omika.App.Desktop Omika.App.Android
Omika.App.iOS (hôtes plateformes)
(hôtes plateformes)
│
│ ProjectReference
▼
┌─────────────────────────────────────────────┐ ┌──────────────────────────────┐
│ Omika.Core │ │ Omika.Api │
│ Modèles · Interfaces · Constantes · │◄───────│ API ASP.NET Core │
│ Logique métier (indépendant UI/API) │ │ Endpoints / DI / OpenAPI │
└──────────────────┬──────────────────────────┘ └──────────────┬───────────────┘
│ ProjectReference │ ProjectReference
▼ ▼
┌─────────────────────────────────────────────┐ ┌──────────────────────────────┐
│ Omika.Data │ │ Omika.Tests │
│ Connexion HFSQL · Repositories · Mapping │ │ Tests unitaires (xUnit) │
│ Migration Batik/OMIKA │ └──────────────────────────────┘
└─────────────────────────────────────────────┘
2. Projets créés
| Projet | Type | Rôle |
|---|---|---|
Omika.App |
Bibliothèque Avalonia (net10.0) | Code UI partagé (Views, ViewModels, Services). Cible commune aux hôtes Android / iOS / Windows. |
Omika.App.Desktop |
Exécutable Avalonia (net10.0) | Hôte desktop Windows/Linux/macOS. Point d'entrée pour le futur client Windows. |
Omika.App.Android |
Exécutable Avalonia (net10.0-android) | Hôte Android (APK/AAB). |
Omika.App.iOS |
Exécutable Avalonia (net10.0-ios) | Hôte iOS (simulateur/appareil). La compilation d'un .app pour iOS exige macOS + Xcode. |
Omika.Api |
API ASP.NET Core (net10.0) | Expose les fonctionnalités métier et données via HTTP + OpenAPI. |
Omika.Core |
Bibliothèque (net10.0) | Modèles communs, interfaces, constantes, types partagés, logique métier. Aucune dépendance UI/API. |
Omika.Data |
Bibliothèque (net10.0) | Accès aux données HFSQL : options de connexion, contrats, repositories, mapping de tables, migration Batik/OMIKA. |
Omika.Tests |
xUnit (net10.0) | Tests unitaires des éléments critiques (Result, validation HFSQL, mapping de tables). |
3. Dépendances entre projets
Omika.App.Desktop ──► Omika.App ──► Omika.Core
Omika.App.Android ──► Omika.App ──► Omika.Core
Omika.App.iOS ──► Omika.App ──► Omika.Core
Omika.Api ──► Omika.Core
──► Omika.Data
Omika.Data ──► Omika.Core
Omika.Tests ──► Omika.Core
──► Omika.Data
- Omika.Core n'a aucune dépendance : c'est le noyau partagé.
- Omika.Data dépend de Omika.Core (interfaces, constantes, types).
- Omika.Api dépend de Omika.Core et Omika.Data.
- Omika.App et ses hôtes dépendent de Omika.Core (les appels à l'API se feront via HTTP, pas par référence directe au projet Data).
- Omika.Tests référence Omika.Core et Omika.Data.
4. Gestion des packages
Le fichier racine Directory.Packages.props active la gestion centralisée
des packages (CPM). Toutes les versions NuGet y sont déclarées une seule fois ;
les fichiers .csproj référencent les packages sans version.
| Groupe | Package |
|---|---|
| Avalonia | Avalonia, Avalonia.Themes.Fluent, Avalonia.Fonts.Inter, Avalonia.Desktop, Avalonia.Android, Avalonia.iOS |
| Diagnostique | AvaloniaUI.DiagnosticsSupport |
| Android | Xamarin.AndroidX.Core.SplashScreen |
| MVVM | CommunityToolkit.Mvvm |
| API | Microsoft.AspNetCore.OpenApi |
| Configuration | Microsoft.Extensions.Options.ConfigurationExtensions |
| Tests | xunit, xunit.runner.visualstudio, Microsoft.NET.Test.Sdk, coverlet.collector |
5. Structure des dossiers
Omika.slnx → solution (format .slnx)
Directory.Packages.props → versions centralisées des packages NuGet
docs/architecture-solution.md → ce document
docs/schema-compatibilite-batik-omika.json
→ dictionnaire machine-readable du schéma (tables, rubriques, liens)
analyse-sources.md → analyse WINDEV existante
BATIK.md / OMIKA.md → documentation historique
tools/generate_models.py → générateur des modèles physiques HFSQL (Batik/Omika)
src/
Omika.Core/
Constants/ → constantes applicatives et base de données
Interfaces/ → contrats (IRepository, IUnitOfWork)
Abstractions/ → types partagés (Result)
Runtime/ → version active de la base (BATIK/OMIKA), contexte global
Models/ → (vide pour l'instant) futurs modèles métier
Omika.Data/
Configuration/ → HfsqlOptions + validation
Connection/ → contrats et squelette de connexion HFSQL
Repositories/ → base commune des repositories
Mapping/ → référentiel de tables + mapping Batik/OMIKA
HfSql/Metadata/ → attributs de mapping HFSQL (Table, Column, PrimaryKey, CompositeKey, LegacyField)
HfSql/Models/ → modèles physiques générés (Batik/ et Omika/) — 106 classes
Migrations/ → service de migration Batik → OMIKA
Omika.Api/
Endpoints/ → endpoints HTTP (santé, futur métier)
Omika.App/
Views/ → MainWindow (desktop) et MainView (partagé)
ViewModels/ → MainViewModel, ViewModelBase
Omika.App.Desktop/
Omika.App.Android/
Omika.App.iOS/
tests/
Omika.Tests/ → tests xUnit (47 tests)
6. Conventions et règles
- Séparation des responsabilités : l'UI (App) et l'API ne contiennent aucune logique métier ; celle-ci vit dans Omika.Core.
- Accès aux données : uniquement via Omika.Data, derrière les interfaces
IRepository<TEntity,TId>etIUnitOfWorkdéfinies dans Omika.Core. - Pas de dépendance directe App → Data : l'application mobile consommera l'API (HTTP). Si un accès direct est nécessaire (hors ligne), il passera par une façade dédiée à ajouter ultérieurement.
- Configuration : les options de connexion HFSQL sont typées
(
HfsqlOptions, section"Hfsql"), validées avant usage, et remplaçables par la configuration .NET standard (appsettings / user-secrets / variables d'environnement). - Résultats d'opération : les services renvoient
Result/Result<T>(Omika.Core) plutôt que de lever des exceptions pour les cas métier.
7. État de la couche HFSQL (phase d'architecture)
À ce stade, aucune connexion HFSQL réelle n'est ouverte. La couche fournit :
HfsqlOptionsetHfsqlOptionsValidator: préparation et validation des paramètres (serveur, port 4900, base, groupes de protection ProtectionStd / ProtectionPlus, comptes techniques) ;IHfsqlConnection/HfsqlConnection: contrat + implémentation squelette (OpenAsynclève volontairementNotImplementedException) ;RepositoryBase<TEntity,TId>: base commune prête à câbler le provider HFSQL ;LegacyTableMap: référentiel des 58 tables OMIKA et des tables de l'ancienne version (48 tables, e.g.Intervention_Collaborateursupprimée) ;TableAttribute: association future entité → table HFSQL ;IMigrationService/MigrationService: contrat de compatibilité Batik → OMIKA (conversion de clés numériques vers textuelles, suivi ElementModifie / ElementSupprime), non implémenté.
7.1 Modèles physiques générés (Batik / Omika)
Le dictionnaire machine-readable docs/schema-compatibilite-batik-omika.json
décrit le schéma WINDEV (tables, rubriques, types HFSQL, liens, marquage zombie).
Le générateur tools/generate_models.py produit à partir de ce fichier les
106 modèles physiques dans Omika.Data/HfSql/Models :
| Dossier | Contenu |
|---|---|
HfSql/Models/Batik/ |
Modèles physiques de l'ancienne base (Isis_BO, 48 tables) |
HfSql/Models/Omika/ |
Modèles physiques de la nouvelle base (OMIKA, 58 tables) |
Chaque classe XxxRow porte les attributs de mapping suivants :
[HfSqlTable]: nom de la table, nom du fichier disque (.fic), groupes de protection, versions de schéma concernées (Batik et/ou Omika) ;[HfSqlColumn]: nom physique de la rubrique, type HFSQL, longueur, valeur par défaut, marquage « zombie » ou « Omika uniquement » ;[HfSqlPrimaryKey]/[HfSqlCompositeKey]: clé primaire (automatique ou composée) ;[HfSqlLegacyField]: rubrique historique à migrer, avec éventuellement la rubrique de remplacement (ReplacementColumn).
Ces modèles sont purement descriptifs (attributs) : aucune requête n'est exécutée. Ils constituent le socle du futur provider HFSQL et du mapping table → entité.
Pour régénérer les modèles après modification du dictionnaire :
python .\tools\generate_models.py
Prochaine étape HFSQL : choisir et brancher le provider HFSQL (.NET), puis définir les entités du domaine en s'appuyant sur ces modèles physiques.
8. Sélection de base (BATIK / OMIKA)
Le mécanisme de sélection de la base est centralisé dans Omika.Core.Runtime
et Omika.Core.Compatibility, en distinguant deux notions :
DatabaseSchemaSelection(Omika.Core.Runtime) — enum de la sélection demandée par la configuration :Auto(0) : détection automatique de la base réelle (valeur par défaut sûre) ;Batik(1) : forcer l'ancienne base ;Omika(2) : forcer la nouvelle base.
DatabaseSchemaVersion(Omika.Core.Compatibility) — enum de la provenance / version réellement détectée d'une donnée :Unknown(0) : état non déterminé ;Batik(1) : ancienne version ;Omika(2) : nouvelle version. Ce type ne doit pas être confondu avecDatabaseSchemaSelection: l'un décrit la sélection demandée au démarrage (configuration), l'autre la version réellement détectée du schéma dont provient une donnée.
DatabaseSchemaSelectionParser— analyse une chaîne de configuration (« Auto », « Batik » ou « Omika », insensible à la casse et aux espaces). Il retourne unResult<DatabaseSchemaSelection>et refuse toute valeur inconnue avec un message d'erreur explicite.ApplicationRuntimeContext— contexte global de l'application :ConfigurationKey: clé conventionnelle"Omika:DatabaseVersion";Configure(...): définit la sélection demandée au démarrage (accepte l'enum ou une chaîne de configuration) ;SetDetectedVersion(...): fournit la version réellement détectée (Batik / Omika) et la valide contre la sélection demandée ;ValidateDetectedVersion(...): valide une version détectée sans modifier le contexte global ;Current: accès au contexte actif (propriétésSelection,DetectedVersion,IsBatik,IsOmika) ;FromConfiguration(...): crée un contexte isolé sans toucher au global (utile pour les tests et les traitements par lot) ;Reset(): réinitialise le contexte global.
Sélection demandée ≠ version active
Une valeur de configuration n'est jamais présentée comme version réellement
active : seule la base détectée et validée (DetectedVersion) détermine la
base utilisée. Tant que SetDetectedVersion n'a pas été appelé, la version
détectée reste Unknown, même si une sélection forcée (Batik / Omika) est
configurée.
Comment changer la sélection demandée ?
| Méthode | Exemple |
|---|---|
| Fichier de configuration (recommandé pour l'API) | Modifier la clé "Omika:DatabaseVersion" dans appsettings.json (valeur "Auto", "Batik" ou "Omika") |
| Variable d'environnement | Omika__DatabaseVersion=Batik (la convention .NET __ est lue automatiquement) |
| Au démarrage du code | ApplicationRuntimeContext.Configure(DatabaseSchemaSelection.Batik) ou Configure("Auto") |
Une valeur inconnue lève une erreur explicite au démarrage. En mode Auto,
toute version réelle détectée (Batik ou Omika) est acceptée. En mode forcé, la
version détectée doit correspondre à la sélection demandée ; dans le cas
contraire, SetDetectedVersion retourne un échec explicite et aucune version
active n'est affirmée (la version détectée reste Unknown).
9. État des modèles métier
Les modèles physiques HFSQL (rubriques brutes du schéma WINDEV) vivent dans
Omika.Data/HfSql/Models (voir § 7.1). Omika.Core/Models, qui accueillera les
entités du domaine, est volontairement vide. La prochaine phase devra :
- s'appuyer sur l'inventaire machine-readable du schéma (déjà produit) et sur les modèles physiques pour définir les entités du domaine (Client, Dossier, Intervention, RDV, …) ;
- distinguer les propriétés utiles au domaine des rubriques « zombie » (conservées pour la lecture d'une base existante, à ne pas utiliser comme référence dans le nouveau domaine) ;
- définir les DTO exposés par l'API et consommés par l'application.
10. Commandes utiles
# Restaurer les packages
dotnet restore .\Omika.slnx
# Compiler toute la solution (hôtes desktop + API + bibliothèques + tests)
dotnet build .\Omika.slnx
# Compiler uniquement l'API
dotnet build .\src\Omika.Api\Omika.Api.csproj
# Compiler le client desktop (Windows)
dotnet build .\src\Omika.App.Desktop\Omika.App.Desktop.csproj
# Compiler l'hôte Android (APK)
dotnet build .\src\Omika.App.Android\Omika.App.Android.csproj
# Compiler l'hôte iOS (simulateur) — nécessite macOS + Xcode
dotnet build .\src\Omika.App.iOS\Omika.App.iOS.csproj
# Lancer les tests unitaires
dotnet test .\tests\Omika.Tests\Omika.Tests.csproj
# Lancer l'API en développement
dotnet run --project .\src\Omika.Api\Omika.Api.csproj
# → http://localhost:5xxx/health (état de la solution)
# Lancer le client desktop
dotnet run --project .\src\Omika.App.Desktop\Omika.App.Desktop.csproj
11. Prochaines étapes
- Choisir et intégrer le provider HFSQL (.NET) dans
Omika.Data. - Enrichir le dictionnaire
docs/schema-compatibilite-batik-omika.json(liens, règles de migration) et régénérer les modèles physiques. - Définir les entités métier dans
Omika.Core/Models. - Implémenter les endpoints métier de
Omika.Api. - Brancher l'application Avalonia sur l'API (client HTTP) et préparer la navigation mobile.
- Ajouter un projet
Omika.App.Windowssi un client Windows dédié est requis (le desktop actuel en tient déjà lieu).