D’abord maintenir. Longtemps. Puis réécrire — quand c’est le bon moment.
L’histoire de chocobonplan illustre notre philosophie mieux que n’importe quel discours. On ne débarque pas avec un devis de refonte. On commence par comprendre, maintenir, consolider. Et si un jour la réécriture devient pertinente, c’est le client qui la demande — parce qu’il nous fait confiance depuis des années.
chocobonplan, c’est le leader français des bons plans en ligne. Des centaines de milliers d’utilisateurs par jour. Des pics massifs pendant le Black Friday, les soldes, les French Days. L’application mobile est leur canal principal.
On a travaillé avec eux pendant plusieurs années en maintenance avant de parler de réécriture. Et c’est exactement comme ça que ça devrait se passer.
Phase 1 : la maintenance qui construit la confiance
Quand on a commencé à travailler avec chocobonplan, l’application fonctionnait. Elle avait des problèmes — comme toute app de plusieurs années — mais elle rendait service à des centaines de milliers d’utilisateurs.
Notre rôle pendant cette phase :
- Corrections de bugs en continu, avec priorisation par impact business
- Mises à jour de sécurité et montées de version des dépendances
- Monitoring pour anticiper les incidents avant qu’ils n’arrivent
- Documentation progressive du code existant
- Petites améliorations régulières — sans jamais déstabiliser l’ensemble
C’est ce que Michael Feathers appelle dans Working Effectively with Legacy Code le travail de “caractérisation” : comprendre intimement comment le système fonctionne avant de prétendre le changer. On ne peut pas réparer ce qu’on ne comprend pas.
Pendant cette phase, la confiance s’est construite. L’équipe chocobonplan savait qu’on connaissait leur code, leurs contraintes, leurs pics de charge. Quand ils ont eu besoin de passer à l’étape suivante, on était les interlocuteurs naturels.
Phase 2 : le moment où la réécriture devient pertinente
Après des années de maintenance et de consolidation, chocobonplan voulait franchir un cap. Pas juste “corriger des bugs” — mais une mise à jour majeure pour tenir la charge croissante et débloquer de nouvelles fonctionnalités.
Le diagnostic : quand la dette technique devient irremboursable
3 problemes critiques identifies
1. Performances degradees sous charge — au pire moment. L’application React Native existante ralentissait significativement pendant les pics de trafic. Pile au moment ou les utilisateurs avaient le plus besoin d’elle. Le Black Friday, c’est le Super Bowl du e-commerce : si votre app rame, vos utilisateurs partent chez la concurrence — instantanement, sans regret.
2. Le cercle vicieux des bugs. Les corrections creaient de nouvelles regressions. L’equipe passait plus de temps a reparer qu’a construire. C’est ce que Michael Feathers decrit dans Working Effectively with Legacy Code comme le “legacy code trap” : chaque correction est un pari, chaque pari a des effets de bord imprevisibles, et la confiance de l’equipe s’effondre.
Concretement, un bug corrige dans le module d’affichage des deals cassait le systeme de notifications. Une optimisation de performance sur une page degradait le temps de chargement d’une autre. Les developpeurs avaient peur de toucher au code — et quand les developpeurs ont peur, le produit stagne.
3. Notifications push via un service tiers qui saturait pendant le Black Friday. Les notifications push sont le canal de conversion le plus important pour une app de bons plans. Un deal flash a 50% de reduction ? La notification push convertit 10x plus que n’importe quel autre canal. Et ce canal devenait muet au pire moment de l’annee — quand le service tiers intermediaire saturait sous la charge.
Pourquoi la reprise n’etait plus une option
On a evalue serieusement la reprise progressive. C’est toujours notre premiere option. Mais trois facteurs rendaient la reecriture plus pertinente :
Le cout de la stabilisation depassait celui de la reconstruction. Stabiliser l’application existante aurait pris 4 a 6 mois de travail — avec un resultat incertain, puisque l’architecture fondamentale n’etait pas concue pour la charge actuelle.
L’architecture ne supportait pas les besoins futurs. Il ne s’agissait pas de corriger des bugs — il s’agissait de construire une fondation qui tiendrait les 3 a 5 prochaines annees de croissance. L’architecture existante avait ete concue pour 50 000 utilisateurs, pas 300 000.
Le cout de l’inaction etait mesurable. Chaque Black Friday rate, c’est du chiffre d’affaires qui part chez la concurrence. Chaque notification push non delivree, c’est un deal non converti. On pouvait mettre des chiffres sur la perte — et ces chiffres justifiaient l’investissement dans une reconstruction.
C’est la regle que Kent Beck pose : d’abord faites que ca marche, ensuite faites que ce soit bien. Quand meme “faire que ca marche” devient un pari quotidien, l’existant a atteint son terme.
La regle d’or : ne jamais couper l’ancien systeme
Martin Fowler decrit le Strangler Fig Pattern comme la methode de reference pour remplacer un systeme existant sans interruption. Le principe : le nouveau systeme grandit autour de l’ancien, comme un figuier etrangleur autour d’un arbre. L’ancien systeme continue de fonctionner tant que le nouveau n’est pas pret. Pas de big bang. Pas de “on coupe le lundi matin et on prie.”
C’est exactement l’approche qu’on a suivie pour chocobonplan. Et c’est ce qui a fait la difference entre une reecriture reussie et une reecriture catastrophique.
Phase 1 — Construction en parallele
L’ancienne application a continue de tourner en production pendant toute la reconstruction. Les utilisateurs ne savaient pas qu’une nouvelle version etait en cours. L’equipe de developpement travaillait sur deux fronts : maintenance minimale de l’ancien systeme (corrections de bugs critiques uniquement) et construction du nouveau.
L’architecture de la nouvelle application :
- React Native modernise — derniere version du framework, architecture optimisee pour la performance
- State management repense — Rematch pour une gestion d’etat previsible, testable, et performante
- Notifications push directes via FCM (Firebase Cloud Messaging) — plus d’intermediaire. Le lien entre l’app et les serveurs de notification est direct, sans point de saturation tiers
- Architecture modulaire — chaque fonctionnalite est un module independant, testable et deployable separement
- Cache intelligent — les deals charges une fois sont disponibles hors connexion, ce qui reduit la charge serveur et ameliore l’experience utilisateur
Phase 2 — Migration graduelle des utilisateurs
Pas de bascule brutale. On a migre par vagues, en mesurant chaque etape :
Vague 1 (5% des utilisateurs) — Beta interne, equipe chocobonplan. Detection des bugs majeurs, ajustement de l’UX.
Vague 2 (20% des utilisateurs) — Early adopters selectionnes. Monitoring intensif des performances, comparaison des metriques avec l’ancienne version.
Vague 3 (50% des utilisateurs) — Deploiement progressif. A/B testing sur les metriques business : taux de conversion, engagement, retention.
Vague 4 (100% des utilisateurs) — Migration complete. L’ancienne application est desactivee.
A chaque vague, on comparait les metriques DORA et les metriques business. Si une degradation etait detectee, on pouvait faire marche arriere en quelques minutes. C’est le principe du deploiement “canary” recommande par le Google SRE Book : on expose une petite partie du trafic au changement, on mesure, on decide.
Phase 3 — Validation sous charge reelle
Le vrai test d’une application e-commerce, c’est le Black Friday. C’est la qu’on voit si l’architecture tient — pas dans un benchmark en laboratoire.
La nouvelle application a ete deployee a 100% avant le Black Friday. Les resultats ont ete sans appel.
Les resultats mesurables
| Indicateur | Avant | Apres |
|---|---|---|
| Comportement sous pic de trafic | Ralentissements, crashs | Zero degradation |
| Notifications push pendant Black Friday | Saturees (service tiers) | 100% delivrees (FCM direct) |
| Utilisateurs perdus pendant migration | — | Zero |
| Temps de chargement des deals | 3-4 secondes | < 1 seconde |
| Bugs en production par semaine | 5-8 | 0-1 |
| Temps pour livrer une fonctionnalite | 3-4 semaines | 1 semaine |
Le resultat le plus significatif : l’equipe peut a nouveau innover. Avant la reecriture, l’essentiel du temps de developpement etait consacre a corriger des regressions. Apres, l’equipe peut se concentrer sur le produit — nouvelles fonctionnalites, A/B tests, optimisation de la conversion.
Pourquoi la plupart des reecritures echouent — et comment eviter ca
La reecriture logicielle a mauvaise reputation. Joel Spolsky, co-fondateur de Stack Overflow, a ecrit un article celebre qui la qualifie de “pire erreur strategique qu’une entreprise de logiciel puisse faire.” Et dans la majorite des cas, il a raison.
Les reecritures echouent pour quatre raisons principales :
1. Le “Second System Effect”
Decrit par Frederick Brooks dans The Mythical Man-Month : quand on reconstruit un systeme, la tentation est d’y ajouter tout ce qu’on a reve d’avoir dans l’ancien. Le perimetre explose, le delai triple, et le projet meurt de sa propre ambition.
Comment on l’a evite : perimetre strict. La nouvelle application devait faire exactement ce que l’ancienne faisait — pas plus. Les nouvelles fonctionnalites attendraient que la migration soit terminee.
2. La perte de connaissances implicites
L’ancien code contient des annees de corrections de bugs, de cas limites, de regles metier implicites. Reecrire de zero, c’est risquer de perdre tout ca.
Comment on l’a evite : tests de caracterisation sur l’ancien systeme. Avant de reecrire un module, on documentait son comportement exact — y compris les cas limites bizarres. Le nouveau code devait passer les memes tests.
3. L’absence de feedback pendant la construction
Pendant une reecriture, l’equipe peut passer des mois sans feedback reel des utilisateurs. Quand le nouveau systeme est finalement deploye, les surprises s’accumulent.
Comment on l’a evite : migration par vagues. Des la vague 1, les utilisateurs reels testaient la nouvelle application. Les retours etaient integres en continu.
4. Le big bang du deploiement
On coupe l’ancien, on active le nouveau. Si ca ne fonctionne pas, on est coinces.
Comment on l’a evite : execution en parallele et rollback instantane. A tout moment, on pouvait revenir a l’ancienne version en quelques minutes.
Le framework de decision : faut-il reecrire votre application ?
La reecriture est la bonne decision uniquement quand trois conditions sont reunies :
| Condition | Question a se poser |
|---|---|
| 1. Le code existant est irreparable | La stabilisation couterait-elle plus cher que la reconstruction ? |
| 2. Le cout de l’inaction depasse celui de la reecriture | Pouvez-vous chiffrer ce que vous perdez chaque mois/trimestre ? |
| 3. Vous pouvez gerer la transition comme une migration | Etes-vous pret a faire tourner les deux systemes en parallele ? |
Si les 3 conditions sont remplies, la reecriture est probablement la bonne decision. Si une seule manque, privilegiez la reprise progressive.
Et dans tous les cas : ne coupez jamais l’ancien systeme avant que le nouveau ait prouve sa fiabilite en conditions reelles, avec de vrais utilisateurs, sous une vraie charge.
Ce que vous pouvez faire maintenant
Si votre application mobile montre des signes de fatigue, commencez par un diagnostic :
- Mesurez les performances sous charge. Pas en conditions normales — en conditions de pic. Votre app tient-elle pendant une operation commerciale ?
- Comptez les regressions. Combien de bugs en production ce mois-ci ? Combien sont des regressions (des bugs deja corriges qui reviennent) ?
- Evaluez le cout de l’inaction. Que perdez-vous a chaque incident ? En chiffre d’affaires, en reputation, en moral d’equipe ?
- Faites auditer. Un audit de quelques jours vous dira si la reprise est possible ou si la reecriture est necessaire.
La reecriture n’est pas toujours la reponse — mais quand elle l’est, il faut la faire bien. Et “bien”, ca signifie : en parallele, par vagues, avec des metriques, et sans jamais mettre en danger le service existant.
Votre app tient la charge ? Ou vous croisez les doigts ? Parlons-en.