Portrait de Patrice GADEGBEPatrice GADEGBE

Paquets Flutter

Trois paquets Flutter privés regroupent ce que mes applications avaient en commun : un état de bloc générique et quelques widgets, l’écran et la session de connexion, les réglages de thème et de langue.

Rôle
Auteur unique
Période
Juillet 2025, avec une retouche en janvier 2026
État
En service. Employés par deux applications, Tontini et Soccercup
Technologies
Flutter, Dart, flutter_bloc, hydrated_bloc, dio, retrofit
Dépôts
Trois
Dépendances des paquets Flutter partagésLes applications Tontini et Soccercup dépendent des paquets de réglages et de connexion, qui dépendent eux-mêmes du paquet de base.ApplicationsTontiniSoccercupcofinger_settingsthème, langue, profilcofinger_loginécran, session, jetoncofinger_coreétat de bloc, messageswidgets de formulairedépend dedépend de
Figure 1. Dépendances entre les applications et les trois paquets. Les réglages s’appuient aussi sur la connexion, dont ils lisent la session.

Contexte

Tontini et Soccercup ont été développées la même année sur le même gabarit, et elles répétaient l’une et l’autre la même connexion, les mêmes réglages et la même façon de représenter l’état d’un écran. Les trois paquets sont nés en juillet 2025 de l’extraction de ce code commun, et non d’une conception préalable.

Problème

Chaque cubit redéclarait ses états de chargement, de succès et d’échec, et une correction apportée à l’écran de connexion d’une application devait être reportée à la main dans l’autre. Il fallait par ailleurs que le code partagé n’impose pas son apparence, les deux applications ayant chacune leurs couleurs.

Réponse apportée

Une extraction depuis deux applications en service

Le lendemain de la création des paquets, Tontini a supprimé son propre état de bloc, ses cubits de connexion et plusieurs widgets, soit 1 665 lignes retirées ; Soccercup a suivi dix jours plus tard, avec 1 240 lignes retirées. Les paquets ne contiennent donc que du code qui avait déjà servi.

Une seule forme d’état pour tous les écrans

L’état générique porte un type, à savoir inactif, en chargement, chargé, vide ou en échec, et une donnée facultative pour chacun. Un alias en masque les quatre paramètres de type que la plupart des écrans n’utilisent pas, et c’est la pièce la plus réemployée : elle apparaît 131 fois dans Soccercup et 45 fois dans Tontini.

typedef SimpleBlocState<T> = BlocState<T, void, void, void, dynamic>;

class BlocState<T, Tidle, Tloading, Tempty, Tfailure> extends Equatable {
  const BlocState({
    required this.type,
    this.loadingData,
    this.loadedData,
    this.idleData,
    this.emptyData,
    this.failureData,
  });
Extrait 1. L’état de bloc générique et l’alias qui le rend court à écrire.

Une connexion greffée sur le client de l’hôte

L’application hôte transmet son propre client HTTP au paquet de connexion, qui y ajoute un intercepteur : celui-ci joint le jeton à chaque requête et déconnecte l’utilisateur lorsque le serveur répond qu’il n’est plus autorisé. Le thème et la langue sont de leur côté un état persisté, que l’application applique elle-même à son interface ; les widgets partagés lisent les couleurs du thème en cours, de sorte que chaque application conserve son identité. Les messages destinés à l’utilisateur passent enfin par un bus unique, qu’un seul composant se charge d’afficher.

Limites et perspectives

Les applications référencent les paquets par leur chemin sur le disque et non par une version, ce qui accélère le travail à travers trois dépôts mais laisse passer les changements incompatibles sans numéro ni avertissement, et oblige à cloner chaque application à côté des paquets. Les tests se réduisent au gabarit d’origine.

La connexion fixe par ailleurs le contrat du serveur, à savoir quatre chemins et un schéma de jeton, et ne convient donc qu’aux API qui l’exposent à l’identique ; l’intercepteur suppose en outre que l’hôte ait enregistré la session sous une forme précise, ce qu’aucune documentation n’indique. La réutilisation se limite enfin à deux applications, et le chantier Flutter de Sanu, plus récent, ne s’appuie pas sur ces paquets.

Retour aux autres projets