"Don't write code that guesses the future"
Don't write code that guesses the future, arrange code so you can adapt to the future when it arrives.
Cette citation de Sandi Metz nous enjoint à la retenue et dit de manière élégante un écueil bien réel du développement informatique : la sur-anticipation.
Un exemple : la relation 1-N (one to many) en SQL. Ça pourrait évoluer vers une relation N-N, se dit-on. C'est même très probable, c'est prévu dans 6 mois, 1 an au maximum. Alors on fait d'emblée une N-N, avec la table d'association "qui va bien" et tout le tralala, et on l'utilise de fait comme une 1-N.
Cet exemple est bien réel, je l'ai vu. J'ai vu pire en fait : une entreprise qui implémentait toutes les relations, y compris les 1-1, en tant que N-N, parce que… "au cas où" 😮
Qu'une relation 1-N reste donc une relation 1-N et les brebis seront bien gardées. Par contre, on peut faire en sorte que le changement, s'il advient, soit le plus local possible. L'isolation du domaine peut aider, sans probablement suffire (architecture hexagonale, functional core/imperative shell).
Ne pas anticiper est un art subtil : cette fonctionnalité à venir et la complexité qu'elle engendre, n'en posons pas les bases tout de suite. Attendons qu'elle arrive réellement, gardons la généricité pour plus tard… tout en faisant en sorte qu'elle puisse advenir.
C'est donc une véritable ligne de crête, un numéro d'équilibriste. À dire vrai, cette citation me hante depuis des années, car je ne vois aucune heuristique évidente. Le code que j'écris n'est peut-être "pas assez", à moins qu'il ne soit "déjà trop" : comment savoir ?
C'est d'autant plus difficile que nos esprits créatifs sont fascinés par la complexité et la puissance. Il y aura toujours cette tentation d'en faire un peu plus, du "au cas où", du "parce que ça pourrait servir", du "ça coûte pas plus cher" ; c'est tentant, mais c'est déjà le début de la fin.
Pourquoi ?
Parce que le futur a le bon goût d'être imprévisible : cette fonctionnalité, dont nous sommes certains qu'elle adviendra, n'adviendra peut-être pas. Parce que les utilisateurs nous disent que la fonctionnalité n'est pas utile, ou pas prioritaire, ou parce qu'on perd le budget, vous connaissez. Vous aurez ainsi travaillé des semaines durant pour écrire du code qui n'apporte aucune valeur à l'utilisateur…
Et qui, dans le même temps, complexifie l'ensemble de la codebase. Le code, autrefois simple et concis, reflète à présent un modèle plus complexe, plus abstrait, dont les fonctionnalités de l'application ne sont qu'un cas particulier (encore une fois, tout cela est fait par anticipation). Ce code additionnel, vous le traînez comme un boulet : implémenter de nouvelles fonctionnalités prend plus de temps et va avec plus de bugs.
Mieux vaut donc apporter la complexité "just in time", au dernier moment. J'enfonce des portes ouvertes, me direz-vous ; si vous saviez…