Aller au contenu principal

17. Refactorer : améliorer la structure sans négocier le comportement

Pourquoi ce chapitre existe

Le refactoring est souvent annoncé comme une opération « sans risque » parce qu'il ne change pas l'intention fonctionnelle. C'est une propriété visée, jamais une garantie. Déplacer une règle peut modifier une valeur par défaut, un ordre d'exécution, une transaction, une erreur ou une performance. Sans définition claire du comportement préservé, le refactoring devient une réécriture masquée.

Refactorer est néanmoins indispensable : c'est l'investissement qui maintient le coût de compréhension et de changement sous contrôle. La sécurité vient de petits pas, de contraintes de comportement et d'une séparation honnête entre restructuration et nouvelle capacité.

Les idées essentielles

  • Un refactoring change la représentation interne tout en préservant les comportements observables convenus.
  • Le comportement inclut les résultats, mais parfois aussi les erreurs, les performances, les transactions, les événements et la sécurité.
  • La meilleure préparation est une caractérisation : établir ce que le système fait réellement avant de décider ce qu'il devrait faire.
  • Mélanger refactoring et changement métier augmente l'ambiguïté de revue et rend le diagnostic coûteux.

Créer une base de sécurité

Dans un système bien compris, les tests existants et les contrats fournissent une partie de la sécurité. Dans un système legacy, ils peuvent manquer précisément là où le changement est nécessaire. Il faut alors commencer par des tests de caractérisation, des observations de données ou des parcours exécutés en environnement réaliste. Leur but est de capturer le comportement actuel, y compris lorsqu'il semble étrange, afin de ne pas le modifier par accident.

Le cycle robuste est simple : choisir une petite transformation ; exécuter les preuves de comportement ; vérifier le diff ; intégrer ; recommencer. Plus une étape est petite, plus une divergence est attribuable. Une transformation mécanique massive peut rester sûre si elle est automatisée, revue sur échantillons et encadrée par des vérifications fortes ; elle doit être traitée comme telle, non comme un simple ménage.

Anti-patterns

Réécrire pour « repartir propre »

La réécriture concentre l'apprentissage et le risque dans une période où l'ancien système doit toujours évoluer. Elle est parfois nécessaire, mais ne doit pas être une réponse par défaut à une structure déplaisante. Identifier la friction précise et créer une trajectoire incrémentale est généralement plus fiable.

Déplacer un comportement sans le nommer

Extraire une fonction ou un service sans identifier son invariant peut simplement déplacer l'opacité. Le nouveau nom, l'interface et les tests doivent rendre la règle plus visible qu'avant, sinon le gain est cosmétique.

Mélanger formatage, renommage et règle métier

Ce mélange rend la revue difficile : un défaut se cache facilement dans le bruit, tandis que les discussions esthétiques masquent la décision importante. Séparer les intentions, ou au moins les rendre explicitement distinctes, protège la lisibilité du changement.

Bonnes pratiques

Refactorer au rythme du changement

La meilleure occasion d'améliorer une zone est souvent lorsqu'elle doit déjà être comprise pour une évolution métier. L'équipe peut alors réduire la friction qui rend ce changement dangereux, sans lancer un programme abstrait. La limite est importante : le refactoring doit être proportionné au gain de sécurité et ne pas retarder inutilement une correction urgente.

Faire apparaître les effets de bord

Séparer une décision pure de ses appels réseau, écritures, horloges et générations d'identifiants rend le comportement plus testable. Le but n'est pas une pureté académique : c'est de pouvoir raisonner sur la règle sans devoir simuler le monde entier.

Checklist — Un refactoring reste-t-il sous contrôle ?

  • Quel comportement observable doit rester identique, et quelle preuve le caractérise ?
  • Quels effets non fonctionnels — erreur, ordre, transaction, performance — sont pertinents ?
  • Le changement peut-il être réduit à une transformation plus petite ou plus mécanique ?
  • Le diff sépare-t-il clairement restructuration et nouvelle règle ?
  • Une divergence sera-t-elle facile à attribuer et à restaurer ?
  • La nouvelle structure rend-elle réellement une décision ou une frontière plus lisible ?

À retenir

Refactorer n'est pas écrire le même code autrement. C'est préserver délibérément un comportement tout en réduisant le coût du prochain changement. Les petits pas et les preuves de caractérisation en font une pratique d'ingénierie, pas un acte de foi.