[!NOTE] TL;DR : Gérer plusieurs clients sur une même base de code mobile est un défi majeur. Pour notre application Flutter de traçabilité industrielle, j’ai mis en place une Clean Architecture stricte découplée par Riverpod, un système de persistance asymétrique avec ObjectBox pour garantir le mode hors-ligne, et une stratégie de “forks” Git pour isoler fermement le code propriétaire de chaque client.
En environnement logistique, une application mobile ne peut pas se contenter de fonctionner : elle doit être résiliente aux pertes de réseau et hautement adaptable selon les processus métiers spécifiques de chaque usine. Dans le cadre de mon alternance, j’ai été amené à piloter le développement d’une application de traçabilité Flutter, déployée chez des clients aux contraintes radicalement opposées (un acteur aéronautique en mode Cloud, et un industriel avec infrastructure locale sur-mesure).
Clean Architecture et découplage avec Riverpod
Pour qu’un même cœur applicatif puisse s’adapter à des systèmes d’information clients diamétralement différents, l’architecture logicielle doit reposer sur des couches strictes. J’ai segmenté le projet logiquement :
data/: Les entités et contrats d’interfaces (repositories).modules/: Les fonctionnalités métiers isolées.services/¬ifiers/: L’état applicatif transversal.
Le véritable découplage s’opère via Riverpod. Les repositories sont définis par des classes abstraites, puis injectés dans nos notifiers. Cette abstraction permet de permuter dynamiquement l’implémentation sous-jacente en fonction du client. Ainsi, l’application peut basculer d’une implémentation distante via API REST à une persistance locale, sans jamais avoir à réécrire la logique de l’interface utilisateur. C’est ce même socle abstrait qui m’a d’ailleurs permis d’opérer des migrations de bases de données (de NoSQL vers relationnel) côté backend pour d’autres clients.
Sécuriser le terrain : Stratégie offline-first et ObjectBox
Dans un entrepôt, la perte d’une session d’inventaire en cours à cause d’une coupure Wi-Fi est le risque opérationnel absolu. Pour y répondre, je n’ai pas opté pour une usine à gaz de synchronisation bidirectionnelle, mais pour une approche asymétrique alliant réactivité et sécurité :
- Cache local hautes performances : Les données de référence sont stockées dans une base locale ObjectBox. L’interface lit ces données via des flux réactifs, offrant un affichage instantané sans aucune latence réseau.
- Filet de sécurité applicatif : L’état de la session de scan (tags RFID détectés) est automatiquement sauvegardé au format JSON dans les préférences partagées exactement deux secondes après la détection du dernier produit. En cas de crash, l’opérateur se voit proposer une restauration automatique de son inventaire.
- Green IT & Sécurité : Les bases locales sont chiffrées par design pour protéger les terminaux industriels durcis en cas de perte. De plus, limiter les appels réseau augmente considérablement l’autonomie des batteries sur des cycles de 8 heures.
Le défi multi-clients : L’arbitrage entre forks et flavors
Le dilemme classique du multi-clients sur Flutter : flavors ou dépôts séparés ?
Les flavors mutualisent le code au maximum, mais chaque build embarque potentiellement toutes les sources. C’était inacceptable vis-à-vis des exigences de cloisonnement et de confidentialité de nos clients industriels. J’ai donc fait le choix assumé d’une stratégie de forks Git.
J’ai géré simultanément cinq dépôts Git. À partir d’un dépôt source commun (upstream), les corrections de bugs génériques étaient redescendues, tandis que chaque fork client restait une forteresse isolée pour les développements métier spécifiques. C’est un choix pragmatique : chaque fork reste un projet Flutter standard et lisible immédiatement (un atout essentiel pour faciliter le travail collaboratif et la reprise par d’autres développeurs).
Ce que j’en retiens
L'architecture est l'art des compromis assumés
Cette mission m'a prouvé que chaque choix architectural implique une limite. L'abstraction via Riverpod a un coût d'entrée pour les nouveaux développeurs ; la stratégie des forks alourdit la synchronisation au-delà d'un certain nombre de clients. Mais en documentant et en justifiant ces choix, on passe de développeur qui subit un projet à architecte qui le pilote. Pour aller plus loin sur la méthode qui me permet de concevoir ces architectures, vous pouvez lire mon retour d'expérience sur mon workflow assisté par IA.