Pour moi, c'est une proportion de stabilité (comme dans le béton, l'argile cuite au four, gravée dans la pierre, écrite à l'encre permanente). Plus votre code est instable, plus il est probable que vous deviez le changer à l'avenir, plus il est pliable, comme l'argile humide, pour rester productif. J'insiste également sur la souplesse et non sur la lisibilité. Pour moi, la facilité de changement de code est plus importante que la facilité de lecture. Le code peut être facile à lire et un cauchemar à changer, et à quoi sert-il de pouvoir lire et comprendre facilement les détails de la mise en œuvre s'il s'agit d'un cauchemar à changer? Sauf s'il s'agit simplement d'un exercice académique, le point essentiel pour pouvoir comprendre facilement le code dans une base de code de production consiste à pouvoir le modifier plus facilement au besoin. S'il est difficile de changer, alors, une bonne partie des avantages de la lisibilité disparaissent. La lisibilité n’est généralement utile que dans le contexte de la souplesse et celle-ci n’est utile que dans le contexte de l’instabilité.
Naturellement, même le code le plus difficile à gérer que l'on puisse imaginer, qu'il soit facile ou difficile à lire, ne pose pas de problème s'il n'y a jamais de raison de le modifier, mais de l'utiliser. Et il est possible d'obtenir une telle qualité, en particulier pour le code système de bas niveau où les performances tendent souvent à compter le plus. J'ai le code C que j'utilise toujours régulièrement et qui n'a pas changé depuis la fin des années 80. Il n'a pas eu besoin de changer depuis. Le code est fugly, écrit dans les jours difficiles, et je le comprends à peine. Pourtant, il est toujours applicable aujourd'hui, et je n'ai pas besoin de comprendre son implémentation pour en tirer le meilleur parti.
Bien écrire des tests est un moyen d’améliorer la stabilité. Un autre est le découplage. Si votre code ne dépend pas d’autre chose, sa seule raison de changer est si elle-même doit changer. Parfois, une petite quantité de duplication de code peut servir de mécanisme de découplage pour améliorer considérablement la stabilité, ce qui en fait un bon compromis si, en échange, vous obtenez un code qui est maintenant complètement indépendant de tout le reste. Maintenant, ce code est invulnérable aux changements du monde extérieur. En attendant, le code qui dépend de 10 bibliothèques externes différentes a 10 fois plus de raisons de changer à l’avenir.
Une autre chose utile dans la pratique est de séparer votre bibliothèque des parties instables de votre base de code, voire même de la construire séparément, comme vous le feriez pour des bibliothèques tierces (qui sont également destinées à être simplement utilisées, pas modifiées, du moins pas par votre équipe). Seulement ce type d'organisation peut empêcher les gens de le manipuler.
Un autre est le minimalisme. Moins votre code essaie de faire, plus il est probable qu'il puisse faire ce qu'il fait bien. Les conceptions monolithiques sont presque définitivement instables, car plus elles ajoutent de fonctionnalités, plus elles semblent incomplètes.
La stabilité doit être votre objectif principal lorsque vous écrivez un code qui, inévitablement, sera difficile à modifier, comme le code SIMD parallélisé qui a été mis au point jusqu'à la mort. Vous surmontez la difficulté de maintenir le code en maximisant la probabilité que vous n'ayez pas à le modifier, et donc qu'il ne soit pas obligé de le conserver à l'avenir. Cela ramène les coûts de maintenance à zéro, quelle que soit la difficulté du code à maintenir.