fbpx
code legacy PHP

Code legacy et dette technique en PHP: le guide

Comment se débarrasser du code legacy : le guide pour reprendre le contrôle de votre application PHP

Temps de lecture : 9 minutes

Votre application tourne. Elle rend service. Mais plus personne n’ose y toucher. Ça vous parle ?


Il y a quelques mois, un client m’a contacté avec une phrase que j’entends de plus en plus souvent : « Joan, on a une application qui fonctionne, qui nous fait gagner un temps fou… mais on n’a pas déployé depuis un an. On a peur de tout casser. »

Pas de tests. Pas de documentation. Des classes de 3 000 lignes. Aucun framework. Et une équipe technique qui marche sur des œufs à chaque modification.

Si vous êtes CTO ou lead dev, vous avez probablement déjà vécu cette situation. Ce projet qui était « provisoire » il y a cinq ans et qui est devenu le pilier de votre activité. Ce fameux code legacy que tout le monde redoute mais que personne ne veut affronter.

La bonne nouvelle ? On peut s’en sortir. Sans tout réécrire. Sans tout casser. Et sans y passer deux ans.


Qu’est-ce que le code legacy, exactement ?

Avant d’aller plus loin, clarifions un point. Le code legacy, ce n’est pas juste du « vieux code ». Michael Feathers, dans son livre Working Effectively with Legacy Code, le définit ainsi : c’est du code sans tests.

En pratique, le code legacy cumule souvent plusieurs symptômes : aucune couverture de tests automatisés, une documentation absente ou obsolète, des dépendances à des versions de PHP qui ne sont plus maintenues (PHP 5.6, 7.0…), des fichiers de plusieurs milliers de lignes avec des responsabilités mélangées, un couplage fort entre les couches métier, la base de données et l’affichage, et surtout, une dette technique PHP qui s’accumule à chaque hotfix posé en urgence.

Le résultat : votre application devient un terrain miné. Chaque modification, même mineure, peut provoquer des régressions imprévisibles. Et progressivement, l’équipe arrête de déployer.


Pourquoi la réécriture complète est (presque toujours) une mauvaise idée

La tentation est grande. « On jette tout et on recommence sur un framework propre. » Symfony, Laravel, peu importe. On repart de zéro.

Sauf que dans la réalité, la réécriture totale est l’un des pièges les plus coûteux de l’industrie logicielle. Joel Spolsky l’avait qualifiée de pire erreur stratégique qu’une entreprise puisse faire. Et pour cause.

Le code legacy contient des années de logique métier accumulée. Chaque condition bizarre, chaque if imbriqué sur cinq niveaux correspond souvent à un cas réel, un bug corrigé en production, une demande client. Tout réécrire, c’est prendre le risque de perdre cette connaissance tacite.

Sans compter que pendant la réécriture — qui prend toujours plus de temps que prévu — vous devez maintenir l’ancien système en parallèle. Deux bases de code à gérer. Le double de bugs. Le double de stress.

Alors, quelle est l’alternative ?


La méthode progressive : reprendre le contrôle étape par étape

L’approche qui fonctionne, c’est la modernisation incrémentale. On ne cherche pas à tout refaire d’un coup. On isole, on sécurise, on améliore. Morceau par morceau.

Voici la stratégie en cinq étapes que j’applique avec mes clients.

Étape 1 — Cartographier l’existant

Impossible de moderniser ce qu’on ne comprend pas. La première action, c’est de réaliser un audit technique de l’application.

Quelle version de PHP est utilisée ? Quelles dépendances sont obsolètes ? Où sont les fichiers les plus longs, les plus modifiés, les plus fragiles ? Quel est le niveau de couplage entre les modules ?

Des outils comme PHPStan (analyse statique), PHP Mess Detector ou simplement cloc (comptage de lignes) permettent d’obtenir rapidement une vue d’ensemble. L’objectif n’est pas de tout documenter, mais d’identifier les zones à risque et les zones à forte valeur métier.

Étape 2 — Poser un filet de sécurité avec des tests

C’est le point de bascule. Avant toute modification, il faut des tests de caractérisation. Ce ne sont pas des tests unitaires classiques — ce sont des tests qui documentent le comportement actuel du code, même s’il est « faux ».

Concrètement, vous écrivez un test qui appelle une fonction avec des données connues et vous vérifiez que le résultat correspond à ce que le code produit aujourd’hui. Pas à ce qu’il devrait produire. À ce qu’il produit réellement.

Pourquoi ? Parce que ces tests deviennent votre alarme anti-régression. Le jour où vous modifiez quelque chose et qu’un test casse, vous savez immédiatement que vous avez changé un comportement existant — volontairement ou non.

Pour du code PHP legacy sans framework, PHPUnit reste le standard. Et si le code est trop couplé pour être testé unitairement, commencez par des tests fonctionnels de plus haut niveau (tests HTTP, tests de bout en bout).

Étape 3 — Isoler et découper les responsabilités

Une fois le filet de sécurité en place, on attaque le refactoring. La technique clé ici, c’est l’extraction de classes et de méthodes.

Prenons un cas typique : un fichier OrderController.php de 2 500 lignes qui gère à la fois la validation des commandes, le calcul des prix, l’envoi d’emails et la génération de PDF.

On va extraire chaque responsabilité dans sa propre classe. OrderValidator, PriceCalculator, OrderNotifier, InvoiceGenerator. Chaque extraction est couverte par les tests de caractérisation posés à l’étape précédente.

C’est là que les principes SOLID prennent tout leur sens. Ce ne sont pas des concepts théoriques — ce sont des outils pratiques pour rendre du code legacy maintenable.

Étape 4 — Introduire progressivement une architecture moderne

Une fois les responsabilités séparées, vous pouvez commencer à migrer vers une architecture plus structurée. Plusieurs approches sont possibles selon votre contexte.

Le pattern Strangler Fig est particulièrement efficace. Le principe : vous placez une couche intermédiaire (un routeur, un middleware) devant votre application legacy. Les nouvelles fonctionnalités sont développées dans un environnement moderne (Symfony, par exemple). Les anciennes routes continuent de pointer vers le code legacy. Et au fur et à mesure, vous migrez les routes une par une vers le nouveau code.

L’application legacy « rétrécit » progressivement, étranglée par la nouvelle architecture, comme un figuier étrangleur enveloppe son arbre hôte. D’où le nom.

L’avantage majeur : à chaque instant, l’application reste fonctionnelle et déployable. Pas de big bang. Pas de migration périlleuse.

Étape 5 — Mettre en place une CI/CD et reprendre les déploiements

La dernière étape, et peut-être la plus libératrice : réactiver les déploiements. Avec des tests en place et une architecture plus propre, vous pouvez mettre en place un pipeline d’intégration continue.

L’objectif minimum est simple : à chaque push, les tests tournent automatiquement. Si tout est vert, le déploiement est déclenché. Vous passez d’un cycle « on déploie une fois par trimestre en priant » à un cycle « on déploie plusieurs fois par semaine en toute confiance ».

Des outils comme GitHub Actions, GitLab CI ou Jenkins rendent cette mise en place rapide, même sur des projets existants.


Les erreurs à éviter quand on s’attaque au code legacy

En plus de 13 ans de développement PHP, j’ai vu des projets de modernisation échouer pour des raisons qui reviennent systématiquement.

Vouloir tout refactorer d’un coup. La modernisation incrémentale fonctionne précisément parce qu’elle est progressive. Si vous essayez de tout changer en une seule itération, vous recréez le risque d’une réécriture totale, sans les bénéfices.

Négliger l’adhésion de l’équipe. La dette technique n’est pas qu’un problème technique. C’est un problème humain. Si l’équipe ne comprend pas pourquoi on refactore, si elle ne voit pas les bénéfices concrets (moins de bugs, déploiements plus fréquents, moins de stress), elle résistera au changement. Impliquez vos développeurs dès le départ.

Sous-estimer la valeur d’un regard extérieur. Quand on est plongé dans un codebase depuis des mois ou des années, on développe des angles morts. Un développeur expérimenté qui arrive avec un œil neuf peut identifier en quelques jours des problèmes que l’équipe interne ne voit plus.


Et si le vrai problème n’était pas le code ?

Il y a un paradoxe avec le code legacy. Plus on attend, plus c’est difficile. Plus c’est difficile, plus on repousse. Et plus on repousse, plus la dette technique s’accumule.

Le client dont je vous parlais au début de cet article ? En quelques semaines d’accompagnement, nous avons posé les premiers tests, identifié les zones critiques, et surtout relancé les déploiements. L’application n’était pas parfaite — elle ne le sera jamais — mais l’équipe avait retrouvé la confiance pour la faire évoluer.

Le vrai enjeu n’est pas d’avoir un code parfait. C’est de retrouver la capacité à livrer des améliorations sans avoir peur.


Vous reconnaissez votre situation ?

Si votre application PHP souffre de dette technique, si votre équipe hésite à déployer, si vous sentez que votre code legacy freine votre croissance — il est peut-être temps d’en parler.

Je propose un rendez-vous découverte gratuit de 30 minutes pour comprendre votre contexte, évaluer la situation et voir si un accompagnement peut débloquer les choses.


Joan Drozo — Développeur PHP Symfony, +13 ans d’expérience. J’accompagne les équipes techniques dans la modernisation de leurs applications legacy.
Mon linkedin : https://www.linkedin.com/in/joan-drozo-developpeur-php-rennes/


code legacy PHP
code legacy PHP