Comment quantifier l’inflation de la dette technique ?

Article original : How to quantify technical debt inflation | Belay the C++ (belaycpp.com)
Traductrice : Chloé Lourseyre

Si vous travaillez pour une société de développement logiciel, vous vous êtes sans doute retrouvé dans le cas où vous aviez une dette technique à résoudre, mais où vous n’aviez pas l’approbation de votre hiérarchie pour le faire dans l’immédiat. « On verra ça plus tard », comme ils disent. Mais en bon·ne développeur·se, vous savez deux choses : la dette technique est de plus en plus dure à résoudre au fil du temps, et l’impact d’une dette technique stagnante ajoute un surcoût à chaque ajout de code qui est fait entre-temps.

Quand vous essayez d’argumenter que « la dette technique est coûteuse », vous vous retrouvez souvent face à la question « coûteuse de combien ? ». Mais vous n’avez pas de réponse à cela, car (à l’heure où cet article est rédigé) il n’y a pas de moyen connu pour prédire l’avenir.

C’est ce que j’appelle la problème d’Inflation de la Dette Technique, ou TDI (pour Technical Debt Inflation).

Avertissement : Je ne peux pas vraiment résoudre le sempiternel problème de la TDI dans un article de deux mille mots. Ce que je donne ici est un fruit de réflexion, l’ouverture d’un débat, une ligne d’approche pour vous pousser à mener votre propre réflexion sur le sujet. J’espère que vous pourrez l’apprécier.

Qu’est-ce que la dette technique ?

On peut définir la dette technique comme étant une partie du code qui est mal conçue et qui a besoin d’être réécrite pour être efficace. Elle n’a pas d’impact pour l’utilisateur, mais rend le code plus dur à maintenir et cela complexifie le développement de nouvelles fonctionnalités (on se limitera à cette définition pour cet article).

Souvent, elle apparaît quand on choisit une approche à court terme plutôt qu’une solution sur le long terme. Cela coûte plus de temps d’écrire une solution au long terme sur le moment, mais une version à court terme se repaye toujours dans le futur.

Qu’est-ce que l’inflation de la dette technique ?

Une dette technique est coûteuse de deux manières.

Premièrement, elle est coûteuse à résoudre. Corriger une dette technique prend du temps, et puisqu’elle est invisible du point de vue de l’expérience utilisateur et de la hiérarchie, c’est souvent considéré inutile par ceux-ci.

Secondement, il est coûteux de travailler « proche » d’une dette technique. Elles ont très souvent des impacts autour d’elles, dans la manière de développer de nouvelles fonctionnalités ou de les maintenir. Par exemple, une dette technique peut être une interface contre-intuitive, qui nécessite plus de temps pour s’y habituer qu’une interface ergonomique. Autre exemple, si un module est mal rédigé, toute mise à jour en son sein coûtera sensiblement plus de temps que s’il était bien conçu.

L’inflation de la dette technique est le fait que plus on attend longtemps pour la résoudre, plus ces coûts augmentent.

En effet, plus le temps passe et plus la quantité de code affectée sera grande (puisqu’il y aura de plus en plus de code dépendant de cette dette) et plus il sera difficile de la maintenir.

Quel est l’intérêt de quantifier la dette technique et son inflation ?

Mesurer l’amplitude de l’impact d’une dette technique est compliqué. Il est encore plus dur de justifier une telle évaluation à celles et ceux qui approuveront -ou pas- le travail que ça implique.

Si on arrive à concevoir un modèle qui met des nombres sur la dette technique, il sera plus facile de justifier de la nécessité résoudre celle-ci au plus tôt.

On pourrait avancer des arguments comme « Oui, ça nous coûterait trois jours de corriger cette dette maintenant, mais si on ne le fait pas, dans deux ans elle aura, en tout et pour tout, coûté en moyenne deux heures par semaines par développeuse et développeur, pour un total de cinquante jours à la fin de la deuxième année… ». Cela pourrait aider à mettre en perspective la vision de la hiérarchie.

Mais je dois bien admettre que la chose la plus importante ne sont pas les nombres eux-mêmes, mais les arguments qui se basent dessus.

Comment quantifier la dette technique ?

La dette technique est coûteuse à résoudre. La première étape est d’évaluer combien de temps une dette prendrait à résoudre aujourd’hui. Sans ça, on ne pourra pas évaluer l’inflation de ce coût.

Par chance, c’est souvent assez facile à évaluer. En se basant sur sa propre expérience du code, on est souvent en mesure de donner une estimation du temps nécessaire à la résolution d’une dette.

En général, je conseillerais de multiplier toute évaluation raisonnable par deux ou trois, afin de prendre en compte les impondérables.

Si vous travaillez en équipe, il est sage de baser son estimation sur la personne la plus « lente » de l’équipe, car vous ne serez peut-être pas la personne qui résoudra effectivement la dette, et si vous travaillez plus rapidement que vos collaborateurs, l’évaluation risque d’être faussée.

Une fois cela fait, on peut maintenant évaluer l’inflation de la dette technique.

Comment quantifier l’inflation ?

La chose la plus importante à retenir à propos de l’inflation est qu’elle n’est pas linéaire.

En fait, vu qu’il y a deux axes sur lesquels la dette technique augmente (le surcoût de correction et le surcoût d’utilisation), et qu’ils subissent tous deux l’inflation, alors cette inflation est, a minima, quadratique1. Elle n’est pas proportionnelle au temps, mais au temps au carré.

S’il n’y qu’une chose à retenir de cet article, c’est cela : la TDI est quadratique.

Maintenant, comment évaluer (numériquement) cette inflation ?

Un indicateur simple et utilisable est la taille du code. La taille du code tend à augmenter avec le temps, et si on arrive à avoir un modèle qui extrapole la taille du code dans le futur à partir de son évolution dans le passé, alors on pourra estimer la taille du code dans le futur.

Je vous donne un exemple de méthode d’évaluation de la taille du code dans un des addenda.

À partir de là, il suffit d’appliquer un facteur quadratique sur cette évolution pour obtenir une évaluation de l’inflation de la dette. C’est ce que j’appelle le modèle de Croissance Quadratique (ou Quadratic Expansion dans la langue de Sutter).

Formalisation du modèle de Croissance Quadratique

Soit C0 la taille du code à t0.
Soit C1 la taille du code à t1.
Soit D0 le temps estimé pour résoudre la dette technique à t0.
Soit D1 le temps estimé pour résoudre la dette technique à t1.
Soit I01 le temps perdu à cause de l’impact de la dette technique entre t0 et t1.
Soit Δ01 le total de temps cumulé qu’a coûté la dette technique entre t0 et t1.

C0, C1 et D0 sont des valeurs connues.
D1 et I01 sont des valeurs intermédiaires.
Δ01 et l’objectif du modèle.

D1 = D0 × C1 ÷ C0

I01 = Λ × C1 ÷ C0, où Λ est une constante qu’on appellera “facteur lambda”2.

Δ01 = (I01 × D1) – D0

Δ01 = Λ × D0 × (C1 ÷ C0)2 – D0

Pour simplifier le calcul, supposons Λ = 1 (on cherche à évaluer un ordre de grandeur, pas à avoir une mesure précise), ce qui donne

Δ01 = D0 × ( (C1 ÷ C0)2 – 1 )

Exemple

Vous avez une dette technique conséquente à résoudre. Votre supérieur hésite à la retarder de six (pour des raisons de jalon de livraison). Vous lui dites que ça coûterait du temps en plus de la reporter, et iel vous demande de quantifier à quel point.

À l’heure actuelle, la fonctionnalité concernée est composée de 21,6 milliers de lignes de code. Il y a trois mois, elle était composée de 17,8 milliers de lignes. Le code a donc gonflé de 3,8 milliers de lignes dans cet intervalle. Cependant, votre équipe (composée de quatre développeur·se·s) vient de se voir renforcée avec un nouvel arrivant, ce qui fait un total de cinq devs. Donc au cours des six prochains mois, on peut estimer que le code grossira d’environ 9,5 milliers de lignes supplémentaires (38×2×1,25).

Votre estimez qu’il faudrait une semaine entière (5 jours) pour résoudre la dette technique.

C0 = 21.6k

C1 = 31.1k

D0 = 5 jours

Δ01 = D0 × ( (C1 ÷ C0)2 – 1 ) ≈ 5.4 jours

Conclusion : selon le modèle de croissance quadratique, l’attente coûterait environ cinq jours et demi supplémentaires.

Vous annoncez donc à votre hiérarchie que, compte tenu de la productivité de l’équipe, attendre six fera plus que doubler le temps perdu à résoudre la dette (en incluant sa correction et le temps perdu à la maintenir).

Les limites de ce modèle

Ce modèle a de grosses limitations.

  • Premièrement, le calcul n’est pas transitif. E.g. Δ02 ≠ Δ01 + Δ12. Cela reflète le fait que plus on porte son regard loin (0 → 2), plus le coût de la dette est incertain. Mathématiquement, il faudrait refléter cela avec un intervalle de confiance.
  • Évaluer et extrapoler la taille du code est souvent faisable, mais pas toujours trivial.
  • Surtout, ce modèle n’a jamais été démontré en pratique.

La question à un million d’euros

Il y aurait bien, en théorie, une manière d’évaluer mathématiquement la problématique TDI : en agrégeant des données recueillies sur des centaines de projets à travers les années. Mais ce n’est pas une tâche simple, sinon impossible. En voici les raisons :

  • Cela voudrait dire ingérer dans le code détenu par des sociétés privées.
  • Même en rétrospective, il est complexe d’évaluer l’impact qu’a eu une dette technique.
  • L’étude prendrait des années, sinon des décennies à être complétée, car les impacts d’une dette technique se mesurent dans le temps.

Avec ça en tête, agréger des données réelles dans une étude sérieuse semble impossible. Mais peut-on élaborer un protocole de plus petite échelle qui pourrait nous aider à résoudre la problématique de la TDI ? Ça mérite réflexion.

Conclusion

Je le redis, pour éviter toute ambiguïté : le modèle de Croissance Quadratique est une manière limite, peu précise et non-scientifique d’évaluer l’inflation de la dette technique, mais elle permet d’avoir un ordre de grandeur cohérent en faveur d’une refonte tôtive du code.

J’espère que ce sera le prélude d’étude plus sérieuse sur le problème de la TDI.

Souvenez-vous qu’évaluer le temps « perdu » d’une dette technique existante est loin d’être trivial et qu’un protocole d’évaluation est impossible à petite échelle.

Mais j’espère que ça vous aidera à avoir une idée plus nette du coût concret des dettes techniques.

Merci de votre attention et à la prochaine !

Article original : How to quantify technical debt inflation | Belay the C++ (belaycpp.com)
Traductrice : Chloé Lourseyre

Addenda

Comment évaluer la taille du code? Un exemple

Avec Git et un shell Linux, vous pouvez facilement évaluer la taille du votre code.

git ls-files Liste tous les fichiers.

grep -E '\.(cpp|h|hpp)$' est un filtre sur les fichiers de source et d’en-tête.

wc -l compte le nombre de lignes.

Voici la commande complète :

git ls-files | grep -E '\.(c|cpp|h|hpp)$' | xargs -d '\n' wc -l

(NB : xargs permet d’alimenter la sortie dans la commande  wc. L’option -d '\n' est présente pour échapper les espaces dans les noms de fichier)

Alternativement, vous pouvez utiliser wc -m à la place de wc -l pour compter les caractères au lieu des lignes. C’est un peu plus lent et moins intuitif, mais à mon avis une meilleure métrique que le nombre de lignes.

Pour que le résultat soit plus lisible, vous pouvez faire

grep -E '^ *[0-9]+ total$' pour récupérer uniquement la ligne de total.

sed -r 's/^ *([0-9]+) total$/\1/' enlève les informations superflues.

La commande complète est désormais :

git ls-files | grep -E '\.(c|cpp|h|hpp)$' | xargs -d '\n' wc -l | grep -E '^ *[0-9]+ total$' | sed -r 's/^ *([0-9]+) total$/\1/'

Si vous avez plusieurs sous-modules, vous pouvez :

Ajouter --recurse-submodules pour que l’opération soit récursive.

awk '{s+=$1} END {print s}' somme les valeurs de totaux.

Ligne de commande finale :

git ls-files --recurse-submodules | grep -E '\.(c|cpp|h|hpp)$' | xargs -d '\n' wc -l | grep -E '^ *[0-9]+ total$' | sed -r 's/^ *([0-9]+) total$/\1/' | awk '{s+=$1} END {print s}'

Notes

  1. C’est basé sur cette idée : puisqu’il y a deux coûts qui augmentent et que ces deux coûts sont entremêlés, leur combinaison est multiplicative plutôt qu’additive. Cela fait que, d’après moi, l’inflation est quadrative.
  2. Λ représente à quel point le reste du code dépend de la dette technique. Plus l’impact est important, plus Λ sera grande, et donc plus I01 sera grand à son tour. Pour des raisons de simplification, Λ est ici considérée constante.
  3. Est-il seulement possible de concevoir un protocole qui permettrait d’évaluer la justesse de n’importe quel modèle de TDI ? Puisqu’on ne peut réaliser qu’une des deux actions (résoudre la dette dans l’instant ou la résoudre plus tard) il n’y a aucun moyen d’évaluer avec certitude le temps qu’aurait pris l’alternative. De plus, le temps nécessaire pour résoudre une dette dépend des compétences de la personne qui la raison et, il faut bien l’avouer, de la chance. En plus de cela, le modèle est conçu pour inclure un risque, ce qui signifie que l’inflation estimée sera grande pour y inclure ce risque. Il n’y a (à ma connaissance) aucun moyen de vérifier ce genre de représentation abstraite.

Combien de langages un expert (en C++) doit savoir parler ?

Article original : How many languages should a (C++) expert speak? | Belay the C++ (belaycpp.com)
Traductrice : Chloé Lourseyre

Cet article est une relecture du Lightning Talk que j’ai donné à l’occasion de la CppCon 2020 : How many languages a (C++) expert should speak ? – Thomas Lourseyre – CppCon 2020 – YouTube

Je vais essayer d’élaborer ce que cet interlocuteur (au demeurant stressé et fébrile) essaie de montrer dans cette présentation.

Pourquoi apprendre d’autres langages ?

Je vais partir du principe que vous êtes un(e) développeur(se) C++ et expliquer pourquoi vous devez connaître d’autres langages de programmation en utilisant deux citations.

Si tout ce que vous avez est un marteau, tous les problèmes ressemblent à un clou.
– Marteau de Maslow

Disons qu’on vous donne la tâche de résoudre un problème, un fait technique ou un dilemme de programmation. Une des premières questions que vous aurez à vous poser sera « Quel langage devrais-je utilise pour résoudre cela ? ». Si vous ne connaissez que le C++, vous ne pourrez répondre que « C++ ». Mais, de manière assez évidente, le C++ ne peut pas être toujours la bonne réponse.

Même si vous n’êtes pas expert(e) dans d’autres langages, si vous connaissez les bases et êtes capable de dire « Conceptuellement, ce langage est plus adapté à ce problème », alors vous n’aurez plus qu’à trouver un expert dans ledit langage et le tour sera joué. C’est une forme de recul que vous ne pouvez pas avoir si vous ne vous intéressez qu’à un seul langage.

Ceux qui ne peuvent se souvenir du passé sont condamnés à le revivre.
– George Santayana

L’industrie du développement logiciel n’est pas un paradis rose et sucré où tous les projets commencent avec tous les outils dont on peut rêver dans leur version la plus récente. Parfois (voire souvent, en fonction de comment vous vous positionnez dans l’industrie) vous devrez travailler sur du code legacy. Parfois, il sera écrit en C++ et vous devrez le porter dans un autre langage. Et parfois, il sera écrit dans un autre langage et vous devrez le traduire en C++.

Dans tous les cas, vous ne pourrez faire ce travail que si vous connaissez d’autres langages que le C++.

Posons la vraie question

Tout cela étant dit, je peux affirmer sans crainte que la vraie question n’est pas « Devrais-je apprendre d’autres langages ? » mais plutôt :

Combien d’autres langages devrais-je apprendre ?

Le tableau de répartition des connaissances

J’ai conçu un petit tableau permettant de classer les langages de programmation qu’une personne connaît en fonction de leur niveau de connaissance :

Niveau de connaissanceDétailsExemples personnels
ExpertC’est pas grave si vous n’en connaissez qu’un seulC++
PratiqueLes langages que vous aimez et pratiquez sur une base régulière.Python, C, Rust, Bash
DocumentationLes langages que vous avez pratiqué mais que vous n’aimez pas. Vous êtes capable vous documenter.Java, C#, js, basic, perl
Hello word!Vous ne connaissez pas grand chose à leur propos.Ruby, AS, Go, etc.

Vous pouvez d’ailleurs remarquer (en comparant avec la vidéo) que mes exemples personnels ont évolué depuis l’année dernière – ce qui est rassurant.

Les niveaux de connaissance

  • Expert : Ce sont les langages pour lesquels vous avez une expertise poussée et fiable. Beaucoup de développeurs ne sont pas particulièrement experts et la plupart de ceux qui le sont n’ont qu’un seul langage d’expertise. Il est possible d’en avoir plusieurs bien sûr, mais c’est assez rare et requiert beaucoup d’efforts.
  • Pratique : Ce sont les langages que vous pratiquez sur une base régulière, sans pour autant en être un(e) expert(e). Souvent ce sont des langages que vous aimez bien et que vous utilisez lors de vos projets personnels.
  • Documentation : Il y a probablement des langages que vous avez essayés, mais qui ne vous ont pas spécialement plu. Ou bien des langages que vous avez dû apprendre pour un projet spécifique, mais vous êtes empressé(e) d’oublier après. Ce sont des langages dont vous connaissez au moins les bases et pour lesquels vous êtes capable de vous documenter si nécessaire.
  • Hello world! : Ce sont les langages dont vous ne savez que très peu de choses. Souvent vous les connaissez de nom, peut-être avez déjà rédigé un Hello world!, mais sans plus. Vous n’êtes ainsi pas capable de citer les spécificités fondamentales du langage.

Les seuls niveaux de connaissances utiles sont expertpratique et documentation. À partir du moment où vous êtes capable de savoir où et comment consulter la documentation d’un langage, vous pouvez en faire quelque chose. Le niveau Hello world! est lui inutile.

Comment promouvoir un langage

Votre but est donc maintenant de « promouvoir » les langages pour les faire monter dans le tableau. Mais les efforts nécessaires à cela varient en fonction de là où se trouve chaque langage :

  • De pratique à expert : Devenir un expert est une tâche longue et difficile, quel que soit le domaine. Vous n’avez pas à devenir expert(e) dans un langage à moins que vous ne vouliez y dédier une partie conséquente de votre carrière ou de votre temps libre. C’est un gros gaspillage d’effort de devenir expert dans un langage juste pour être plus polyvalent.
  • De documentation à pratique : Si vous vous forcez à pratiquer un langage que vous n’aimez pas, il y a une bonne chance pour que vous finissiez par le détester encore plus. Bien sûr, vous pouvez toujours avoir une bonne surprise (et vous rendre compte que vous aimez un langage que vous détestiez au départ), mais cela n’arrivera pas souvent. On ne peut pas forcer l’amour, si vous tentez de sur-pratiquer un langage que vous n’aimez pas pour être plus polyvalent est une forme de souffrance assez inutile.
  • De Hello world! à documentation : Qu’est-ce qu’il en coûte d’essayer un langage dont vous ne connaissez que peu de choses dans le but de vous faire un avis ? En l’espace de quelques heures, vous pourrez lire la note d’intention du langage, apprendre les bases et savoir où se trouve la documentation. Peut-être n’aimerez-vous pas ce langage, mais au moins vous en saurez un peu plus à son propos.

La promotion la plus rentable est la dernière, de Hello world! à documentation. Si vous êtes curieux(se) et essayez d’apprendre le pourquoi du comment du plus grand nombre de langages possibles, alors vous aurez une vue beaucoup plus large du monde de la programmation.

Du coup, combien de langages devriez vous savoir parler ?

La réponse que je vais vous donner aujourd’hui est la suivante : autant que ce que votre curiosité vous le permet.

Une des plus grandes qualités qu’un expert peut avoir (que ce soit en C++ ou non) est sa curiosité. Ce qui nous pousse à en apprendre plus, chaque jour, à propos de n’importe quel sujet. Tant que vous serez curieux(se), vous vous enrichirez et grandirez.

Ne gaspillez pas votre curiosité sur un unique sujet, la curiosité est une qualité mieux employée en largeur qu’en profondeur. D’après moi, un bon expert est aussi un polytechnicien.

Avec quelle régularité devriez-vous apprendre des nouveaux langages et entretenir ceux que vous connaissez ?

La réponse à cette question est très dépendante du temps libre que vous voulez allouer à la programmation.

Si, à un moment donné, vous avez juste une heure de temps libre que vous voulez investir dans la programmation, prenez un langage dont vous ne connaissez rien (ou presque). Lisez la note d’intention et écrivez un petit programme simple. Normalement, ce sera suffisant pour que vous sachiez si vous voulez y investir plus de temps ou non. Si c’est non, gardez en tête comment accéder à la documentation, ça pourra toujours être utile.

Si un langage que vous venez de découvrir vous plaît, essayez d’évaluer combien de temps vous pouvez passer pour vous y entraîner. Vous pouvez faire des tutoriels, des exercices, des projets personnels.

Il y a un bon moyen de s’entraîner dans vos langages favoris : les plateformes comme CodinGame vous propose de l’entraînement, des défis et des compétitions de codage. Essayez, c’est très addictif !

Coding Games and Programming Challenges to Code Better (codingame.com).

Est-ce un exercice réservé aux experts ?

Je peux entendre supprimer certains d’entre vous derrière votre écran, « Je ne suis même pas expert(e) en C++, dois-je vraiment prendre la peine d’apprendre un autre langage ? ».

Tous les arguments que j’ai détaillés dans cet article sont valables pour les non-experts aussi bien que pour les experts. La différence est que, selon mon expérience personnelle, les personnes « non-expertes » sont plus à même de changer de langage au cours de leur carrière. Connaître plusieurs langages vous permettra donc d’avoir de l’avance et un peu plus de recul sur les possibilités qui pourront s’offrir à vous.

La curiosité est une excellente qualité, dans le développement logiciel.

Merci de votre attention et à la semaine prochaine !

Article original : How many languages should a (C++) expert speak? | Belay the C++ (belaycpp.com)
Traductrice : Chloé Lourseyre