Opinions

Comité Refactorisation : Améliorer le code existant

Mathieu De Gracia avatar
Publié le 15 février 2024
Couverture de l'article Comité Refactorisation : Améliorer le code existant

Il est fort probable que vous soyez un jour confronté en entreprise à une application désuète, vieille de plusieurs années, dont la simple évocation du nom provoque de mauvais souvenirs.

Une application sur laquelle il n'est pas plaisant de travailler où les cycles de développement sont longs et laborieux ... sans que le temps attribué à chaque modification ne soit corrélé avec une quelconque richesse fonctionnelle.

Ne mentez pas, nous connaissons et nous vivons tous avec ce genre d’application au quotidien et certaines sont même de notre ressort.

Pourquoi, de nos jours, une application Web est elle destinée à être quasi obsolète tous les 3 ans ? À quel niveau avons nous collectivement échoué afin de garder un avenir radieux pour nos projets ?

Nous sommes parfois des bricoleurs qui se prennent pour des artisans.

Face à ce constat, il est tentant de vouloir recommencer un projet à zéro afin de reprendre la main sur la base de code, orgueilleux de nos nouvelles expériences nous n'allons tout de même pas reproduire les mêmes erreurs ? Le code sera parfait cette fois ci !

Dans les faits, vouloir recommencer une application de zéro est bien souvent financièrement impossible et techniquement périlleux pour une entreprise et vous éluderez la difficile question sous-jacente : pourquoi mon application est devenue obsolète ?

Bien souvent, ces applications génèrent de la dette non pas car le besoin fonctionnelle a fortement évolué avec le temps mais parce qu'elles sont incapables d'accueillir sereinement le changement.

Sans prise de recul, il y a fort à parier que vous reproduirez les mêmes erreurs ... mais sur un framework à jour, félicitations.

Les développeurs savent coder mais rarement concevoir.

En tant que développeur, nous pensons un peu trop rapidement que notre métier consiste à coder, à connaître sur le bout des doigts nos langages et nos frameworks. C'est une grave erreur, le métier de développeur consiste à concevoir et cela implique beaucoup plus de relationnel que vous ne le pensiez.

Prenons de la hauteur à travers une série de plusieurs exercices afin d'analyser et de bâtir le futur de vos applications.

Former un comité

Une application est un bien collectif appartenant à une équipe, son amélioration relève d'un effort commun et non d'un développeur isolé, aussi bien intentionné soit il.

Commencez par former un comité, composé de quelques développeurs, en privilégiant les personnes possédant une bonne expérience dans le métier de votre entreprise et une connaissance approfondie de vos applications.

Dans un premier temps, je vous conseille de limiter la taille de ce comité tant que le fond et la forme ne sont pas clairement maîtrisés pour éviter de vous disperser.

Privilégiez également des personnes de confiance faisant preuve de professionnalisme et dont l'opinion provient d'une réflexion sincère plutôt que d'un réflexe conservateur ou d'un esprit de contradiction.

Notre métier est souvent gangrené par l'image du développeur ninja (anciennement le développeur barbu) qui bien ancré sur ses positions pourrait mettre à mal ou s'accaparer les discussions du groupe, les membres du comité doivent savoir s'écouter et se considérer.

Cependant, à l'avenir, les portes de ces comités doivent être ouvertes à tous, n'isolez pas les développeurs, ne vous enfermez pas dans une tour d'ivoire, la qualité est l'affaire de tous.

Ce comité aura la lourde responsabilité d'identifier les problématique de conceptions et d'y proposer des solutions, n'ayez pas le regard trop porté en arrière, votre objectif est de préparer le futur et non de s'apitoyer sur votre sort et de blâmer les erreurs passées.

Une fois le comité constitué, nous pouvons passer à la seconde étape.

Identifier nos pratiques

Une application est toujours constituée d'un ensemble de pratiques et de patterns de conception, qu'ils soient propres à votre framework, issus de votre langage ou tout simplement communs comme concepts d'architecture logicielle.

Ces patterns sont extrêmement variés, allant de concepts génériques d'architecture tels que la Clean Architecture, le MVC, le CQRS à des concepts intégrés de manière dogmatique par nos frameworks comme les ressources, les façades, les global scope de Laravel ...

Au fil des années, une application accumule un ensemble de pratiques répondant plus ou moins bien à ses enjeux, intégrées avec plus ou moins de finesse, et parfois, répondant à une problématique plus ou moins encore existante.

Lors de cette seconde étape le comité se réunira pour lister les patterns et les pratiques structurantes d'une application.

Durant cet exercice, évitez de plonger dans le code source de l'application, les véritables problèmes, ceux qui provoquent une douleur quotidienne viennent rapidement en tête.

Une fois listées, distinguer les pratiques à améliorer, pertinentes pour votre application mais méritant d'être traitées ou abordées différemment, des choses qui au contraire nécessitent d'être progressivement abandonnées.

Réfléchissez également aux patterns manquants qui pourraient être ajoutés à votre application afin de répondre intelligemment à vos nouveaux besoins.

Cette réflexion vous amènera à placer ces différentes pratiques dans des post-it sur le schéma suivant, entre les trois extrémités : Improve, Stop, Start.

Plus un post-it se trouve proche d'une extrémité et plus il nécessite d'être amélioré, stoppé, ou étudié.

Cet exercice pourrait facilement générer plusieurs dizaines de post-it, on se représente difficilement le nombre de patterns constituant nos applications avant de s'y intéresser, alors ne lésinez pas sur la taille de votre triangle !

Si un post-it vous semble difficile à placer sur votre schéma, c'est probablement que la pratique en question est trop générique ou ambiguë et nécessite d'être précisée dans un contexte plus concret.

Il est également possible qu'une pratique ne soulève aucune réflexion, aucune douleur, quelconque, ne le plaçant vers aucune extrémité de votre schéma ... dans cette situation, n'hésitez pas à tout simplement supprimer le post-it en question.

L'exercice est intellectuellement éprouvant, alors privilégiez des sessions courtes de 1h - 1h30.

Proposer des solutions

Maintenant que des patterns sont clairement identifiés, il est temps de s'attarder sur les problématiques qui en résulte et à réfléchir aux solutions potentielles.

Cet exercice est réalisable en groupe ou de manière asynchrone, encore une fois, cet atelier est difficile et chronophage alors concentrez vous uniquement sur les post-its situés aux extrémités de votre triangle.

Vous pouvez utiliser le template suivant :

1# [pattern]
2
3Problèmes :
4- ...
5
6Solutions :
7- ...

Commencez par nommer le pattern en question, ajoutez quelques lignes succinctes sur les problématiques du pattern justifiant votre volonté de le faire évoluer et enfin lister les solutions potentielles.

Pour le moment, ne considérez pas l'effort nécessaire à la mise en œuvre des solutions (cela constituera le cadre du prochain atelier) mais concentrez-vous uniquement sur comment répondre aux problématiques du post-it.

À ce stade, il n'est pas non plus nécessaire d'approfondir la marche à suivre pour intégrer les diverses solutions, cela n'est pas une spécification technique, les détails potentiels d'une implémentation seront discuté plus tard.

Voici, par exemple, ce que pourrait donner les réflexions sur le post-it concernant l'utilisation des Global Scope de Laravel que nous souhaitons progressivement supprimer :

1# Global Scope
2
3Problèmes :
4- Peu explicite et source d'incompréhension.
5- Devient rapidement contraignant et favorise l'apparition des bugs.
6
7Solutions :
8- Interdire l'écriture d'un nouveau Global Scope à l'aide d'une règle PHPStan.
9- Refactoriser les requêtes existantes afin de supprimer les Global Scope.

Ne négligez pas une solution sous prétexte qu'elle ne répond pas à l'intégralité de votre problématique, une solution n'est pas vouée à être parfaite mais à améliorer le code existant.

Ce comportement correspond à un biais cognitif parfaitement humain, appelé le "Sophisme de la solution parfaite", vous éloignant naturellement d'une solution qui ne répondrait pas à tous vos cas d'usage.

Une fois que vous avez collectivement déterminé un ensemble de solution pour vos post-its les plus aux extrémités, il sera temps de passer à la dernière étape.

Prioriser les solutions

Dernière étape de cette série d'exercices, il est désormais temps de prioriser les différentes solutions que le comité aura déterminées.

La matrice suivante possède deux axes : l'abscisse représente le coût, c'est-à-dire l'effort nécessaire à la réalisation de la tâche, tandis que l'ordonnée représente la valeur, c'est-à-dire son utilité dans l'amélioration de la qualité de votre application.

Placez désormais vos différentes solutions dans cette matrice en considérant la valeur et le coût de la réalisation :

Le placement des premières solutions sur cette matrice peut, il est vrai, sembler hasardeux ... n'ayez crainte et lancez-vous !

Aucun placement n'est définitif et votre échelle de valeurs évoluera naturellement au fil de l'exercice, autorisez-vous simplement à ajuster la position de telle ou telle solution dès lors que vous aurez plusieurs points de référence.

Une solution sera toujours plus ou moins couteuse qu'une autre

Contrairement à l'exercice précédent, la priorisation des solutions doit se faire de manière synchrone avec l'ensemble des membres du comité. Cette étape est de loin la plus importante car c'est elle qui déterminera les tâches que l'équipe devra effectuer par la suite (ou justifier devant un PO pour compléter une roadmap).

Tous les exercices précédents vous ont conduits à cette étape particulière, alors prenez votre temps et examinez attentivement chacune des solutions que vous envisagez. Il serait malencontreux de hâter ce dernier exercice et de vous lancer hâtivement tête baissée dans le code.

N'oubliez pas, notre métier n'est pas de coder mais de concevoir !

Une fois toutes les solutions placées sur notre matrice, nous pouvons identifier les "regions" suivantes :

Ces régions sont à titre indicatif, elles n'ont pas de frontière stricte !

Une solution avec une faible valeur et un faible coût de mise en place sera un "quick win", comprenez une tâche simple et rapide à déployer qui pourrait être réalisée en fil rouge d'une autre tâche. Il n'y a pas énormément d'enjeux derrière un "quick win" et vous pouvez vous lancer dans cette tâche quand l'opportunité se présentera.

Une tâche avec un coût faible mais une valeur élevée sera un "no-brainer", il n'y a pas de question à se poser, la solution vous apparaît comme une évidence, allez y !

Une tâche avec une forte valeur et un coût élevé sera un "worthy investment" comprenez une tâche complexe mais méritant qu'on s'y attarde. Une spécification technique et/ou un ADR peuvent s'avérer utiles pour préciser davantage la solution et potentiellement la diviser en plusieurs petites tâches moins coûteuses. Ces tâches seront des efforts longs et difficiles mais à coup sûr extrêmement bénéfique pour la qualité de votre application.

Et pour finir, une tâche avec une faible valeur et un coût élevé sera un "nop", soit une solution trop complexe et peu avantageuse en l'état. Dans cette situation, n'hésitez pas à re-étudier le pattern en question afin de réfléchir à des solutions plus actionnables et moins couteuses.

La notion de qualité

Il serait tentant d'utiliser le comité pour discuter sans fin de l'emplacement idéal d'une accolade, et vous, vous la placez avant ou après la signature d'une méthode ?

Il est vrai qu'un code peu lisible nuira au confort de lecture et à sa compréhension, un manque de soin deviendra également un frein dans la détection des erreurs lors des revues de code : la lisibilité et le style du code sont importants.

Cependant, gardez en tête que la qualité est aussi une histoire de contexte et qu'elle doit être considérée en fonction des besoins et de la criticité d'un programme.

Des normes, telles que la ISO 25010 peuvent vous aider à éclaircir et à mettre le doigt sur les critères réellement déterminants pour la qualité de votre code.

Votre application doit-elle répondre à des enjeux de sécurité ou de fiabilité ? Doit-elle être tolérante à la faute et/ou fortement disponible ? C'est uniquement en répondant à ces différentes questions que vous pourrez véritablement placer un curseur précis sur la qualité du code à obtenir.

Cet outil peut vous aider à prendre en main la norme ISO 25010.

À travers ces critères, il est même possible que le code suivant, que vous avez probablement vu passer sur Twitter, vous apparaisse finalement comme ... adéquat?

Ce code est performant et robuste mais également très fermé et peu évolutif ... mais sans contexte et critères de qualité spécifiques, il devient difficile de juger de la pertinence de ce dernier, comment affirmer qu'il ne répond pas correctement à ses besoins sur la base d'une simple image ?

La principale contrainte de ce code est qu'il est intimement lié à un contexte d'exécution, le rendant rigide et peu réutilisable, pour autant, un code "stupide" n'est pas synonyme de mauvais.

Notre égo de développeur pourrait soutenir le contraire face au caractère primitif de ce code, mais j'insisterais sur le fait que votre code n’a pas besoin d’être dense pour être performant et intelligent.

Ne refactorisez pas un composant de votre application parce que cela vous semble cool mais parce que cela est nécessaire.

Une refactorisation est une chose couteuse et complexe, elle doit nécessairement répondre à un enjeu de qualité permettant d'assurer la pérennité de votre application et non à satisfaire une envie, bien souvent puerile, de changement.

Le temps du comité est précieux, alors favorisez les discussions sur le fond plutôt que sur la forme, à moins que cette dernière ne soit réellement une source d'inconfort.

L'importance du métier

Attention, cet article prend le parti pris de se concentrer sur l'aspect purement technique afin de simplifier la présentation des différents exercices du comité refactorisation.

Cependant, n'oublions pas que nous développons en entreprises afin de répondre à ses enjeux technologiques : la technique répond aux problématiques de votre entreprise et non l'inverse.

Vous aurez énormément de mal à justifier auprès des parties prenantes un temps alloué à la refactorisation et à l'évolution de votre application si vous négligez l'aspect métier dans toutes vos réflexions.

Un code d'une qualité moindre peut parfois se justifier sur des fonctionnalités peu utilisées ou peu critiques, alors n'hésitez pas lorsque cela est nécessaire à impliquer des personnes extérieures aux développeurs dans vos réflexions car la véritable valeur d'une fonctionnalité est autant technique que fonctionnelle.

Conclusion

Le comité refactorisation ne résoudra pas tous vos problèmes, il n'est pas une solution magique qui éliminera la dette technique de votre entreprise, voyez le plutôt comme un support de réflexion permettant d'impliquer davantage les développeurs dans la prise de décisions et de les responsabiliser quant aux conséquences de leurs choix.

N'oubliez pas que les attitudes sont contagieuses, le comité doit impérativement faire l'effort de maintenir son regard vers l'avenir et de porter son attention sur des actions concrètes et réalisables. Ne vous attardez pas sur les erreurs passées et concentrez votre attention sur des actions bénéfiques.

Conservez également un regard bienveillant sur l'état de vos applications et ne soyez pas trop prompt à casser le code de vos prédécesseurs, ce dernier répond généralement à des problématiques oubliées que vous n'avez même pas en tête.

La dette de votre application, le legacy, est votre héritage, il n'est pas sale, il n'est pas honteux, il est même souvent celui qui fait vivre votre entreprise.

La première étape pour améliorer votre application sera de l'accepter et de commencer à en prendre soin car personne d'autre que vous ne pourra veiller sur votre code.

The only way to go fast, is to go well. - Robert C. Martin

A lire

Autres articles de la même catégorie