Pourquoi nous construisons lentement

La vitesse au début d’un projet est empruntée, pas acquise. Plaidoyer pour consacrer les premières semaines aux décisions sur lesquelles il est coûteux de revenir.

Publié le
Temps de lecture
4 min
Auteur
Matteo Chirivi

Il existe une manière de développer des logiciels qui ressemble au progrès sans en être. Une fonctionnalité est livrée tous les quelques jours, la démonstration s’améliore chaque semaine, et pendant un temps la courbe ne fait que monter. Puis arrive la troisième intégration, ou le premier vrai client avec de vraies données, et l’équipe découvre que la forme du système ne peut pas l’accueillir. Le travail des six mois suivants consiste à défaire celui des trois derniers.

Nous avons fait le choix inverse. Nos projets démarrent lentement, à dessein.

La vitesse est empruntée sur une décision que vous n’avez pas encore prise

L’essentiel de la vélocité initiale vient du report des décisions plutôt que de leur prise. Vous ne choisissez pas un modèle de données, vous acceptez celui qu’implique votre premier écran. Vous ne définissez pas de frontière entre deux préoccupations, vous les laissez partager un fichier en promettant de les séparer plus tard. Chaque report est un petit emprunt, et les intérêts se paient à chaque modification ultérieure.

Les emprunts qui font mal ne sont pas ceux contre lesquels on met en garde. Un balisage dupliqué se corrige à peu de frais. Un nom de variable confus se corrige à peu de frais. Ce qui ne se corrige pas à peu de frais :

  • Le modèle de données. Chaque écran, export, contrôle d’autorisation et intégration finit par dépendre de la forme de vos entités centrales. Se tromper ne produit pas un bug, cela produit une catégorie de bugs qui réapparaît pendant des années.
  • Les frontières entre systèmes. Dès que deux préoccupations connaissent le fonctionnement interne l’une de l’autre, les séparer oblige à toucher aux deux. Le coût de cette séparation augmente avec chaque fonctionnalité construite à cheval sur la jointure.
  • Le sens d’un mot. Si « compte » signifie une chose dans la facturation et une autre dans le reporting, l’ambiguïté sera inscrite dans une centaine de fonctions avant que quiconque ne nomme le problème.

Aucun de ces problèmes ne se rattrape par un sprint de refactorisation. Ils se rattrapent par une réécriture, qui est la manière la plus coûteuse d’apprendre ce que l’on aurait pu apprendre en réfléchissant une semaine.

En quoi consiste réellement ce démarrage lent

Construire lentement n’est pas la même chose que construire avec soin au sens général. C’est un ensemble d’activités précises, qui se déroulent avant qu’il y ait grand-chose à regarder.

Nous consacrons la première phase à essayer d’énoncer le problème en une phrase. Pas la solution : le problème. C’est plus difficile qu’il n’y paraît, et c’est là que la plupart des produits échouent sans bruit. Un problème que l’on ne sait pas énoncer précisément est un problème que l’on résoudra approximativement, et une solution approximative à un problème flou ne se distingue pas d’un produit dont personne n’a besoin.

Vient ensuite le modèle. Nous décrivons les entités, leurs relations et leurs invariants avant de concevoir un écran, parce que les écrans découlent du modèle et non l’inverse. Si le modèle est juste, les interfaces sont peu coûteuses à modifier et peuvent continuer à s’améliorer pendant des années. Si le modèle est faux, aucun travail d’interface ne pourra le masquer.

Viennent ensuite les frontières. Nous décidons ce que chaque partie du système a le droit de connaître, et nous le consignons par écrit. Les frontières sont la seule défense contre le mode de défaillance dans lequel une base de code devient techniquement fonctionnelle et pratiquement impossible à modifier.

Ce n’est qu’alors que l’implémentation commence, et elle est comparativement rapide, parce que les questions coûteuses ont déjà reçu une réponse.

Le problème de la mesure

La difficulté, pour être honnête, est que cette approche se démontre mal pendant qu’elle se déroule. Une équipe qui passe trois semaines sur un modèle de données n’a rien d’autre à montrer à la fin qu’un document et quelques définitions de types. Une équipe qui passe trois semaines à construire des écrans a des écrans.

La différence apparaît plus tard, et elle apparaît sous la forme d’une absence. Il n’y a pas de réécriture. Il n’y a pas de mois passé à migrer des données parce qu’une colonne signifiait deux choses. Il n’y a pas de fonctionnalité qui se révèle impossible. Les absences sont difficiles à faire figurer dans un rapport d’avancement, et c’est précisément pour cela que, dans la plupart des entreprises, les incitations poussent dans l’autre sens.

Nous acceptons ce coût parce que nous possédons ce que nous construisons. Personne ne nous demande de montrer une courbe ce trimestre, nous pouvons donc optimiser l’état du système la cinquième année plutôt que l’état de la démonstration la troisième semaine.

Là où la vitesse a sa place

Ce n’est pas un plaidoyer pour la lenteur comme vertu. La lenteur au mauvais endroit n’est que du gaspillage.

Une fois le modèle et les frontières établis, nous voulons avancer très vite, et tout l’intérêt du démarrage lent est que nous le pouvons. Des systèmes bien définis sont agréables à faire évoluer. Ajouter une fonctionnalité est une modification locale plutôt qu’une négociation avec l’ensemble de la base de code. La vélocité arrive plus tard, mais elle arrive et elle reste, au lieu de s’éroder à mesure que le système accumule des décisions que personne n’a prises délibérément.

Un logiciel qui dure une décennie n’est pas un logiciel construit avec plus de soin au sens général. C’est un logiciel dans lequel le petit nombre de décisions véritablement irréversibles a été pris lentement, et tout le reste rapidement.

SuivantPosséder plutôt que louer