Référence d’application. Il s’agit d’une architecture illustrative et d’une liste de contrôle du périmètre, et non d’un projet client vérifié ni d’un déploiement mesuré. Les technologies, le périmètre d’intégration et les livrables sont définis en fonction du besoin réel.
Scénario et contraintes
Un produit de services dont les flux de travail sont identiques sur iOS et Android, qu’une petite équipe doit maintenir sur les deux plateformes. Trois contraintes façonnent la conception : des réseaux mobiles peu fiables, des cycles de validation des boutiques d’applications qui ralentissent les correctifs urgents, et la nécessité de modifier les règles métier sans publier de nouvelle version.
Architecture
Couches et responsabilités
| Couche | Technologie | Responsabilités |
|---|---|---|
| Application | Flutter (Dart), organisé en couches UI / état / dépôt | Écrans et interactions. La couche dépôt est la seule à savoir si les données proviennent du réseau ou du cache local, ce qui évite de gérer le mode hors ligne dans le code de l’interface utilisateur. |
| Stockage local | SQLite (drift) + stockage sécurisé de la plateforme | Entités mises en cache, file d’attente des écritures en attente et jetons dans le stockage sécurisé plutôt que dans les préférences partagées. |
| API | Go + Gin, routes versionnées | Règles métier, validation, autorisation. Versionnée dès le premier jour, car les anciennes versions de l’application restent longtemps entre les mains des utilisateurs après leur publication. |
| Stockage | PostgreSQL | Données transactionnelles ; JSONB est utilisé pour les attributs réellement variables, plutôt que d’élargir sans cesse les tables. |
| Cache / file d’attente | Redis | Sessions, limitation du débit, clés d’idempotence et file d’attente des tâches en arrière-plan. |
| Notifications push | FCM et APNs derrière un service de notification unique | Une API interne unique pour les notifications ; les différences entre plateformes sont gérées côté serveur, et non dans l’application. |
| Administration | Panneau d’administration Vue | Gestion des utilisateurs, du contenu et des commandes, ainsi que des valeurs de configuration à distance qui modifient le comportement de l’application sans nouvelle publication. |
Modèle de données
Les tableaux ci-dessous définissent les règles dont dépend tout le reste. Une mauvaise conception à ce niveau peut transformer une démo fonctionnelle en un système impossible à faire évoluer.
Entités principales
| Entité | Champs clés, relations et règles |
|---|---|
| user / auth_identity | Un utilisateur peut posséder plusieurs identités (téléphone, Apple, Google, WeChat). Séparer l’identité de l’utilisateur permet d’ajouter ultérieurement une méthode de connexion sans migration. |
| device | Jeton push, plateforme, version de l’application et paramètres régionaux pour chaque appareil. Le ciblage des notifications et les déploiements progressifs s’appuient sur ces données. |
| order / booking | Entité métier avec une colonne d’état explicite et un journal des transitions, afin que le support puisse répondre à la question « comment cet état a-t-il été atteint ? ». |
| outbox (côté client) | Écritures locales en file d’attente, associées à un UUID généré par le client. Cet UUID devient la clé d’idempotence côté serveur, ce qui permet de réessayer sans risque après un délai d’expiration. |
| sync_cursor | Repère updated_at par utilisateur pour la synchronisation incrémentielle, afin que l’application récupère les différences au lieu de recharger des collections entières. |
| remote_config | Configuration clé-valeur par version de l’application et plateforme, permettant de modifier les règles et les indicateurs de fonctionnalité sans soumettre l’application à une boutique. |
Interfaces clés
Points de terminaison qui portent les règles métier
| Point de terminaison | Objectif et remarques sur la concurrence |
|---|---|
| POST /api/v1/auth/token | Émet un jeton d’accès de courte durée et un jeton d’actualisation renouvelé à chaque utilisation. La rotation des jetons d’actualisation limite les conséquences du vol d’un jeton sur un appareil auquel vous ne pouvez pas accéder. |
| GET /api/v1/sync?since= | Récupération incrémentielle des enregistrements modifiés depuis un curseur, avec pagination et limite, afin qu’un utilisateur de retour après plusieurs semaines hors ligne ne puisse pas déclencher une réponse sans limite. |
| POST /api/v1/orders | Accepte l’UUID du client comme clé d’idempotence ; après une expiration du délai d’attente réseau, une nouvelle tentative renvoie la commande d’origine au lieu d’en créer une autre. |
| POST /api/v1/devices | Enregistre ou actualise le jeton push, associé à l’utilisateur et à la version de l’application pour permettre des notifications ciblées et progressives. |
| GET /api/v1/config | Renvoie la configuration à distance correspondant à la version de l’application qui en fait la demande — le mécanisme qui évite de publier une nouvelle version pour modifier une règle. |
Décisions techniques
- Flutter plutôt que deux bases de code natives. Les flux de travail sont partagés et l’équipe est petite : le partage du code applicatif peut réduire la maintenance en double lorsque les flux se recoupent ; les intégrations aux plateformes, les vérifications sur les appareils et les publications nécessitent toujours un travail distinct. Lorsque les plateformes diffèrent réellement — paiement, notifications push, biométrie — la différence est isolée derrière un canal de plateforme plutôt que de la laisser se propager dans le code partagé.
- Tolérance au mode hors ligne, sans en faire le mode prioritaire. Les lectures sont mises en cache et les écritures placées dans une file d’attente, mais le serveur reste la source de référence. Une approche entièrement hors ligne avec résolution des conflits coûte nettement plus cher et ne se justifie que si les utilisateurs travaillent réellement hors connexion pendant de longues périodes.
- UUID générés par le client comme clés d’idempotence. Les réseaux mobiles interrompent régulièrement les requêtes par expiration du délai. Sans cette mesure, les nouvelles tentatives après expiration peuvent créer un risque de commandes en double qu’il faut tester.
- API versionnée dès la première publication. Les utilisateurs reportent les mises à jour ; le serveur doit donc continuer à prendre en charge les anciennes versions. Ajouter la gestion des versions après le lancement coûte bien plus cher que de la prévoir dès le départ.
- Configuration à distance pour les règles métier. Les publications côté client dépendent de la validation des plateformes et de l’adoption par les utilisateurs. Les seuils pris en charge, les textes et les indicateurs de fonctionnalité peuvent être gérés côté serveur lorsque les règles des plateformes le permettent ; les modifications nécessitant une nouvelle version de l’application restent soumises à cette dépendance.
Objectifs de conception hypothétiques
Les chiffres ci-dessous sont des exemples hypothétiques de planification des capacités, et non des résultats client mesurés, des recommandations de dimensionnement validées ou un SLA. Définissez des objectifs d’acceptation propres au projet après avoir précisé la charge de travail, les appareils, les données, le matériel et les dépendances tierces ; vérifiez-les au moyen d’un pilote et de tests de charge avant de vous engager sur un objectif de production.
Objectifs de capacité et de performance
| Objectif | Valeur et hypothèse |
|---|---|
| Démarrage à froid jusqu’au premier écran utile | Moins de 2 secondes sur un appareil Android de milieu de gamme, en supposant que les données mises en cache s’affichent pendant que l’actualisation réseau se déroule en arrière-plan. |
| Synchronisation incrémentielle | Charge utile différentielle inférieure à 200 Ko pour un utilisateur de retour typique, avec une taille de page plafonnée afin qu’un utilisateur absent depuis longtemps bénéficie d’une dégradation progressive plutôt que d’une expiration du délai. |
| Latence de l’API | p95 inférieur à 300 ms pour les lectures standard, hors appels à des services tiers dont nous ne maîtrisons pas la latence. |
| Livraison des notifications push | Définir et mesurer les délais de mise en file d’attente côté application et d’accusé de réception du fournisseur. Le délai de livraison final dépend de la plateforme et n’est pas garanti par cette référence. |
Éléments inclus dans la livraison
- Code source de l’application Flutter, du backend Go et de l’interface d’administration Vue dans votre dépôt
- Configuration de compilation et de signature pour les deux plateformes, ainsi que préparation des fiches des boutiques
- Documentation de l’API, schéma de base de données et historique des migrations
- Notes de déploiement, accès à la surveillance et aux journaux, procédure de sauvegarde et de restauration
- Assistance à la soumission sur l’App Store et Google Play ; la décision et les délais de validation relèvent d’Apple et de Google
Préparer ce projet pour votre entreprise
Les modules ci-dessus constituent un point de départ, et non un forfait fixe. Nous limitons généralement la première version à un flux de travail métier principal et à un flux de travail administratif précis, puis nous l’étendons lorsque l’utilisation réelle met en évidence la charge et les cas limites. Envoyez-nous un brief délimité et nous le comparerons à cette architecture pour vous indiquer les éléments dont vous n’avez pas encore besoin.

