La billettique mobile des réseaux de transport
Instant System · depuis mai 2023 · en production
J'arrive dans une équipe sans aucun développeur mobile, seul sur le périmètre billettique de l'ensemble du portefeuille — pendant un an. Voici cinq chantiers, avec le problème qui les a déclenchés et ce qu'ils ont produit.
01L'authentification qui déconnectait sans raisonUn code hérité que personne ne voulait toucher — refondu avec des acteurs
Problème
Quand plusieurs requêtes recevaient une réponse « non autorisé » en même temps, chacune déclenchait son propre rafraîchissement de jeton. Les rafraîchissements concurrents s'invalidaient entre eux, et l'utilisateur se retrouvait déconnecté sans raison apparente. Le code d'authentification datait de 2019 et personne ne voulait y toucher.
Décision
J'ai pris l'initiative de la refonte, et je suis passé en async/await avec un acteur pour porter l'état d'authentification.
Pourquoi un acteur plutôt qu'un verrou : un verrou protège l'état à condition qu'on pense à le prendre partout — rien ne le vérifie, et un verrou tenu pendant une attente asynchrone est un blocage qui n'attend que son heure. Avec un acteur, l'isolation devient une propriété du type : tout accès venant de l'extérieur est nécessairement sérialisé, et l'oubli n'est plus possible.
Le cœur de la correction : la tâche de rafraîchissement en cours est mémorisée. Les requêtes concurrentes n'en lancent pas une nouvelle, elles attendent la même. Un seul rafraîchissement, quel que soit le nombre d'appels simultanés — plus une garde contre la boucle de réessais sur un même appel.
Résultat
L'authentification sur TCL est devenue nettement plus stable. Fin des déconnexions inexpliquées — celles qu'on ne reproduit jamais en test et qu'on ne voit qu'en production.
02La fraude au QR codeUne initiative en sprint d'innovation, devenue une fonctionnalité vendue
Problème
Un titre dématérialisé s'affiche en QR code. Les fraudeurs en prenaient une capture d'écran qu'ils transmettaient à des tiers — et au contrôle, rien ne distinguait la copie de l'original.
Décision
En sprint d'innovation, j'ai pris l'initiative de concevoir une bibliothèque interne qui masque le contenu de l'écran dès qu'une capture ou un enregistrement est en cours. Le titre reste lisible pour son porteur, et disparaît de tout ce qui pourrait être partagé.
Résultat
Déployée sur l'ensemble des applications, puis reprise sur le nouveau socle. Les clients en sont satisfaits — au point que c'est devenu une fonctionnalité qu'ils paient. Une idée de sprint devenue une ligne de valeur.
03Le rechargement de carte sur le réseau lyonnaisDu POC à la production, développé quasiment seul
Problème
Le réseau lyonnais attendait de pouvoir recharger une carte de transport depuis le mobile. Côté iOS, tout restait à faire : l'intégration du SDK du prestataire de billettique n'avait jamais été menée.
Décision
J'ai d'abord prouvé l'intégration par un POC — un POC ne doit pas montrer que ça marche, il doit montrer ce qui va coincer en production. Puis j'ai développé quasiment seul la fonctionnalité complète sur iOS, jusqu'à la mise en production.
Résultat
Livrée. Je suis aujourd'hui l'un des référents techniques de l'application TCL, dont je suis l'expert, et je porte le lancement du m-ticket dessus.
04Tenir la clean architecture jusqu'au boutLe produit porte le défaut, le prestataire n'override que sa différence
Problème
L'architecture d'abstraction par prestataire de billettique avait été posée par le tech lead. Mais des implémentations totalement indépendantes du prestataire vivaient quand même dans les modules prestataires — donc dupliquées autant de fois qu'il y a de fournisseurs.
Décision
J'ai créé le module d'un nouveau prestataire alors qu'il présentait peu de spécificités : le faire vivre à part aurait été plus court, mais aurait laissé un trou dans l'architecture. La cohérence de bout en bout valait la ligne de code en plus.
Et j'ai milité pour — et obtenu — la remontée au niveau du produit des implémentations indépendantes du prestataire. Les prestataires ne surchargent plus que ce qu'ils veulent réellement changer.
Résultat
Moins de duplication entre fournisseurs, et une règle claire qui tient sans arbitrage : le produit porte le comportement par défaut, le prestataire n'override que sa différence.
05Le lancement du nouveau socleOùra et la Toscane, sur tous les pans fonctionnels
Problème
Le nouveau socle produit, en clean architecture avec injection de dépendances, devait embarquer toute la billettique — sans régression par rapport à un socle éprouvé depuis des années.
Décision
Je suis intervenu sur tous les pans fonctionnels : catalogue d'achat, panier, produits à paramètres, historiques d'achat, gestion de bénéficiaires, achat pour autrui. Et j'ai écrit la bibliothèque interne de génération des QR codes à partir d'un payload encodé — la brique qui porte la validation du titre et son contrôle.
Résultat
Socle lancé sur Oùra (Auvergne-Rhône-Alpes) et sur la Toscane. J'y ai appris SwiftUI, l'injection de dépendances et cette architecture en production, sur un produit livré.




