Clean code et refactoring - 21 - Dette technique — quand elle est acceptable, quand elle tue le projet

La dette technique n'est pas toujours du mauvais code. C'est un compromis conscient avec des interets a payer.

  1. 01 Clean code et refactoring - 00 - Pourquoi le clean code est un investissement, pas un luxe
  2. 02 Clean code et refactoring - 01 - Nommage : la competence la plus sous-estimee
  3. 03 Clean code et refactoring - 02 - Fonctions : courtes, claires, responsables
  4. 04 Clean code et refactoring - 03 - Conditions et lisibilité : sortir de la pyramide
  5. 05 Clean code et refactoring - 04 - Commentaires et documentation : quand le code ne suffit pas
  6. 06 Clean code et refactoring - 05 - Immutabilite et effets de bord : moins de surprises, moins de bugs
  7. 07 Clean code et refactoring - 06 - Gestion des erreurs propre : fail fast, fail loud
  8. 08 Clean code et refactoring - 07 - Programmation defensive vs offensive : valider aux frontieres, faire confiance a l'intérieur
  9. 09 Clean code et refactoring - 08 - SOLID en pratique avec TypeScript
  10. 10 Clean code et refactoring - 09 - DRY, KISS, YAGNI
  11. 11 Clean code et refactoring - 10 - Couplage et cohesion
  12. 12 Clean code et refactoring - 11 - Complexite cyclomatique
  13. 13 Clean code et refactoring - 12 - Abstractions prematurees vs tardives
  14. 14 Clean code et refactoring - 13 - Code smells
  15. 15 Clean code et refactoring - 14 - Techniques de refactoring
  16. 16 Clean code et refactoring - 15 - Refactoring legacy sans tout casser
  17. 17 Clean code et refactoring - 16 - Tests comme filet de sécurité pour le refactoring
  18. 18 Clean code et refactoring - 17 - Structurer un projet — feature-based vs layer-based
  19. 19 Clean code et refactoring - 18 - Constantes, configuration et magic numbers
  20. 20 Clean code et refactoring - 19 - Linting et formatting — ESLint, Biome, automatiser la qualité
  21. 21 Clean code et refactoring - 20 - Conventions d'équipe et ADR
  22. 22 Clean code et refactoring - 21 - Dette technique — quand elle est acceptable, quand elle tue le projet
  23. 23 Clean code et refactoring - 22 - Code review — donner et recevoir du feedback
  24. 24 Clean code et refactoring - 23 - Glossaire — tous les termes de la serie

21 - Dette technique — quand elle est acceptable, quand elle tue le projet

Ce que tu vas apprendre

  • Ce qu'est vraiment la dette technique (et ce qui n'en est pas)
  • La différence entre dette intentionnelle et non-intentionnelle
  • Le quadrant de la dette de Martin Fowler
  • Comment mesurer la dette (SonarQube, CodeClimate)
  • Les interets de la dette : comment elle ralentit l'équipe
  • Comment rembourser : sprints dédiés vs boy scout rule
  • Comment expliquer la dette a des non-techniques
  • Quand accepter la dette sans culpabiliser

Prerequisites

Article précédent : 20 - Conventions


En 2020, je bossais sur une startup qui avait leve 2 millions d'euros. Le CTO avait décidé de "livrer vite et corriger apres". Le MVP a ete lance en 3 mois. Le produit marchait. Les clients signaient. Mais au bout d'un an, chaque nouvelle feature prenait trois fois plus de temps. Les bugs en production etaient hebdomadaires. Deux devs seniors ont demissionne parce qu'ils ne supportaient plus de travailler sur le codebase.

La startup a fini par passer six mois a reecrire le backend. Six mois sans nouvelle feature. Les clients sont partis chez la concurrence. La dette technique avait dépassé le seuil critique.

Ce qu'est vraiment la dette technique

Ward Cunningham a invente la metaphore en 1992. L'idee : prendre un raccourci technique, c'est comme emprunter de l'argent. Tu gagnes du temps maintenant, mais tu paies des interets plus tard sous forme de complexité accrue, de bugs et de ralentissement.

La confusion la plus courante : tout le mauvais code n'est pas de la dette technique. Un dev junior qui écrit du code sale par manque d'experience ne "contracte" pas de la dette. Il ne sait pas qu'il le fait. La dette technique est un choix delibere de prendre un raccourci en connaissance de cause.

typescript// Ceci est de la dette technique intentionnelle :
// On sait que c'est pas ideal, on le fait consciemment pour livrer plus vite
const users = await db.query("SELECT * FROM users"); // TODO: ajouter pagination
// Ticket TECH-342 cree pour corriger

// Ceci n'est PAS de la dette technique. C'est juste du code sale :
function x(d: any) {
  const r = d.map((i: any) => ({ ...i, v: i.a * 1.2 }));
  return r.filter((i: any) => i.v > 100);
}

La distinction compte. La dette technique a un ticket, un plan de remboursement. Le code sale a besoin d'un refactoring.

Le quadrant de la dette de Fowler

Martin Fowler a propose un quadrant qui classe la dette selon deux axes : intentionnelle vs non-intentionnelle, prudente vs imprudente.

Prudente Imprudente
Intentionnelle "On livre maintenant et on paye la dette dans le sprint suivant" "On n'a pas le temps de faire les tests"
Non-intentionnelle "Maintenant qu'on connaît mieux le domaine, on sait qu'on aurait du structurer autrement" "C'est quoi la séparation des responsabilités ?"

La dette prudente et intentionnelle est saine. C'est un compromis d'adulte. Tu sais ce que tu fais, tu documentes le raccourci, tu planifies le remboursement.

La dette imprudente et intentionnelle est dangereuse. "On n'a pas le temps de faire les tests" veut dire qu'on ne fera jamais les tests. Les interets s'accumulent vite.

La dette prudente et non-intentionnelle est inevitable. Au début d'un projet, tu ne connais pas assez le domaine pour faire les bons choix. Tu apprends en avancant. L'article sur le refactoring continu traite ce cas.

La dette imprudente et non-intentionnelle est du manque de competence. La solution n'est pas un plan de remboursement : c'est de la formation.

Mesurer la dette

Tu ne peux pas gerer ce que tu ne mesures pas. Plusieurs outils quantifient la dette technique :

SonarQube calcule un "effort de remediation" en jours. Il analyse la complexité cyclomatique, les duplications, les vulnérabilités de sécurité et la couverture de tests. Le chiffre est imprecis mais donne un ordre de grandeur.

CodeClimate attribue une note de maintenabilité (A a F) et identifié les fichiers les plus problématiques. La vue "hotspots" croise la complexité avec la fréquence de modification — un fichier complexe qui change souvent est une bombe a retardement.

En ligne de commande, des outils comme complexity-report ou les metriques de Biome donnent des indications locales :

typescript// Ce fichier a une complexite cyclomatique de 23
// SonarQube le marque comme "dette technique : 4 heures"
function processOrder(order: Order, user: User, config: Config): Result {
  if (!order.items.length) return { error: "empty" };
  if (!user.isActive) return { error: "inactive" };
  if (user.isBanned) return { error: "banned" };
  // ... 150 lignes de conditions imbriquees
}

Les metriques automatiques sont un point de depart. Elles ne remplacent pas le jugement humain. Un fichier marque "complexe" par SonarQube est parfois juste un fichier de routing avec beaucoup de cas. Le contexte compte.

Les interets de la dette : le ralentissement invisible

La dette technique ne casse pas le projet du jour au lendemain. Elle le ralentit progressivement. Le premier mois, l'équipe livre 10 features. Le sixieme mois, elle en livre 4. Le douzieme mois, 2. Les managers ne comprennent pas : "l'équipe a grossi, pourquoi on livre moins ?"

Les interets prennent plusieurs formes :

  • Temps de comprehension : comprendre du code complexe prend plus longtemps
  • Effet de cascade : un changement ici casse quelque chose la-bas
  • Tests manuels : sans tests automatiques, tout est vérifié a la main
  • Onboarding : les nouveaux devs mettent 3 mois au lieu de 3 semaines a etre productifs
  • Turnover : les bons devs partent parce que le code est frustrant

Le problème est que ces interets sont invisibles dans les metriques business. Aucun dashboard ne montre "temps perdu a cause de la dette technique". C'est pour ca que la dette s'accumule : elle est indolore a court terme. Pour approfondir ces sujets, tu peux consulter les articles sur paltemps.fr.

Rembourser la dette : deux stratégies

Les sprints dédiés : bloquer un sprint entier (ou une partie) pour rembourser de la dette. L'avantage est la visibilité : le management voit l'effort. L'inconvenient est le risque de "big bang refactoring" qui casse des choses et la difficulte de justifier des sprints sans feature visible.

La boy scout rule : chaque dev ameliore le code qu'il touche, a chaque commit. "Laisse le campement plus propre que tu ne l'as trouve." L'avantage est qu'il n'y a pas de sprint perdu, l'amelioration est continue. L'inconvenient est que les gros problèmes structurels ne se resolvent pas a coups de petites ameliorations.

La bonne stratégie combine les deux. La boy scout rule pour l'entretien quotidien. Les sprints dédiés pour les gros chantiers (migrer une librairie, restructurer un module, ajouter des tests sur un module critique).

typescript// Boy scout rule en action : tu modifies une fonction et tu l'ameliores au passage

// Avant (tu dois ajouter un parametre)
function calc(a: any, b: any, c: any) {
  const r = a * b;
  if (c) return r * 1.2;
  return r;
}

// Apres (tu ajoutes le parametre ET tu nettoies)
function calculateTotal(
  unitPrice: number,
  quantity: number,
  includeTax: boolean,
  discount: number = 0 // nouveau parametre
): number {
  const subtotal = unitPrice * quantity;
  const discounted = subtotal * (1 - discount);
  return includeTax ? discounted * 1.2 : discounted;
}

Communiquer la dette aux non-techniques

"On a de la dette technique" ne veut rien dire pour un product owner ou un CEO. Parle en termes business :

  • "Ajouter cette feature devrait prendre 2 jours. A cause de l'état du code, ca prend 2 semaines."
  • "On a 3 bugs en production par semaine. En nettoyant ce module, on peut descendre a 1."
  • "Le nouveau dev est productif en 3 mois au lieu de 3 semaines. Si on documente et restructure, on gagne 2 mois par embauche."

Les chiffres concrets parlent. Les abstractions techniques, non. Ne dis pas "on doit refactoriser le module de paiement". Dis "le module de paiement nous coûte 15 heures par sprint en corrections de bugs et en contournements. Si on investit 3 sprints pour le remettre en état, on récupéré ces 15 heures par sprint définitivement."

Quand accepter la dette

La dette technique n'est pas toujours mauvaise. Il y a des situations ou elle est le bon choix :

Prototypes et POC : tu valides une idee. Si ca ne marche pas, tu jettes le code. Investir dans la qualité d'un prototype qu'on va peut-etre jeter, c'est du gaspillage.

Deadlines dures : un salon professionnel, un lancement marketing, une date contractuelle. Livrer un produit imparfait a temps vaut mieux que livrer un produit parfait trop tard.

Experimentation : tu testes une hypothese. L'objectif est d'apprendre, pas de construire du durable. Le code est jetable par design.

La condition : documente la dette. Un commentaire // TECH-DEBT: ... avec un ticket associe. Sans ca, la dette "temporaire" devient permanente. J'ai vu des // TODO: temporary fix dater de 2017 en production en 2025.

Résumé

  • La dette technique est un choix delibere, pas du code sale par accident
  • Le quadrant de Fowler aide a classifier la dette : prudente/imprudente, intentionnelle/non-intentionnelle
  • SonarQube et CodeClimate quantifient la dette mais ne remplacent pas le jugement humain
  • Les interets de la dette sont invisibles mais réels : ralentissement, bugs, turnover
  • Combine la boy scout rule (entretien quotidien) et les sprints dédiés (gros chantiers)
  • Communique en termes business : heures perdues, bugs evites, temps d'onboarding
  • La dette est acceptable pour les prototypes, deadlines dures et experimentations — si elle est documentee

Article précédent : 20 - Conventions

Article suivant : 22 - Code review

Sources

Réservez un audit gratuit de 30 minutes. Je vous montre concrètement ce qu'on peut automatiser.