Une fois n’est pas coutume, j’ai envie de parler un peu de technique sur ce blog. Wikeo tourne sur PHP 7.4 depuis peu. Jusque là nous étions cantonné à la version 7.3 car nous sommes en train de réécrire Wikeo entièrement avec des outils modernes. Nous n’avons donc pas mis la priorité sur le legacy.
Cependant, cette dette technique commençait à peser : si nous voulons suivre les mises à jour de sécurité et de performances de nos serveurs, nous sommes obligés d’assurer une maintenance de l’ancien code.
Une maintenance manuelle de ce code aurait été bien trop chronophage pour un gain presque invisible. Nous avons donc étudié les différentes solutions open-source existantes afin d’assurer cette transition.
La peur du legacy
Lorsqu’un logiciel évolue, les développeurs évoluent en même temps que les améliorations des technologies, la découvertes de nouvelles techniques, etc. Alors que nous nous concentrons sur les nouvelles fonctionnalités, les anciennes stagnent, se stabilisent et finissent par ne plus évoluer.
Le code prend alors de l’âge et devient « legacy », les développeurs commencent à considérer comme risqué d’y toucher car ce code est souvent un chateau de cartes et on y perd rapidement beaucoup de temps.
Quand vient le moment de réécrire le code, il est parfois difficile de se souvenir de ce que faisait exactement la fonctionnalité. Deux options s’offrent alors : analyser en détail la fonctionnalité afin de définir son but exact et la refaire avec des cas d’utilisation identiques. Ou alors cette fonctionnalité n’est plus utilisée dans son entièreté et c’est l’occasion de faire le ménage pour simplifier le nouveau code en définissant les nouveaux cas d’utilisation.
Mais en attendant la réécriture, il faut continuer à maintenir le legacy sans y perdre trop de temps. Une solution est d’automatiser cette maintenance au maximum. C’est cette approche que nous avons choisi.
Le framework
Wikeo a été développé sur base d’un framework PHP qui a maintenant disparu : Kohana. Heureusement, une équipe de développeurs qui avaient besoin de faire évoluer des applications legacy tournant encore sur ce framework ont repris la base de code du framework. Ils mettent à disposition le fruit de leurs efforts sur Github : https://github.com/koseven/koseven
La première étape a donc été de remplacer les composants de Kohana par ceux de KO7 en utilisant la branche « devel » qui est compatible avec PHP 7.4.
Nous avons assuré cette transition sans trop de mal : les constantes préfixées par « KOHANA_ » ont toutes été remplacées par « KO7_ », un simple rechercher/remplacer en est venu à bout.
Le module « kohana » assure la transition vers les classes préfixées par « Kohana_ » que nous avons remplacées par « KO7_ ». Il a suffit de charger ce nouveau module dans le fichier bootstrap pour assurer la compatibilité avec les classes héritées.
Le code
Le plus gros morceau concernait le code de Wikeo en lui-même : plus de 800 fichiers répartis dans des modules, des extensions et les contrôleurs. Impossible de tout vérifier manuellement surtout pour certains changements complexes (des appels à la fonction implode à unifier notamment) et idéalement unifier et moderniser la syntaxe complète (ne plus appeler array(…) mais utiliser la structure […]).
Heureusement, des outils existent ! Le plus connu est PHP-CS-Fixer : cet outil va scanner votre code à la recherche de manquements à des règles préalablement définies dans un fichier de configuration. S’il trouve des problèmes, il les résout automatiquement ! Ca paraît facile non ?
En fait c’est vraiment simple ! Le tout est de trouver un bon fichier de configuration pour démarrer. J’ai pris celui du Gist de Laravel Shift : https://gist.github.com/laravel-shift/cab527923ed2a109dda047b97d53c200 que j’ai adapté aux besoins de Wikeo.
Le fichier final est disponible sur le Gist de Wikeo : https://gist.github.com/bistory/2df00f28c36e8782866f393ea0256eaf
Les règles de PHP-CS-Fixer
'@PSR1' => true,
'@PSR2' => true,
'@PHP74Migration' => true,
'@PHP80Migration' => true,
Ces règles sont des raccourcis pour activer des ensembles de règles : compatibilité PSR1, PSR2, PHP 7.4 et PHP 8.0. Elles permettent de diminuer un peu la taille du fichier de configuration. J’ai parcouru les règles qui sont activées avec ces raccourcis afin de nettoyer un peu le fichier de configuration de base.
'psr4' => false,
Kohana a une structure de fichiers qui ne correspond pas du tout au standard PSR4. J’ai donc dû désactiver ce paramètres pour éviter la réécriture de tous les noms des classes.
'no_alias_functions' => true,
Renomme une liste d’alias de fonctions pour utiliser le nom natif. Permet d’éviter d’avoir des appels à des fonctions dépréciées.
'implode_call' => true,
La fonction implode peut accepter l’argument « glue » en première ou deuxième position. PHP 7.4 renvoie un warning pour signaler que l’argument « glue » sera uniquement accepté en première position. Cette règle permet de réécrire les appels à implode pour supprimer ces warnings.
'no_php4_constructor' => true,
Renomme les constructeurs en style PHP 4 vers __construct(). J’ai rajouté cette règle car PHP 8 va supprimer la compatibilité avec ces types de constructeurs. Il n’y en avait pas dans le code mais ça permet de s’en assurer.
'no_unneeded_final_method' => true, 'no_unreachable_default_argument_value' => true,
C’est la même idée ici : PHP 8 apporte plus de constraintes pour améliorer la qualité du code PHP produit. Ces deux règles suppriment des mauvaises pratiques ou des erreurs dans le code.
Les autres règles du fichier agissent sur le formatage, l’uniformisation du code (utilisation de echo et pas de print par exemple), etc.
Cette étape a permis de détecter et réparer une dizaine de deprecation notices et nettoyer la plupart des fichiers de la base de code !
Pérenniser l’effort
Faire cette maintenance était nécessaire, mais s’assurer qu’elle puisse s’inscrire sur le plus long terme, c’est mieux ! Nous avons donc mis en place des garde-fous issus des développements sur la nouvelle version de Wikeo.
Nous nous sommes tournés vers GrumPHP, un outil qui permet d’exécuter une série de vérifications avant d’envoyer du code sur un dépôt Git. De cette manière, toute inclusion de code sera trackée et validée par PHP-CS-Fixer, si elle n’est pas valide, elle sera rejetée jusqu’à ce que ça soit le cas.
Conclusion
La migration de tout le code legacy de Wikeo vers PHP 7.4 s’est faite en l’espace d’une journée seulement. Le service a été ensuite testé et mis en ligne le lendemain. Nous avons pu arrêter les services PHP 7.3 pour tout faire tourner sur PHP 7.4. Nous envisageons aussi un passage serein vers PHP 8.0 d’ici quelques mois (il tourne déjà sur notre serveur de test).
Il est important de noter qu’aucune régression n’a été constatée pendant cette migration.
Fun fact : le seul soucis que nous avons rencontré lors de nos tests était lié à un problème de droits de lecture sur des fichiers statiques…
Le gain de performances est perceptible : moins de mémoire et de CPU consommés signifient que le serveur est capable de mieux tenir la charge en cas d’augmentation du trafic !