Application Legacy – Refactoring avec le plugin SQALE (II)

LegacyTechDebtRefactoring3Comme je l’ai expliqué dans le post précédent, nous n’avons pas personnalisé le profile SonarQube et le modèle SQALE en fonction de notre application Legacy et de son contexte. En fait, nous utilisons les résultats ‘out of the box’ afin d’illustrer une démarche possible d’estimation du coût de refactoring de celle-ci, et de présenter quelques pistes d’action à approfondir avec l’équipe de projet et le management – ou éventuellement à voir ceux-ci les rejeter.

En d’autres termes, c’est la démarche qui nous intéresse plus que les résultats sur notre application, tout au moins dans le cadre de ces articles.

Je vais présenter ces actions, des plus simples au plus avancées.

Corriger les défauts les plus critiques

La première chose que je peux voir avec le widget que je me suis configuré (cf. Figure 1 – Données SQALE sur la Dette Technique), c’est qu’il nous en coûte :

  • 59.6 jours pour remédier aux issues de type Critical et au-delà, c’est-à-dire Critical et Blockers.
  • 1 115.6 jours pour remédier aux issues Major, Critical et Blocker.

La même information m’est fournie par le widget suivant :

Figure 1 – SQALE Remediation Cost par criticité

Legacy Technical Debt Criticity

La partie bleue foncée sur chacune des barres horizontales de ce graphique correspond à la barre précédente, afin de calculer un coût par criticité et un coût total, tel qu’affiché dans les deux colonnes de droite.

Nous avions déjà vu que nous n’avions aucun défaut sur les règles de type Blocker, et 753 défauts de type Critical, la plupart d’entre eux concentrés sur 2 règles.

Figure 2 – Violations aux règles Critical

C_World_Crticals

La figure suivante liste les fichiers comportant ces défauts et leur coût de remédiation :

Figure 3 – SQALE Remediation Cost – Critical et Blockers

Legacy Technical Debt Files Critical Issues

Je peux ouvrir chacun de ces fichiers dans SonarQube, et choisir de ne visualiser que certaines ‘Issues’. La figure suivante présente le programme ‘fltexp.c’ et ses différentes Issues critiques.

LegacyTechfltexpCritical

Pour chacun des 16 défauts de type Critical dans ce programme, je peux voir :

  • La ligne de code correspondante.
  • Le coût de remédiation de cette issue, tel que configuré dans le plugin SQALE par défaut : 1 heure dans le premier cas (MISRA C++ 6-6-1) et 15 minutes dans le second (MISRA C++ 5-14-1).

Sur la base de ces chiffres, je peux donc proposer une première action de refactoring portant sur les composants avec des défauts critiques, pour un total d’environ 60 jours, ou encore 12 jours pour une équipe de 5 personnes.

Dans la réalité, je travaillerai avec l’équipe de projet afin d’estimer avec eux les défauts qu’ils considèrent ou non Critical (ou Blocker), le temps qu’ils estiment nécessaire pour résoudre chaque Issue, et ainsi configurer le ‘profile’ (ensemble de règles SonarQube) en fonction de leurs remarques.

Ramener le SQALE Rating au niveau A

Avec le widget que je me suis configuré (cf. Figure 1 – Données SQALE sur la Dette Technique), je peux voir également qu’il nous en coûte 291.9 jours afin de ramener le SQALE Rating de B, son niveau actuel, à A. Le SQALE Rating mesure le poids de la dette dans l’application, de la manière suivante dans notre cas :

  • B : entre 10% et 20%.
  • A : inférieur ou égal à 10%.

A raison de 18.5 jours travaillés par mois, ces 291.9 jours représentent 15.8 mois au total, ou 3 mois et 3 jours par développeur pour une équipe de 5 personnes. Si j’ajoute une charge de gestion de projet de 20%, ce qui est le chiffre par défaut pour toute prévision de planning, nous passons à 3 mois et 15 jours par développeur.

Nous avons vu que l’écriture de tests de caractérisation nécessitait environ 3 mois, avec un peu de marge de manœuvre pour la gestion de projet ce qui est acceptable dans le cadre d’un transfert de connaissances. Si nous ajoutons à nouveau 3 mois et quelques jours, notre projet de refactoring passe à 6 mois ou 7 mois, ce qui me semble acceptable pour fiabiliser notre application avec des tests et la ramener à un niveau très correct de dette technique.

Dans la réalité, il est très difficile pour le management de justifier auprès des utilisateurs de paralyser toute évolution – et surtout toute correction – pendant une telle période. J’ignore tout du backlog en matière de demandes utilisateurs, modifications et tickets, ainsi que des charges moyennes de correction par mois qu’il faudrait prendre en compte dans un planning de refactoring : je me contenterai donc de ces 292 jours et je vais essayer de les optimiser au mieux afin de construire un plan sinon recevable, du moins envisageable pour les décideurs.

La pyramide Sqale va nous aider à choisir, parmi les différentes catégories de violations aux best practices.

Figure 4 – SQALE Tecnical Debt Pyramid

Legacy Technical Debt SQALE Pyramid

Chaque facteur de plus haut niveau possède un certain nombre de ‘caractéristiques’ qui vont rassembler chacune les métriques relevant de cette catégorie. La figure suivante montre l’écran de configuration SQALE dans SonarQube, qui permet de paramétrer le coût de remédiation pour chaque violation à une ‘best practice’ de programmation, au sein de chaque catégorie, en l’espèce dans notre exemple, les ‘Characteristics’ de ‘Testability’.

Figure 5 – Configuration des règles dans le modèle SQALE

Legacy Technical Debt SQALE Quality Profile Configuration

Je n’ai pas de règles pour la ‘Reusability’ dans ce Profile pour ce langage, ce qui explique la dette technique à 0 sur ce facteur (cf. Figure 4 ci-dessus).

La ‘Portability’ voit une règle unique enfreinte, pour une dette technique de 3.5 jours, mais elle ne se révèle importante que dans le cas d’une réécriture de l’application en C++. A prendre en compte dans le cadre d’un reengineering donc, mais pas d’un refactoring.

Figure 6 – Règle de ‘Portability’

Legacy Technical Debt SQALE Characteristic Portability

Il en va de même pour les règles concernant la Testability (voir la figure 5 précédente), comme ‘Avoid too complex file’, ‘Avoid too complex function’, le nombre de paramètres d’une fonction ou l’utilisation de ‘Goto’ et de ‘Continue’ : un refactoring de ce type de défauts nécessite un redesign de l’application, donc encore une fois, à envisager dans le cadre d’un reengineering. Car si vous devez repenser le design et l’architecture de votre application afin de mieux répartir la complexité, alors vous pouvez en profiter pour réécrire celle-ci dans un langage orienté objet, comme le C++, et bénéficier ainsi de l’héritage, de l’encapsulation et du polymorphisme.

Pareil pour la Changeability. La figure suivante présente le SQALE Sunburst avec :

  • Au niveau 1, les différents facteurs de Maintainability, Testability, Reliability, etc.
  • Au niveau 2, les caractéristiques au sein de ces facteurs, comme Undestandibility et Readibility pour la Maintainability.
  • Au niveau 3, les règles au sein de chaque caractéristique.

Figure 7 – Règle de ‘Changeability’ dans le SQALE Sunburst

Legacy Technical Debt SQALE Sunburst Changeability

Nous pouvons voir dans cette figure que les 13.7 jours de dette technique en matière de Changeability porte sur une unique règle concernant des ‘if’ imbriqués. Plus vous avez de ‘if’ au sein de ‘if’, plus le code devient difficile à comprendre, et plus le risque d’introduire un bug à l’occasion d’une modification du code sera élevé.

Remarque : une telle règle pourrait très bien se retrouvait également sous la ‘characteristic’ de Understandibility. En fait, nombre de règles en matière de Maintainability sont souvent candidates au groupe des règles en matière de Changeability. Raison pour laquelle encore une fois, il est recommandé de personnaliser le modèle SQALE en fonction de ses propres cas d’utilisation, et non pas de l’utiliser ‘out of the box’ comme je l’ai fait pour cet article.

En tout cas, ces défauts en matière de ‘if’ imbriqués sont tout à fait dans la cible d’un refactoring, et donc nous pouvons inclure ces 13.7 jours dans notre plan d’actions.
Dans la figure suivante, j’ai inséré par copié-collé différentes mesures pour :

  • La Maintainability : 738 jours de refactoring au total, qui se décomposent en …
  • 505.6 jours pour la Understandibility et 232.3 jours pour la Readability.

Figure 8 – SQALE Sunburst pour la Maintainability

Legacy Technical Debt SQALE Sunburst Maintainability

On constate que les coûts de remédiation les plus élevés sont sur des règles qui ne sont pas forcément critiques. Que Microsoft n’ait pas utilisé il y a 20 ans les conventions de nommage de macro aujourd’hui usuelles n’est ni étonnant, ni vraiment très important, et la résolution de ces défauts pour un coût de refactoring de 128.1 jours ne représente pas un gain réellement suffisant pour envisager une telle action.

Il en va de même pour l’utilisation des accolades avec des ‘if..else’ qui liste énormément de ‘if’ sur une seule ligne, donc très lisibles et très compréhensibles. Peu de bénéfices pour un coût très élevé.

Non, il y a mieux que les défauts de Maintainability pour optimiser les 291 jours nous permettant de ramener la Technical Debt de cette application à un niveau A. Nous pouvons voir dans la pyramide SQALE (figure 4) que les défauts en matière de Reliability nécessitent un refactoring de 291.8 jours, et donc collent parfaitement avec notre enveloppe de jours disponibles.

De surcroît, il s’agit de défauts qui impactent la fiabilité et la robustesse de l’application, donc présentent un risque pour l’utilisateur ou le client final, par opposition aux défauts en matière de Maintainability qui vont certes peser sur les coûts de maintenance mais ne causeront jamais de bugs. Evidemment, cela dépend encore une fois de l’orientation que vous souhaitez donner au modèle SQALE, en le personnalisant plutôt vers la satisfaction des utilisateurs ou plutôt en faveur de la préservation de vos budgets.

D’abord je peux voir que les 59.6 jours nécessaires pour régler les violations de type ‘Critical’ (cf. figure 2 précédente) concernent des règles au sein de la Reliability. Le tableau suivant présente ces différentes règles et leur coût de remédiation.

Table 1 – Coûts de remédiation des défauts en matière de Reliability

Legacy Technical Debt Reliability Cost

Toutes ces règles visent á améliorer la robustesse de l’application et à diminuer les risques de bug. Si j’ajoute les 13.7 jours en matière de Changeabilité, pour supprimer les ‘if’ imbriqués, nous passons à 305.5 jours, soit 16.5 mois ou 3 mois et 6 jours par développeur (hors charges de projet).

Cela dit, la charge de projet ne devrait pas être énorme, puisque le plan d’action, d’un point de vue opérationnel, est déjà dans le plugin SQALE. Nous avons vu (figure 2 du post précédent) que celui-ci nous donnait la distribution des programmes sur l’échelle du rating SQALE. Dans la figure suivante, je peux voir la liste des fichiers avec le rating le plus bas.

Figure 9 – SQALE Rating des fichiersLegacy Technical Debt Rate Files

On remarquera qu’il s’agit de fichiers .h, en fait avec une notre très basse à cause du nombre très important de violations à la règle ‘Macro names should comply with a naming convention’. D’où l’importance encore une fois de personnaliser le Quality Profile et le modèle SQALE sur les règles qui nous intéressent.

Gestion de la dette technique au fil de l’eau

Corriger les défauts les plus critiques nous coûte 59.5 jours, soit environ 12 jours pour une équipe de 5 développeurs.

Ramener la dette technique de notre application sur un SQALE Rating A nécessite près de 300 jours, et un peu plus de 3 mois pour notre équipe, ce que les managers ou les stakeholders vont probablement considérer un effort maximal, voire trop élevé.

Une solution intermédiaire consisterait en une gestion de la dette technique au fil de l’eau, c’est-à-dire en parallèle aux actions de maintenance de l’application. Chaque fois qu’un développeur devra effectuer une évolution ou une correction sur un programme, il utilisera également le plugin SQALE afin de vérifier :

  • Si la dette technique augmente. C’est l’utilisation principale pour un développeur d’un plugin tel que SQALE, comme nous en avons parlé dans le post précédent : éviter l’inflation régulière de la dette technique et de se retrouver au bout de quelques années avec une application inmaintenable.
  • S’il lui est possible de réduire celle-ci à l’occasion des modifications qu’il doit réaliser, en se centrant sur les règles que nous aurons définies comme critiques dans le plugin SQALE.
  • S’il n’a pas augmenté la dette technique après avoir implémenté ses modifications.

Inutile de demander au développeur de respecter plus de 10 best practices : au-delà, cela devient trop compliqué de toutes les retenir. Cela dépend également de l’expérience des développeurs et de leur niveau de connaissances, pour ne pas dire de maturité en matière de best practices. Mais même  les développeurs les plus expérimentés commettent des erreurs d’inattention et laisseront passer des défauts. D’où l’importance d’un suivi régulier de la dette technique.

Evidemment, le choix entre ces différentes propositions de plans d’action va dépendre, non seulement de l’effort à fournir, mais également de leur rentabilité. Pouvons-nous proposer au management une hypothèse de retour sur investissement ?

Comme ce post est déjà très long, je terminerai sur ce thème du ‘Refactoring avec SQALE’ par une synthèse de nos propositions et une tentative de calcul de ROI. Dans le prochain post.

Ce article est également disponible en Leer este articulo en castellano et Read that post in english.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *