1 points par GN⁺ 4 시간 전 | 1 commentaires | Partager sur WhatsApp
  • YAGNI n’est pas une simple règle d’économie disant « n’écrivez pas de code dont vous n’avez pas encore besoin », mais un principe qui traite du coût qu’il y a à figer une structure sur la base de suppositions avant que le besoin ne soit confirmé
  • Le cœur du problème n’est pas la conception en elle-même, mais le moment où concevoir ; structurer trop tôt peut être aussi risqué que structurer trop tard
  • Une structure anticipée engendre à la fois un coût d’option, en fermant des choix avant l’arrivée des informations, et un coût de VAN (valeur actuelle nette), en avançant les coûts et en retardant les gains
  • Même si le coût de génération du code devient presque nul, YAGNI ne disparaît pas ; au contraire, une génération bon marché peut rendre plus facile la création de frameworks fondés sur des suppositions
  • La conclusion, à savoir construire quand c’est nécessaire, ne vient pas du coût d’écriture du code, mais du fait que la valeur des options non exercées et de l’argent non dépensé reste intacte

YAGNI n’interdit pas la conception

  • YAGNI, pour « You Aren’t Gonna Need It », n’est pas une excuse pour ne jamais concevoir ce qui n’est pas encore nécessaire
  • S’il faut quelque chose, on peut le construire ; l’essentiel est le timing
  • Le point de départ est une anecdote répétée dans des projets : face à l’idée « dans trois semaines, une implémentation simple ne suffira plus, donc j’ai envie de construire quelque chose de plus complexe dès maintenant », la réponse revenait sans cesse : « You aren’t going to need it »
  • Ce principe considère comme risqués aussi bien le fait de créer une structure trop tôt que celui de la créer trop tard

Le problème n’est pas le coût d’écriture du code, mais la structure fondée sur des suppositions

  • Une interprétation courante voit YAGNI comme une règle d’économie : « n’écrivez pas de code qui n’est pas encore nécessaire parce qu’il coûte cher »
  • Mais ce que vise YAGNI, ce n’est pas le coût de production du code ; c’est la structure spéculative (speculative structure) construite à l’avance, avant qu’une fonctionnalité réelle ne l’exige
  • Ce type de structure génère deux catégories de coûts, à des moments différents et pour des raisons différentes

Premier coût : l’option

  • Construire une structure avant l’arrivée d’une fonctionnalité revient à s’engager sur la base de suppositions pour des besoins que l’on ne connaît pas encore
  • La fonctionnalité anticipée diffère généralement de celle qui arrive réellement, ce qui entraîne souvent un double coût
    • le coût pour contourner une structure conçue avec une mauvaise forme
    • le coût pour démonter ensuite cette structure
  • Le problème ne se résume pas à dire que « prévoir est difficile »
  • Même si la supposition est correcte, on y perd encore, car on abandonne l’option qui consiste à ne pas s’engager tout de suite et à construire plus tard la bonne structure
  • Attendre n’est pas de la paresse ; c’est conserver un actif : l’option

Deuxième coût : la VAN

  • De la même manière que l’argent a une valeur temporelle, une fonctionnalité a elle aussi une valeur temporelle
  • Si vous construisez aujourd’hui une structure pour une fonctionnalité dont vous n’aurez besoin que dans trois mois, vous avancez le coût et vous retardez la sortie de la fonctionnalité qui génère réellement de la valeur
  • Ce coût existe même si la supposition est correcte
  • Même une prévision parfaite ne change pas l’ordre entre coûts et gains ; la perte naît de l’écart où les coûts sont engagés avant les bénéfices
  • Le coût d’option dit : « ne vous engagez pas avant d’avoir l’information » ; le coût de VAN dit : « ne payez pas avant d’en avoir besoin »
  • Même l’objection « ce sera trop coûteux de le corriger plus tard » peut elle-même reposer sur une nouvelle prédiction

YAGNI reste valable même si générer du code devient bon marché

  • Aucun de ces deux coûts n’inclut le coût de frappe du code
  • Si le coût d’écriture du code devient presque nul, l’interprétation frugale de YAGNI — « le code est moins cher, donc on peut le faire à l’avance » — s’effondre
  • Mais comme YAGNI n’est pas une règle d’économie, une génération de code bon marché ne le rend pas obsolète
  • Le coût d’option naît non de la quantité d’effort, mais de l’engagement qui ferme des choix futurs
  • Le coût de VAN naît non du prix de production, mais du timing des flux de valeur
  • La génération gratuite n’affaiblit pas YAGNI ; elle peut au contraire faciliter la création de frameworks spéculatifs
  • Les structures générées produisent toujours ces deux coûts et, comme elles n’ont pas été écrites directement, elles peuvent être encore moins bien comprises
  • La conclusion n’est pas « attendez parce que le code coûte cher », mais « construisez quand c’est nécessaire », car les options et l’argent ont plus de valeur tant qu’ils n’ont pas été dépensés

1 commentaires

 
GN⁺ 4 시간 전
Commentaires sur Hacker News
  • On peut aussi considérer que le coût des changements de structure a baissé
    Grâce à l’IA, le coût de renforcement du comportement par des tests avant de modifier la structure a diminué, et le coût de mise en œuvre de migrations sans interruption a lui aussi baissé
    L’une des grandes raisons pour lesquelles Rust a attiré l’attention, même avant l’IA, était justement le faible coût des changements de structure interne des applications, et c’est encore plus vrai aujourd’hui
    Le coût d’opportunité lié à l’incapacité de modifier la structure en toute sécurité a fortement augmenté, et aujourd’hui on optimise avant tout la capacité à changer rapidement et sûrement de grandes parties du code et du produit

    • La capacité à changer rapidement et sûrement de grandes parties du code et du produit a toujours été une bonne chose, et avait de la valeur indépendamment de l’arrivée du coding avec IA
      Simplement, avant l’IA, les changements de structure prenaient bien plus de temps, donc on peut aussi considérer que la valeur de ce qu’on cherche à optimiser a au contraire baissé
      Cela reste précieux, mais peut-être un peu moins qu’avant
    • J’ai du mal à être d’accord
      Avec la multiplication des tests générés par IA fragiles, le coût des changements de structure est plus élevé qu’avant
      Réorganiser une suite de tests pour vérifier le cœur du problème sans valider des décisions de conception accidentelles est encore quelque chose que l’IA fait mal
    • Exact
      Mais il est aussi beaucoup trop facile d’obtenir, sans faire cet effort, une suite de tests fragile à peine mûre à 75 %
      Beaucoup de gens se satisfont de passer de « quelques tests banals et fragiles écrits par des humains » à « beaucoup de tests banals et fragiles écrits par l’IA », en considérant cela comme une amélioration objective
      Je suis tout à fait d’accord avec l’idée d’utiliser les outils de cette manière, mais j’ai du mal à en conclure qu’on peut cesser de s’inquiéter de construire trop tôt un mauvais château de cartes
      Concevoir un contrat de tests parfait qui résiste au refactoring reste encore assez difficile
    • Cela rappelle le principe ouvert/fermé : « ouvert à l’extension, fermé à la modification »
      Comme si l’ancien revenait sous des habits neufs
      De l’efficacité contextuelle d’approches comme la DDD ou la clean architecture jusqu’à ce genre de points, l’IA n’introduit pas de nouveaux compromis : elle agit comme un amplificateur
      Elle augmente la productivité des équipes qui travaillent correctement, et accroît aussi la dette des équipes dont les standards de qualité en conception et en architecture sont faibles
    • On dirait qu’on multiplie de plus en plus les gestes inutiles en pariant que l’IA corrigera le tir
      Le seul gain, c’est de ne plus avoir à réfléchir en profondeur
      Or réfléchir sérieusement ne demande ni tant de temps ni tant d’effort, donc ceux qui utilisent l’IA tout en réfléchissant suffisamment pour éviter ces gestes inutiles prendront l’avantage
  • Kent Beck compare le code pas encore écrit à une option financière permettant d’acheter du code à un certain prix
    Mais ce n’est qu’une métaphore, et si on la pousse trop loin elle devient étrange
    Si aucun code n’a encore été écrit, a-t-on une infinité de choix ? Même si on n’a pas encore dépensé de temps, cela ne semble pas juste
    Cela pourrait même servir à justifier qu’on reste en phase de planification et qu’on repousse indéfiniment l’écriture du code pour ne rien figer
    Cela dit, si la métaphore fonctionne, le coût se situe peut-être dans la lecture du code
    Le code non écrit n’a pas besoin d’être lu, et si l’on utilise un agent de code, il n’encombre pas non plus le contexte avec des détails non pertinents
    Le code pas encore écrit n’a pas besoin d’être testé, et les tests pas encore écrits ne consomment pas de temps d’exécution
    Il vaut donc mieux garder un projet aussi petit que possible, et repousser des fonctionnalités permet de ralentir au maximum la croissance de la base de code
    Cela signifie aussi qu’exécuter le code de quelqu’un d’autre permet d’éviter beaucoup de coûts
    Si l’on peut utiliser une API standard, il n’est pas nécessaire de comprendre l’implémentation en détail ni d’exécuter ses tests, même si ajouter une dépendance comporte des risques

    • Dans le « Tidy, First? » de Kent, le logiciel crée de la valeur de deux façons : par ce qu’il fait aujourd’hui, et par les possibilités qu’il peut ouvrir demain
      Le code non écrit n’a aucune valeur
      Pour que le code écrit aujourd’hui crée de la valeur, il doit soit résoudre une demande ou un problème d’aujourd’hui, soit faciliter quelque chose demain
      On ne crée pas de valeur si l’on accumule de la dette technique avec une solution bricolée ou si l’on perd du temps sur quelque chose qui va à l’encontre de YAGNI
      L’important n’est pas le code non écrit, mais le code qui sera écrit ensuite et son objectif
      Il faut trouver le bon compromis entre résoudre le ticket ou la tâche d’aujourd’hui et éviter de se tirer une balle dans le pied à l’avenir
      Écrire du code, c’est un engagement : la valeur d’aujourd’hui est visible, mais celle de demain relève davantage de l’estimation
      Il y aura malgré tout toujours un coût à payer plus tard, donc on essaie d’anticiper ce qui deviendra nécessaire afin d’en minimiser le coût
  • Je pense qu’on n’insiste pas assez sur les bonnes pratiques à l’ère de l’IA, mais il y a aussi quelque chose que Kent rate complètement
    Il y a une vraie valeur à découvrir plus vite quelles sont les fonctionnalités nécessaires
    Construire une structure spéculative peut servir de mécanisme de contrainte pour clarifier les exigences, ou au moins commencer à révéler les modes d’échec
    Comme cela peut coûter plus cher que d’attendre, il ne faut pas faire ainsi pour la plupart des exigences, mais cela peut parfois être le meilleur choix
    Le coût de construire la mauvaise chose a maintenant beaucoup baissé, et donc le calcul autour de YAGNI change lui aussi
    Cela reste malgré tout un calcul à faire, et chaque équipe doit désormais déterminer par elle-même en quoi il a changé pour elle

    • Si l’on transforme la structure spéculative en spike puis qu’on la jette, alors c’est acceptable
      Si on ne la jette pas, cela devient un mécanisme qui force à produire un résultat sale
    • À mon avis, les fonctionnalités nécessaires découlent déjà des exigences et de la conception du système censé y répondre
      YAGNI, c’est le problème qui consiste à construire quelque chose qui n’est pas dans les exigences actuelles en anticipant que les exigences changeront plus tard
      Ce n’est pas la même chose que préciser les exigences et contraintes actuelles
      Ces éléments viennent surtout des échanges avec les parties prenantes, les utilisateurs et les clients, ainsi que des ressources, des contraintes d’ingénierie et des capacités disponibles
      Un prototype a de la valeur quand il sert à échanger avec des parties prenantes, à construire un modèle de gestion de projet ou à faire de la recherche en ingénierie
      En dehors de cela, c’est mettre la charrue avant les bœufs
  • Il est juste de considérer le logiciel en cours d’exécution comme un actif
    En revanche, le coût de l’exécuter puis de le reconstruire a fortement baissé
    Le coût qui n’a pas baissé, c’est celui de rompre la chaîne de confiance menant à des résultats prévisibles
    Une version donnée d’un logiciel en production a accumulé de la confiance, et si on le réécrit depuis zéro, ce capital est remis à zéro au moment de la livraison

  • À un moment, mon point de vue a changé
    Je repousse les éléments concrets au nom de YAGNI, et j’écris autant que possible une version abstraite
    Créer un UserStore ? Ça semble le plus simple, mais il se peut qu’on n’ait pas besoin d’une forme spécifique comme User
    Donc je crée un Store capable de contenir n’importe quoi de stockable
    Si on n’y est pas habitué, cela ressemble à de la surconception et à un fourre-tout de génériques, mais paradoxalement c’est la manière qui promet le moins vis-à-vis de toute implémentation concrète

    • Ça ressemble exactement à de la surconception et à un fourre-tout de génériques
      Non seulement cela revient à créer une interface UserStore probablement inutile, mais aussi une abstraction Store généralisée dont on n’avait clairement pas besoin
      C’est implémenter des couches collantes, inutiles et qui ont de fortes chances de le rester, juste pour éviter de s’engager envers une implémentation concrète
      Si l’abstraction ne repose pas sur un besoin réel, alors même si elle devient nécessaire plus tard, il y a de fortes chances qu’elle ait été conçue de travers
      Au final, UserStore sera nécessaire, donc c’est ça qu’il aurait fallu créer d’abord
  • Je ne suis pas d’accord avec l’idée que « ce n’est pas une affirmation selon laquelle la prédiction est difficile, comme si un architecte plus affûté pouvait l’éviter »
    Cette affirmation ne tient que si l’on part du principe que prédire est difficile

    • « Même une supposition correcte est pire que de ne pas s’engager » me semble aussi confus
      Si on prépare à l’avance le terrain pour une fonctionnalité très probable et que tout s’aligne, on livre plus vite
      Rien ne garantit non plus que l’équipe va forcément grandir ou même rester stable, donc vouloir à tout prix coller à YAGNI dans la panique juste avant l’échéance me paraît pire que de se féliciter de sa retenue
  • Récemment, j’ai dû m’extraire fonctionnellement d’une codebase saturée de YAGNI, et c’était un travail énorme, même avec un agent
    Dans un système distribué, comment savoir ce qui est réellement utilisé ? Il y a des choses que j’ai ratées, d’autres que l’agent a ratées, et l’ensemble a pris bien plus de temps que nécessaire
    Il ne s’agissait pas d’un simple portage 1:1 ; comme j’en ai profité pour simplifier, il a fallu comprendre complètement le fonctionnement de l’ancien système
    Même des éléments en réalité jamais utilisés entraient dans ce périmètre de compréhension si on n’arrivait pas à les identifier comme tels

  • Au final, je pense que tout revient à explorer le problème et à implémenter la solution
    Résoudre le mauvais problème a toujours un coût, et implémenter une mauvaise solution pour quelque chose dont on n’a même pas besoin a aussi un coût
    Le développement logiciel peut parfois dériver vers de simples essais-erreurs au lieu de réfléchir aux stratégies d’exploration et à l’ensemble des problèmes
    Il arrive qu’explorer plus en profondeur un problème dans une direction donnée que ce qui est strictement nécessaire soit utile à long terme, mais implémenter des solutions sans objectif n’est jamais une bonne chose
    Je pense que ce que critique réellement Kent Beck, c’est l’attitude qui consiste à implémenter quelque chose « au cas où », sous prétexte qu’on pourrait en avoir besoin plus tard

  • Il dit que « construire la structure avant que la fonctionnalité n’arrive, c’est s’engager envers une supposition », mais je pense que, dans tous les cas, on fait des suppositions
    Il peut être très probable qu’une fonctionnalité arrive, sans que ce soit certain
    Si on ne construit pas la structure maintenant, il y aura un coût de refactorisation ; si on la construit trop tôt et que la fonctionnalité n’arrive jamais, l’effort est gaspillé
    Quels sont les coûts, les probabilités et les compromis entre ces possibilités ? Évidemment, cela dépend du contexte
    YAGNI dans son ensemble est intentionnellement une grande généralisation
    En fin de compte, tout dépend des circonstances
    Dans un sens comme dans l’autre, on se retrouve souvent avec beaucoup de suppositions et d’explications gestuelles ; c’est le même genre de problème que les estimations de travail fiables
    Certains développeurs supportent mal un monde incertain et cherchent des règles noir ou blanc pour tout

  • Je n’ai jamais rien vu d’utile, dans les écrits de Kent Beck, pour une entreprise de puces
    Dans une entreprise de puces, beaucoup de personnes doivent travailler pendant longtemps, les clients ne peuvent rien voir avant que ce soit terminé, et pour gagner de l’argent il faut vendre par centaines de milliers, voire par millions

    • N’est-il pas quelqu’un qui construit du logiciel et écrit sur le développement logiciel ?
      Le matériel a de fortes contraintes
      Si le logiciel a été inventé au départ, c’était justement pour s’affranchir de ce type de contraintes
    • Dire que les clients ne peuvent absolument rien voir avant l’achèvement n’est pas forcément exact
      Il est vrai que beaucoup d’entreprises de puces ne partagent pas les travaux en cours, mais il est possible, et cela se fait réellement, de partager des simulations, des prototypes et des échantillons d’ingénierie
      Bien sûr, ce sont généralement de gros clients
      Les enseignements tirés d’un secteur où le coût du changement est relativement faible s’appliquent mal à un secteur où ce coût est élevé, et l’inverse est souvent vrai aussi
    • Intéressant
      Comment les entreprises de puces planifient-elles ce genre de projets ? Agile, en cascade, ou utilisent-elles un cadre différent de celui de l’industrie logicielle ?