Adieu, Clean Code (2020)
(overreacted.io)- À travers l’expérience d’une réécriture du code de redimensionnement d’un éditeur graphique centrée sur la suppression des doublons, finalement annulée, l’article montre qu’une obsession du Clean Code peut nuire à la facilité réelle de changement
- L’implémentation existante répétait des formules pour chaque poignée de Rectangle, Oval, Header et TextBlock ; la nouvelle implémentation cherchait à éliminer les doublons en séparant directions et formes pour les combiner
- Juste après le refactoring, la taille du code avait été réduite de moitié et les points de modification regroupés à un seul endroit, mais par la suite, si des comportements spécifiques par forme et par poignée devenaient nécessaires, l’abstraction aurait au contraire pu devenir un frein
- Le problème le plus important n’était pas le jugement technique, mais le fait d’avoir directement commité sur master sans consulter le collègue qui avait écrit le code d’origine, ce qui peut nuire à la construction de la confiance dans l’équipe
- La « propreté » n’est pas un objectif, mais seulement un outil pour gérer des systèmes complexes ; plus que l’apparence du code, ce qui compte est la capacité de l’équipe à réagir au changement ensemble
La répétition dans le code de redimensionnement d’un éditeur graphique
- Le canevas d’un éditeur graphique contenait du code permettant de redimensionner des formes comme des rectangles et des ellipses à l’aide de petites poignées situées sur les bords
- L’implémentation fonctionnait, mais les formules calculant la position et la taille étaient répétées pour chaque forme et chaque direction de poignée
Rectangleavait des méthodes commeresizeTopLeft,resizeTopRight,resizeBottomLeft,resizeBottomRightOvalavait des méthodes commeresizeLeft,resizeRight,resizeTop,resizeBottomHeaderetTextBlockavaient aussi chacun leurs propres méthodes de redimensionnement
- Quand l’utilisateur maintenait Shift, il fallait aussi gérer la conservation des proportions pendant le redimensionnement, ce qui ajoutait encore plus de formules
Une abstraction pour supprimer les doublons
- Les répétitions semblaient se répartir selon deux axes
- Elles se répétaient entre poignées de même direction :
Oval.resizeLeft()etHeader.resizeLeft()correspondent toutes deux à l’action de faire glisser la poignée gauche - Elles se répétaient entre méthodes d’une même forme : les différentes méthodes de
Ovalmanipulent toutes une ellipse
- Elles se répétaient entre poignées de même direction :
- La nouvelle structure divisait le code en
DirectionsetShapesafin de combiner les comportements par direction et les comportements par formeDirectionscontenaittop,left,bottom,rightShapescontenaitOval,RectanglecreateHandleetcreateBoxcombinaient poignées et formes
- Avec cette approche, on créait des configurations de poignées comme
fourCorners,fourSides,twoSides, puis on les utilisait pour créerRectangle,Oval,Header,TextBlock
L’illusion juste après le refactoring
- Après le refactoring, la taille totale du code avait été réduite de moitié et les doublons semblaient avoir disparu
- On pensait qu’en cas de changement du comportement d’une direction ou d’une forme donnée, il suffirait de modifier un seul endroit plutôt que plusieurs méthodes
- Tard dans la nuit, le changement a été commité sur master, avec l’impression d’avoir proprement démêlé le code désordonné d’un collègue
Le problème révélé le lendemain
- Le lendemain, le responsable a demandé d’annuler le changement ; à l’époque, comme le nouveau code semblait plus propre que l’ancien, c’était difficile à accepter
- Avec le recul, ce jugement était correct pour deux raisons
- Le code avait été réécrit et commité sans en parler à la personne qui avait écrit le code d’origine
- En échange d’une réduction des doublons, on avait sacrifié la facilité d’évolution face aux changements de besoins
- Une équipe d’ingénierie saine doit continuellement construire la confiance, et une réécriture massive du code d’un collègue peut porter un coup important à la collaboration
Le coût d’une mauvaise abstraction
- Par la suite, de nombreux cas particuliers et comportements spécifiques sont devenus nécessaires pour plusieurs poignées de plusieurs formes
- Dans la nouvelle structure abstraite, prendre en charge ces besoins aurait pu rendre le code plusieurs fois plus complexe
- À l’inverse, l’ancienne structure « désordonnée » séparait chaque méthode, ce qui rendait ce type de changement relativement facile à appliquer
- Supprimer les doublons n’est pas gratuit : on peut gagner une capacité tout en en perdant une autre
Repenser la « propreté »
- Beaucoup de développeurs peuvent passer par une période d’obsession pour le « Clean Code » et la suppression des doublons
- Quand on manque de confiance dans le code que l’on écrit, il est facile d’associer sa fierté à des éléments mesurables comme des règles de lint strictes, des conventions de nommage, une structure de fichiers ou l’absence de doublons
- Lorsqu’on apprend à créer des abstractions, on peut être tenté, chaque fois que l’on voit du code répétitif, de croire que l’abstraction est une vertu et de l’appliquer
- Il faut réfléchir en profondeur au lien entre le sentiment de « propreté » ou de « saleté » et les résultats réels en ingénierie
- Ce qui compte, ce n’est pas seulement l’apparence du code, mais aussi la manière dont le code évolue et se modifie avec les personnes de l’équipe
Quand il faut lâcher le Clean Code
- Le Clean Code n’est pas un objectif, mais une tentative de comprendre des systèmes complexes
- Il peut servir de mécanisme de défense pour s’orienter lorsqu’on n’est pas sûr de l’impact qu’un changement aura dans une base de code
- Au début, il peut être agréable de simplifier du code complexe en extrayant des fonctions ou en refactorant des classes
- Mais il ne faut pas s’arrêter là et devenir un « fanatique du Clean Code »
- Laissez le Clean Code vous guider, mais à un certain moment, il faut savoir le lâcher
1 commentaires
Avis de Hacker News
La duplication de code peut parfois être acceptable, mais cela ne prouve pas pour autant que le Clean Code soit mauvais
On a l’impression que le refactoring est allé un peu trop loin ; se contenter d’extraire « 10 lignes de maths répétées » dans une fonction aurait été plus propre
Le collègue qui n’a pas transformé ces 10 lignes en fonction n’a pas non plus fait du bon travail, donc à sa place j’aurais refusé la PR, mais je ne l’aurais pas réécrite moi-même
Réécrire la PR de quelqu’un d’autre est une façon rapide et insultante de fermer toute discussion, et on ignore souvent le contexte dans lequel le code a été écrit
S’il n’y a pas de standards de codage, il faut relire et refuser la PR ; si on laisse passer des commits au motif que « le Clean Code n’est pas important », on se retrouve en quelques mois avec une codebase sur laquelle plus personne n’a envie de travailler
Ce qu’il faut en retenir ici, ce n’est pas le Clean Code, mais la communication et la considération
Cela prive aussi l’auteur initial de l’occasion d’apprendre concrètement en quoi du code de faible qualité fait perdre du temps
Même si l’approche Clean Code est meilleure, le point central ici n’est pas le code, mais le fait d’avoir gaspillé son propre temps sans fournir de feedback utile
La meilleure issue aurait été que l’auteur initial hausse son niveau d’exigence, tandis que l’autre personne se consacre à d’autres tâches qui avaient réellement besoin d’être reprises. Autrement dit, la bonne réponse était la revue de code
Ces personnes finissent souvent par résoudre des non-problèmes au lieu des vrais problèmes, tout en créant de futurs problèmes
Lors d’une première implémentation, il vaut mieux ne pas abstraire un tout petit morceau de code de ce type, de l’ordre de 10 lignes. Un code qui fait exactement cette chose-là sera facile à modifier plus tard, et abstraire 10 lignes pour un bénéfice non démontré n’a pas grand intérêt
Clean Code n’a aucune importance, et la plupart des règles ou « principes » du même genre non plus. Ce sont plutôt des choses auxquelles s’accrochent les gens qui veulent justifier l’accumulation, au fil du temps, d’une structure en nid d’abeille dans la codebase
Au final, on obtient facilement du code trop abstrait, difficile à modifier, lent et difficile à comprendre
S’il faut un principe, il suffit de veiller à exprimer clairement et de façon facilement modifiable ce que le programme fait réellement : des transformations de données
La plupart des principes SOLID n’aident pas à voir ce que sont ces transformations de données ni comment elles se produisent ; ils peuvent même gêner cette compréhension, et sont donc globalement peu utiles pour comprendre de vrais programmes
À voir le refactoring proposé, ces 10 lignes n’étaient en fait pas identiques, seulement similaires
La formule pour redimensionner le coin supérieur gauche d’un rectangle et celle pour modifier le coin inférieur droit d’une ellipse sont différentes. En surface elles se ressemblent, mais à certains endroits il y a par exemple un
-au lieu d’un+Dans ce cas, la complexité se trouve dans la géométrie elle-même ; l’« abstraire » ne fait que déplacer le désordre ailleurs, sans le faire disparaître fondamentalement
Il pourrait exister une abstraction mathématique ingénieuse, comme un système numérique spécial, mais si elle n’est pas intégrée au langage, le coût d’implémenter des opérations spéciales avec des entiers de base risque fort de dépasser les bénéfices obtenus
Le « Clean Code » a besoin d’un rebranding
En plus de 25 ans de carrière, j’ai vu une opposition sans fin aux design patterns, à l’abstraction, à la suppression de duplication, etc.
Les raisons invoquées sont toujours les mêmes : l’abstraction rend le code plus complexe, on n’a pas le temps d’écrire du code propre, tout cela n’est qu’affaire de goût et d’opinion
Mais l’objectif du Clean Code est de rendre le code plus simple et plus maintenable quand les exigences changent
La valeur du logiciel tient au fait qu’il peut évoluer avec le temps. Sinon, on utiliserait des circuits fixes, bien plus faciles et moins chers à implémenter et à maintenir
Si le refactoring n’a pas atteint cet objectif, et si le manager peut expliquer de manière convaincante qu’il est devenu plus difficile à maintenir face à de futurs changements d’exigences, alors ce code n’était pas « clean »
Le fait de ne pas en avoir discuté avec l’auteur initial relève des procédures et de la courtoisie, pas du Clean Code. Agir de manière impolie et unilatérale ne fait pas disparaître la valeur du Clean Code
Le célèbre livre Clean Code présente « l’absence de duplication » comme une condition d’un système bien conçu, et décrit la duplication comme l’ennemi principal du travail supplémentaire, du risque supplémentaire et de la complexité inutile
Selon cette définition, supprimer la duplication devient synonyme de simplification, et c’est faux
Supprimer la duplication, c’est introduire une dépendance. Si cette dépendance modélise bien le problème, elle peut devenir une bonne abstraction et une simplification ; sinon, ce n’est qu’une compression déguisée en abstraction
À titre de référence, cette citation vient de la mention, dans Clean Code, du Simple Design de Kent Beck
L’un désigne le sentiment subjectif qu’un code est bon ; l’autre le fait de suivre le livre Clean Code et les recommandations associées
De plus en plus de gens estiment que ces deux choses divergent largement. Suivre certaines recommandations du livre peut même produire du code qui n’a rien de propre
Dans un monde idéal, tout le monde voudrait écrire du code propre, mais de moins en moins de personnes ont le sentiment que Clean Code est une bonne façon d’atteindre cet objectif
En particulier, l’excès d’abstraction et la suppression de duplication sont devenus, pour beaucoup, des sources de code désordonné
Parfois, la dette technique est encodée dans les exigences produit elles-mêmes ; on ne peut pas la corriger par du refactoring ou des bonnes pratiques, seulement réduire la douleur
L’objectif du Clean Code et les résultats de sa mise en pratique sont très différents. Les gens prédisent généralement mal l’état futur du code, même avec les exigences sous les yeux
Le Clean Code invite à poser la terrible question « et si ? », qui devient facilement une boîte de Pandore repoussant indéfiniment la sortie du produit
Il vaut presque toujours mieux coder en fonction de ce que l’on sait, et laisser quelqu’un qui a de l’expérience du domaine guider l’architecture
Beaucoup de bonnes abstractions se trouvent déjà dans des bibliothèques. Malheureusement, bien sûr, ce n’est pas toujours le cas
Les mauvaises abstractions dévorent du temps ; et comme le code sert aussi à communiquer avec les autres membres de l’équipe, la façon dont ceux-ci reçoivent cette communication compte bien plus que ma propre manière de penser
Un collègue avait écrit beaucoup de code par copier-coller, et vous l’avez refactorisé après le commit
Le collègue s’est plaint à votre supérieur, celui-ci vous a réprimandé, et vous en avez en quelque sorte conclu que, la prochaine fois, vous laisseriez du bazar dans la codebase
Il y a bien une leçon à en tirer, mais cela ne veut pas dire que le copier-coller vaut mieux que l’écriture d’une fonction
Le refactoring aurait dû être proposé comme une modification séparée, en taguant l’auteur initial pour obtenir sa review
Cela dit, le fait que le collègue soit passé par le supérieur au lieu de venir vous en parler directement, et que le supérieur vous ait demandé de revenir en arrière, est un assez mauvais signal
Les réponses possibles seraient « Non, parce que… » ou, plus rarement, « Oui, en effet, je le ferai demain »
Sans bruit, tout le monde évite le problème, et quelqu’un peut éventuellement apprendre quelque chose
Mais l’auteur a ajouté un contexte important. Il a échangé la possibilité de changements de besoins contre une réduction de la duplication, puis plus tard il a fallu beaucoup de cas particuliers et de comportements propres à chaque poignée de forme
Cela montre la différence entre DRY accidentel et DRY essentiel
Les bibliothèques A et B semblent souvent cohérentes entre elles, ce qui conduit à du code identique, mais en réalité cela peut n’être qu’une coïncidence
Même si un wrapper autour de lib A et un wrapper autour de lib B contiennent le même code, s’ils encapsulent des choses totalement différentes, les abstraire donnera un mauvais résultat
C’est pareil pour « 15 ». Si « toutes les listes doivent toujours afficher 15 éléments », alors abstraire 15 est correct ; mais si ce sont séparément « les 15 meilleurs morceaux de la page d’accueil » et « les 15 commentaires par défaut sous une chanson », les regrouper autour de ce 15 est un plus mauvais choix
Le deuxième signal d’alarme, c’est que le refactoring lui-même n’est pas non plus un bon refactoring. Il manque de modularité, reste couplé, et ne fait que réduire un peu la duplication
Cela peut sonner comme : « Ton code n’était pas terrible, alors je l’ai réécrit. Un problème ? »
La meilleure solution serait probablement de demander des explications sous forme de « review tardive », de proposer une solution, et d’espérer que l’auteur initial ne l’ignore pas simplement
Le point clé est de reconnaître que le code changera à l’avenir. Les exigences changent, et le code concerné aussi
Si l’on crée une abstraction qui limite cette capacité de changement, on nuit à la capacité de son futur soi à adapter la codebase
En particulier, on s’attache émotionnellement aux abstractions dans lesquelles on a investi beaucoup de temps et d’efforts, et on finit parfois par perdre encore plus de temps à faire entrer les changements dans une solution élégante
KISS est la bonne approche
Ce cas ressemble au problème « personne n’aime les gens qui se la jouent »
Cela arrive souvent, surtout quand un développeur junior n’a pas encore appris que le travail ne se passe pas seulement entre lui et l’ordinateur, mais entre lui, l’ordinateur et d’autres personnes
Une version plus propre aurait très probablement été acceptée si une vraie discussion avait eu lieu avec l’auteur initial et qu’un meilleur moyen avait été convenu
Le titre de l’article aurait plutôt dû être J’ai appris à travailler en équipe que « Adieu, Clean Code »
Le code plus complexe a été perçu comme une menace, et peut-être comme un concurrent à faire rentrer dans le rang via la chaîne hiérarchique
Si vous êtes junior, il faut comprendre que cette phrase dépend du contexte. Dans beaucoup d’entreprises, la simplicité compte plus que la flexibilité, on évite les fonctionnalités de langage déroutantes, et on préfère les approches qui demandent de longues heures devant le clavier, ainsi que les langages qui s’y prêtent
À l’inverse, une philosophie qui valorise l’apprentissage continu, le craftsmanship logiciel et la réflexion sur les processus entre totalement en conflit avec ce genre d’environnement
Les tentatives de s’améliorer ne sont pas populaires auprès des gens qui ne grandissent pas
Les deux sont des choix de vie valables. Le logiciel peut être un endroit commode où travailler 7 heures puis rentrer chez soi, comme un monde d’exploration dont les seules limites sont l’imagination et l’intelligence
Si vous voulez découvrir de nouvelles choses, méfiez-vous de l’idée de passer des décennies avec des personnes qui craignent l’inconnu
En plus court : si vos incitations ne sont pas alignées avec celles de vos collègues, envisagez de partir
Cet article a des raisons de rester apprécié longtemps, et il a ouvert les yeux de nombreux développeurs qui tombaient dans le même piège
Même en travaillant seul, on peut surconcevoir une abstraction élégante et se faire mordre par elle plus tard
Le problème est que les changements sont committés directement dans la branche main sans review
Toute modification de code devrait faire l’objet d’une review par les pairs, que ce soit via du pair programming ou une PR traditionnelle, afin d’éviter ce type d’escalade
Le supérieur était un mauvais manager. Au lieu de réprimander, il aurait dû remarquer qu’il manquait un bon processus
Dans une équipe avec une culture de code review, même si une nouvelle recrue trop enthousiaste tentait ce genre de chose, un collègue aurait dit « merci, mais ce n’est pas ça » ou « bonne idée, mais essayons plutôt comme ceci »
À part ça, je pense qu’il ne faut pas refactoriser du code sans bonne raison. Même du mauvais code peut être du code qu’on n’a presque jamais besoin de modifier
Le meilleur moment pour refactoriser, c’est quand on doit changer le comportement et qu’on se rend compte que la structure existante rend cela trop difficile
Malheureusement, ici, il semble que la mauvaise leçon ait été retenue
Je ne comprends pas pourquoi tout le monde ne parle que de ce qu’il aurait dû faire à la place. C’est une leçon tout à fait légitime
En finance, on manipule en permanence des produits plus ou moins similaires, sans être exactement les mêmes. Les options sur actions et les options de change sont toutes deux des options, ont un prix d’exercice et sont valorisées avec une certaine version de Black-Scholes, mais en pratique elles sont très différentes
Pour une nouvelle personne dans l’équipe, la tentation est forte de vouloir mutualiser beaucoup de comportements, et nous nous retrouvons souvent dans la position du supérieur de l’article original, à dire à de jeunes développeurs de se calmer et de garder les choses séparées
Il ne s’agit pas de dire adieu au clean code, mais de dire qu’il faut éviter la sur-abstraction pour pouvoir réellement conserver un code propre
Ce que font des poignées génériques, ce sont des transformations affines — translation, rotation, mise à l’échelle, réflexion — et, dans le cas d’une mise à l’échelle uniforme, une transformation de similitude. Il est garanti que cela fonctionne pour n’importe quelle forme
Le vrai problème est qu’il ne faut pas abstraire ce que l’on ne comprend pas suffisamment. Surtout si l’on ne sait pas quelles possibilités apparaîtront à l’avenir
Par exemple, si l’on pense que les ovales se limitent aux cercles et aux ellipses, on risque d’être assez surpris à l’arrivée du premier « vrai » ovale
Comme l’auteur ne distingue pas vraiment le code brouillon du code « non clean », les autres essaient de faire cette distinction
DRY a de la valeur, mais l’abstraction a un coût. C’est toujours un compromis
L’une des raisons pour lesquelles j’aime des langages comme Haskell, c’est que le maximalisme de l’abstraction n’y est pas situé au niveau du codage, mais au niveau du langage
Tout le monde est d’accord sur ce qu’un Applicative doit faire. Le défi se déplace plus à droite dans le pipeline qui va de l’idée au code : trouver l’Applicative adapté au problème
La plupart des design patterns orientés objet ont, dans ce genre d’environnement, des équivalents naturels et bien définis, ce qui aide à réduire les abstractions propres à chaque projet
Pour les débutants, le coût initial d’apprentissage du langage est élevé, et il arrive souvent qu’en ouvrant du code Haskell d’un autre projet on tombe sur une douzaine d’extensions du compilateur jamais vues qu’il faut comprendre
Mais comme ces extensions du compilateur peuvent ensuite être réutilisées dans tous les projets, j’y vois tout de même un gain net
Pour les experts, l’inconvénient est qu’il faut un doctorat pour avoir une idée de la quantité de RAM que cats va consommer
Lorsqu’un code utilise Applicative ou Monad, ces lois permettent d’en connaître le comportement
Les design patterns orientés objet n’ont pas de telles lois. Ce sont des concepts ou des patterns définis de manière lâche, ouverts aux interprétations personnelles et aux personnalisations, mais sans lois concrètes qui disent précisément ce qu’ils sont ni quel comportement ou quelle sortie il faut en attendre
Cela dit, pour l’exemple du billet de blog, je dois dire que suivre la voie du clean code m’a vraiment souvent amené à me tirer une balle dans le pied pour l’avenir
Si, plus tard, il faut étudier l’abstraction pour la comprendre à nouveau, alors cette abstraction n’est pas bénéfique
Là où l’orientation objet s’applique le plus naturellement, c’est dans les widgets GUI et l’implémentation d’éditeurs
La règle qui unifie les autres règles de l’orienté objet, c’est ne demandez pas, donnez des ordres
Dans cet exemple, les poignées seraient partagées de manière connue, et il y aurait des points de contrôle propres à chaque forme. Quand une poignée de boîte change, on peut appeler
updateControlPoints(changedHandle), et quand un point de contrôle change, on peut appelerupdateBoxHandles(changedControlPoint)D’autres séparations propres seraient possibles, mais c’est ainsi que je ferais
Mais le choix de la bibliothèque de parsing, de
Data.Text.StrictouData.Text.Lazy, du degré d’usage du style point-free, de.et>>>ou d’autres combinateurs, ainsi que des extensions du langage à utiliser, fait beaucoup moins consensusJ’aime Haskell, mais il rencontre des problèmes similaires à ceux des autres langages. Les gens ne parviennent vraiment pas à s’accorder sur la meilleure façon de faire les choses
On obtient le système de types de Haskell et des performances prévisibles
Il aurait suffi de déplacer la partie mathématique répétée dans une fonction séparée, puis de l’appeler depuis les fonctions de redimensionnement
Si les fonctions de redimensionnement elles-mêmes semblaient répétitives, c’est parce qu’elles constituaient une interface, et le refactoring qui les supprimait était donc une erreur
Mais les calculs effectués par ces fonctions étaient une cible tout à fait valable pour nettoyer le code
On se retrouve au final avec plein de petites fonctions pures, mais ce n’est pas un problème, car les tests et le refactoring deviennent faciles
Il existe de nombreuses façons et de nombreux patterns pour résoudre un même problème, mais démolir une interface existante utilisée par d’autres n’est pas un bon point de départ
L’avantage de l’abstraction est de pouvoir rendre l’intérieur plus flexible sans nuire au reste
Une bonne première étape consiste, comme indiqué, à créer en dessous des fonctions mathématiques plus flexibles tout en laissant le reste intact
Ensuite, on peut discuter plus en profondeur avec l’équipe de la manière de communiquer autour d’une interface fournissant une façade claire, tout en abstraisant l’implémentation
Ce qui est décrit ici ressemble à une mauvaise abstraction
Le vrai problème, c’est que les gens conçoivent à partir de seulement deux ou trois exemples, sans vérifier si c’est suffisamment général pour accueillir des usages futurs.
Il faut abstraire du bas vers le haut, pas du haut vers le bas
Il n’est pas nécessaire de créer un point unique où tout se passe et qui gère
2^ncombinaisonsOn peut tout de même réduire la répétition, pouvoir modifier à un seul endroit, et conserver la capacité de faire des ajustements sur mesure quand c’est nécessaire
Dire simplement « évitez les mauvaises abstractions » ou « prévoyez les usages futurs » ne suffit donc pas
En général, personne ne peut prédire l’avenir
Les abstractions doivent être utilisées avec une extrême prudence, même quand elles semblent justes. Mieux vaut adopter un scepticisme radical
Dans le code de calcul, toucher à une chose affecte tout le reste
À un moment donné, il devient plus simple de laisser un peu de code dupliqué, d’indiquer les similarités par des indices dans la structure du code ou par des commentaires, puis, avec le temps, de faire ressortir dans les commentaires les différences essentielles
L’approche Clean Code pour ce type de code gère mal l’évolution des exigences
On finit facilement avec un tas de fonctions utilitaires contenant plusieurs chemins de code selon l’endroit d’où elles sont appelées
Parfois, on peut abstraire cela ; certains l’auront peut-être déjà remarqué, mais la phrase précédente décrivait le polymorphisme orienté objet
Mais comment connaître à l’avance les exigences exactes ? Tenter de faire du « clean code » à un stade aussi précoce ne mène qu’à une mauvaise abstraction ou à une surconception
La bonne approche consiste à ne rien faire, à noter les problèmes possibles, puis à attendre d’en savoir davantage sur le domaine du problème
Du code un peu dupliqué mais facile à comprendre, comme dans l’exemple d’origine, ne m’inquiète pas vraiment
En revanche, si je dois corriger le même problème à trois endroits, ou ajouter le code d’une nouvelle fonctionnalité à trois endroits, là je m’inquiète
C’est à ce moment-là que je commence à me demander s’il est possible, d’une manière ou d’une autre, de pousser le code à modifier ou à ajouter vers un emplacement commun
Les gens lisent sur les design patterns ou DRY et, comme ils sont encore en train d’apprendre, les appliquent généralement de travers, puis en rejettent la faute sur les textes d’origine
Rob Pike a dit un jour que l’une des raisons pour lesquelles Go est devenu ainsi était que « de petites copies valent mieux que de petites dépendances »
Plus je programme, plus je comprends ce que cela veut dire
La répétition en elle-même n’est pas le problème. Ce qui compte, c’est de comprendre l’unité que l’on est en train de lire et que l’on devra peut-être modifier
DRY signifie souvent ajouter une abstraction supplémentaire, et si cette abstraction n’est pas suffisamment orthogonale, on a aggravé la situation, car il faut désormais raisonner sur deux unités au lieu d’une