Dette technique¶
Identifier, classifier et gérer la dette technique — un levier strategique quand elle est délibérée, un risque systémique quand elle est invisible.
Définition¶
Le terme "dette technique" a été introduit par Ward Cunningham en 1992. L'analogie avec la dette financiere est délibérée : on emprunte de la vitesse à court terme en acceptant un coût de maintenance à long terme. Comme pour la dette financiere, le problème n'est pas d'en avoir — c'est de ne pas savoir combien on en a, ni de ne pas la rembourser.
La dette technique, ce n'est pas du "mauvais code". C'est l'ecart entre l'état actuel du système et l'état qu'il devrait avoir pour supporter les exigences actuelles et a venir. Cet ecart peut être délibéré (on a fait un choix pragmatique en connaissance de cause) ou involontaire (on ne savait pas qu'on créait de la dette).
Le quadrant de Fowler¶
Martin Fowler a propose un quadrant qui classe la dette technique selon deux axes : délibérée vs involontaire, et prudente vs imprudente.
quadrantChart
title Quadrant de la dette technique
x-axis "Imprudente" --> "Prudente"
y-axis "Involontaire" --> "Deliberee"
quadrant-1 "Deliberee + Prudente"
quadrant-2 "Deliberee + Imprudente"
quadrant-3 "Involontaire + Imprudente"
quadrant-4 "Involontaire + Prudente" | Quadrant | Exemple | Posture |
|---|---|---|
| Délibérée + Prudente | "On livre sans cache, on l'ajoutera quand le trafic le justifiera" | Acceptable — documenter dans un ADR |
| Délibérée + Imprudente | "On n'a pas le temps de concevoir, on code directement" | Dangereuse — souvent sous-estimée |
| Involontaire + Prudente | "On ne connaissait pas le pattern CQRS quand on a commence" | Naturelle — on apprend en construisant |
| Involontaire + Imprudente | "C'est quoi les bounded contexts ?" | Structurelle — nécessité formation |
La dette délibérée et prudente est la seule forme acceptable à long terme. Les autres formes doivent être identifiées et traitees avant qu'elles ne deviennent systemiques.
Identification de la dette technique¶
La dette technique est souvent invisible dans les outils de suivi classiques. On la détecté par plusieurs signaux complementaires.
Métriques de code¶
| Métrique | Outil | Signal de dette |
|---|---|---|
| Complexité cyclomatique | radon, lizard | > 15 par fonction |
| Couplage afferent/efferent | jdepend, deptry | Ratio instabilite proche de 0.5 |
| Duplication de code | jscpd, CPD | > 5% du codebase |
| Taille des fichiers | cloc, tokei | > 500 lignes par fichier |
| Âge du code non modifie | git log | Modules critiques non touches > 1 an |
| Couverture de tests | pytest-cov, istanbul | < 60% sur les modules core |
Analyse de couplage¶
Le couplage est le premier indicateur de dette architecturale. Un système fortement couple résisté au changement — modifier un module en casse trois autres.
# analyse_couplage.py
# Mesure le couplage entre modules via les imports
from pathlib import Path
import ast
from collections import defaultdict
def analyse_coupling(src_dir: str) -> dict[str, list[str]]:
"""Construit le graphe de dependances entre modules."""
deps = defaultdict(set)
for py_file in Path(src_dir).rglob("*.py"):
module = py_file.parts[1] if len(py_file.parts) > 1 else None
if not module:
continue
with open(py_file) as f:
try:
tree = ast.parse(f.read())
except SyntaxError:
continue
for node in ast.walk(tree):
if isinstance(node, ast.ImportFrom) and node.module:
parts = node.module.split(".")
if len(parts) > 1 and parts[0] == "src":
target = parts[1]
if target != module:
deps[module].add(target)
return {k: sorted(v) for k, v in deps.items()}
Velocite de l'équipe¶
La dette technique se manifeste aussi dans les métriques d'équipe :
- Temps de livraison croissant — les features simples prennent de plus en plus de temps
- Ratio bug/feature croissant — on passe plus de temps a corriger qu'a construire
- Onboarding lent — les nouveaux développeurs mettent des semaines a être productifs
- Zones de code "intouchables" — des modules que personne n'ose modifier
- Contournements fréquents — les développeurs ajoutent des couches d'abstraction plutôt que de corriger le problème sous-jacent
- Reviews de plus en plus longues — la complexité du code rend les revues plus difficiles et plus longues
Note
La velocite de l'équipe est le signal le plus fiable de dette technique. Les métriques de code sont des indicateurs — la velocite est la conséquence réelle.
Classification : sévérité et effort¶
Une fois la dette identifiée, on la classe selon deux axes pour prioriser le traitement.
Matrice sévérité x effort¶
quadrantChart
title Priorisation de la dette technique
x-axis "Effort faible" --> "Effort eleve"
y-axis "Severite faible" --> "Severite elevee"
quadrant-1 "Planifier"
quadrant-2 "Quick wins"
quadrant-3 "Reporter"
quadrant-4 "Ignorer" | Quadrant | Action | Exemple |
|---|---|---|
| Quick wins | Traiter immédiatement | Renommer un module mal nomme |
| Planifier | Intégrer dans le prochain cycle | Extraire un service couple |
| Reporter | Documenter, surveiller, traiter quand l'effort diminue | Migration de framework |
| Ignorer | Accepter explicitement (dette prudente) | Code legacy stable non modifie |
Scoring de la dette¶
Pour chaque item de dette identifié, on attribue un score sur trois dimensions :
- Impact (1-5) : conséquence sur la velocite, la fiabilité, la sécurité
- Probabilite d'aggravation (1-5) : risque que la dette empire si non traitee
- Effort de remédiation (1-5) : coût de correction en jours-équipe
Le score de priorité = (Impact * Probabilite) / Effort. Les items avec le score le plus élevé sont traites en premier.
Stratégies de remédiation¶
Boy scout rule¶
"Laisse le code un peu plus propre que tu ne l'as trouve." Chaque PR qui touche a une zone de dette inclut une amélioration incrementale. Pas de refactoring massif — des petites améliorations constantes.
Efficace pour la dette de faible sévérité et de faible effort. Inefficace pour la dette structurelle qui nécessité un changement coordonné.
Tech debt sprints¶
Dedier régulièrement du temps au remboursement de la dette. Deux modèles :
- Pourcentage fixe : 20% du temps de chaque sprint est réservé à la dette technique. Simple a mettre en place, difficile à maintenir quand la pression augmente.
- Sprint dédié : un sprint sur quatre ou cinq est entièrement dédié à la dette. Plus visible, plus impactant, mais crée un cycle "on accumule puis on rembourse".
Strangler fig pattern¶
Pour la dette structurelle massive (monolithe a decomposer, migration de stack), le strangler fig pattern permet de remplacer progressivement un système existant sans big bang.
flowchart LR
CLIENT["Client"] --text--> PROXY["Proxy / Gateway"]
PROXY --"ancien"--> LEGACY["Systeme legacy"]
PROXY --"nouveau"--> NEW["Nouveau systeme"]
LEGACY -.->|"migration\nprogressive"| NEW Le principe : on intercale un proxy devant le système existant. Les nouvelles fonctionnalités vont dans le nouveau système. Les anciennes fonctionnalités sont migrees progressivement. Le système legacy retrecit jusqu'à disparaitre.
Refactoring continu¶
Le refactoring n'est pas un projet — c'est une pratique quotidienne. Les refactorings structurels (extraction de module, changement de pattern de communication) sont planifies comme des features. Les refactorings locaux (simplification, renommage, extraction de fonction) sont faits au fil de l'eau.
Tracking de la dette¶
Backlog de dette technique¶
La dette technique doit avoir son propre backlog, visible et priorise. Chaque item de dette est un ticket avec :
- Description : qu'est-ce qui ne va pas ?
- Impact : quelle conséquence si on ne fait rien ?
- Proposition : quelle approche de remédiation ?
- Score : priorité calculee (impact * probabilite / effort)
- Owner : qui est responsable du suivi ?
Fitness functions comme gardes¶
Les fitness functions (chapitre précédent) servent aussi de gardes contre l'aggravation de la dette. Une fois qu'on a identifié un problème de couplage, on pose une fitness function qui empêche le couplage d'augmenter — même si on ne le réduit pas immédiatement.
# fitness/test_coupling_guard.py
COUPLING_BASELINE = {
"order": {"catalog": 3}, # 3 imports existants (dette connue)
"notification": {"order": 1},
}
def test_coupling_does_not_increase():
"""La dette de couplage ne doit pas augmenter."""
current = analyse_coupling("src")
for module, deps in COUPLING_BASELINE.items():
for target, max_count in deps.items():
actual = count_imports(module, target)
assert actual <= max_count, (
f"Couplage {module} -> {target} a augmente: "
f"{actual} > {max_count} (baseline)"
)
Communication de la dette au management¶
La dette technique est un concept d'ingénierie. Le management raisonne en termes de risques, de coûts et de délais. Pour obtenir du temps pour rembourser la dette, il faut traduire.
Le langage du risque¶
Ne pas dire : "il faut refactorer le module Order". Dire : "le module Order a un couplage critique qui fait que chaque nouvelle feature prend 3 fois plus de temps que prévu. Si on ne le traite pas, le prochain release cycle prendra 8 semaines au lieu de 3."
Métriques parlantes¶
| Métrique technique | Traduction management |
|---|---|
| Complexité cyclomatique > 25 | Chaque modification risque d'introduire un bug |
| Couverture tests < 40% | On ne détecté les bugs qu'en production |
| 5 dépendances avec CVE critique | Risque de sécurité non couvert |
| Couplage inter-modules élevé | Impossible de livrer un module sans toucher 3 autres |
Visualiser la tendance¶
Un graphique montrant l'évolution du temps de livraison par feature sur 6 mois est plus convaincant que n'importe quel argumentaire technique. Si la courbe monte, la dette est en train de gagner.
Tableau de bord de dette¶
| Indicateur | Source | Tendance souhaitee |
|---|---|---|
| Nombre d'items de dette | Backlog | Stable ou baissier |
| Score total de dette | Backlog (somme) | Baissier |
| Ratio dette / features | Sprint metrics | < 20% |
| Complexité cyclomatique moyenne | SonarQube, radon | Stable ou baissier |
| Couverture de tests | CI | Croissant |
| Temps de livraison moyen | DORA metrics | Stable ou baissier |
Tip
La dette technique zero n'existe pas — et n'est pas souhaitable. L'objectif est de maintenir la dette à un niveau maîtrise et délibéré, pas de l'éliminer. On géré la dette technique comme on géré la dette financiere : on sait combien on doit, on paie les intérêts, et on rembourse le principal quand c'est strategiquement pertinent.
Chapitre suivant : Architecture Repository — centraliser les standards, patterns et décisions dans un référentiel vivant.