« Le développeur à cerveau de grug » (2022)
(grugbrain.dev)- La plus grande leçon qui revient après une longue expérience du développement, c’est que la complexité est l’« ennemi éternel » d’une base de code, et qu’elle crée un état où un petit changement casse des endroits inattendus
- L’outil le plus puissant pour réduire la complexité est de dire « non » aux fonctionnalités et aux abstractions, mais quand un compromis réaliste est nécessaire, une solution 80/20 permet de livrer l’essentiel de la valeur avec peu de code
- La conception et les tests mettent davantage l’accent sur la recherche de bonnes frontières une fois que la forme du système apparaît, plutôt que sur une abstraction trop précoce, et privilégient les tests d’intégration qui tiennent dans la durée plutôt que les tests unitaires
- Les outils, les systèmes de types, la journalisation, les débogueurs et la conception d’API doivent réduire la charge cognitive des développeurs, et la grande valeur pratique d’un système de types réside dans l’autocomplétion de l’IDE
- Même des techniques bien nommées comme DRY, la séparation des préoccupations, les microservices, les SPA, les génériques ou le refactoring excessif peuvent devenir des vecteurs de complexité si elles rendent le code plus difficile à comprendre et à maintenir
La complexité est le risque numéro un d’une base de code
- La complexité transforme soudain un système auparavant compréhensible en quelque chose de difficile à manipuler, et un changement à un endroit casse ailleurs, dans des zones qui semblent sans rapport
- La complexité peut entrer par l’intermédiaire de développeurs ou de chefs de projet pleins de bonnes intentions, et il arrive que la complexité qu’on a soi-même introduite soit la source du problème
- Il n’existe pas de « massue » universelle pour résoudre la complexité ; la meilleure réponse est de ne pas la laisser entrer dès le départ
« non » et « ok » : refus et compromis réaliste
- La meilleure arme contre la complexité, c’est « non »
- « Cette fonctionnalité, on ne la développe pas »
- « Cette abstraction, on ne la crée pas »
- Mais même si « non » est un bon conseil d’ingénierie, cela peut être moins favorable aux récompenses ou aux promotions
- Lorsqu’il faut faire un compromis réaliste, on répond « ok », puis on cherche une solution 80/20
- Une manière d’implémenter 80 % de la valeur voulue avec 20 % du code
- Elle peut ne pas avoir toutes les finitions et être un peu moins élégante, mais elle délivre l’essentiel de la valeur tout en gardant une faible complexité
- Comme un chef de projet peut oublier des exigences de détail, les déplacer ou quitter l’entreprise, l’approche 80/20 peut parfois être un meilleur choix
La conception et la décomposition du code sont risquées si elles arrivent trop tôt
- Au début d’un projet, la forme du système est encore floue, comme de « l’eau », donc on évite la décomposition trop précoce
- Avec le temps, de bonnes frontières apparaissent
- l’interface avec le reste du système est étroite
- la complexité interne est masquée par un petit nombre de fonctions ou d’abstractions
- Si l’on crée des abstractions trop tôt, il est facile de produire de mauvaises abstractions ; mieux vaut donc attendre
- Pour les développeurs qui veulent construire de grosses abstractions dès le départ, il peut être utile de leur donner des livrables jetables comme des UML, ou d’exiger une démo fonctionnelle pour le lendemain
- Un prototype initial montre plus vite du code qui fonctionne réellement et des contraintes réalistes
Les tests : pas « tout à la fin », mais en parallèle quand la forme se précise
- Les tests évitent beaucoup de problèmes, mais l’auteur est opposé à l’idée d’imposer le test first avant même de comprendre le domaine
- Il préfère écrire l’essentiel des tests après le prototype, quand le code commence à se solidifier
- L’attitude qui consiste à sauter les tests sous prétexte que « ça marche sur ma machine » est très mauvaise
- Les préférences selon le type de test sont nettes
- tests unitaires : utiles au début d’un projet, mais ils cassent facilement quand l’implémentation change et peuvent compliquer le refactoring
- end to end : ils montrent le comportement du système complet, mais lorsqu’ils échouent il est difficile d’en comprendre la cause, et s’ils cassent souvent ils finissent facilement ignorés
- tests d’intégration : assez haut niveau pour vérifier la justesse du système, assez bas niveau pour trouver la cause avec un débogueur ; ils sont proches du meilleur compromis
- Une fois les API de frontière stabilisées, il faut investir fortement dans les tests d’intégration autour d’elles
- Les tests end-to-end doivent rester un petit ensemble bien maintenu, centré sur les fonctionnalités UI les plus courantes et quelques edge cases importants
- Le mocking n’est utilisé qu’en cas de nécessité, si possible seulement à l’échelle de grandes frontières
- Lorsqu’un bug est découvert, l’exception consiste à d’abord le reproduire avec un test de régression, puis à le corriger
Agile, refactoring et Chesterton's Fence
- Agile n’est pas la pire chose en soi et peut servir comme mode d’organisation du développement, mais il faut se méfier des « agile shamans » qui s’en servent comme d’un outil d’exonération en cas d’échec
- Les prototypes, de bons outils et le recrutement de bons développeurs comptent davantage dans le succès d’un logiciel, et aucun processus n’est une silver bullet capable de tout résoudre
- Le refactoring est utile, surtout plus tard quand le code s’est durci, mais plus un refactoring est important, plus il risque d’échouer
- on le découpe en petites étapes
- on maintient autant que possible le système dans un état qui continue de fonctionner
- on ne passe à l’étape suivante qu’une fois la précédente terminée
- Une abstraction excessive peut mener à l’échec du refactoring, voire du système
- Chesterton's Fence rejoint l’idée qu’il ne faut pas supprimer un code peu esthétique avant d’avoir compris pourquoi il existe
- Un code en production, même imparfait, mérite du respect, et plus le système est grand, plus il faut d’abord du temps pour le comprendre
Microservices et outils
- Les microservices ajoutent des appels réseau à un problème déjà difficile : découper correctement un système
- Les outils peuvent fortement améliorer la productivité et la compréhension des développeurs
- dans un nouvel environnement, il vaut la peine d’investir du temps pour apprendre les outils
- deux semaines passées à maîtriser les outils peuvent doubler la vitesse de développement
- sans documentation, il faut aller demander à d’autres développeurs et creuser soi-même
- La complétion de code de l’IDE évite d’avoir à mémoriser toute une API et est presque indispensable en développement Java
- Un bon débogueur est extrêmement important
- points d’arrêt conditionnels
- évaluation d’expressions
- exploration de la pile
- Un nouveau développeur devrait apprendre en profondeur le débogueur disponible ; cela peut lui en apprendre davantage sur l’ordinateur qu’un cours universitaire
Systèmes de types, expressions et DRY
- La plus grande valeur d’un système de types réside dans le support outillé qui affiche les actions possibles quand on tape un point
- La sûreté des types est utile aussi, mais la complétion et la navigation dans le code ont une valeur pratique encore plus grande
- Il faut se méfier des développeurs qui utilisent le système de types de manière trop abstraite
- les génériques peuvent être particulièrement dangereux
- dans la plupart des cas, il préfère les limiter à des classes conteneurs
- Plutôt que d’entasser de courtes conditions sur une seule ligne, mieux vaut les décomposer en variables intermédiaires avec des noms explicites : c’est meilleur pour le débogage et la compréhension
- DRY est un bon conseil, mais il faut de l’équilibre
- un code dupliqué simple et clair vaut parfois mieux qu’un modèle complexe de callbacks, closures ou objets
- si l’élimination de la duplication augmente elle-même la complexité, le coût peut dépasser le bénéfice
Séparation des préoccupations, closures et journalisation
- La séparation des préoccupations est une idée puissante, mais en pratique elle peut faire perdre du temps en obligeant à naviguer entre plusieurs fichiers pour comprendre un comportement
- Comme alternative, l’auteur préfère la locality of behavior
- en plaçant le code près de « la chose qui agit », on voit immédiatement ce qu’il fait en regardant l’élément concerné
- Les closures conviennent bien pour abstraire des opérations sur des collections, mais en petites quantités, comme du sel
- Le « callback hell » de JavaScript est un exemple de complexité créée par un usage excessif des closures
- La journalisation est très importante, surtout en environnement de déploiement cloud
- on ajoute des logs à chaque branche logique importante
- pour les requêtes qui traversent plusieurs machines, on inclut un request ID pour regrouper les logs
- si possible, on ajuste dynamiquement les niveaux de log
- si possible, on ajuste les niveaux de log par utilisateur pour déboguer les problèmes d’un utilisateur précis
- Les bibliothèques de logging peuvent être complexes, mais investir dans une bonne infrastructure de journalisation rapporte beaucoup plus tard
Concurrence, optimisation et API
- La concurrence est un domaine dont il faut se méfier, et l’auteur préfère des modèles aussi simples que possible
- des handlers de requêtes web sans état
- des files de travaux distants qui ne dépendent pas les unes des autres
- des API simples
- Sur le web, l’optimistic concurrency peut très bien convenir
- Même les structures de données concurrentes comme ConcurrentHashMap en Java doivent être utilisées avec prudence
- L’optimisation ne devrait commencer qu’après identification d’un problème concret à l’aide d’un vrai profil de performance
- il ne faut pas regarder uniquement le CPU
- un accès réseau équivaut à beaucoup de cycles CPU, donc il faut le réduire si possible
- voir des boucles imbriquées et se lancer immédiatement dans l’élimination d’un
O(n^2)peut accroître la complexité
- Une bonne API doit éviter de faire trop réfléchir les développeurs
- si l’auteur d’une API reste enfermé dans une vision d’implémentation ou de domaine, elle devient difficile à utiliser
- pour les cas simples, il vaut mieux fournir une API simple et, pour les cas complexes, une autre API plus complexe : cette stratification fonctionne bien
- dans une approche orientée objet, le comportement devrait autant que possible se trouver sur l’objet concerné
- L’exemple des stream/collector en Java est critiqué comme une API qui détourne inutilement des tâches courantes
Parsing, Visitor Pattern et frontend
- Les parseurs en recursive descent sont jugés amusants et élégants
- Les générateurs de parseurs rendent le code produit difficile à comprendre et à déboguer, tout en masquant la nature récursive de la grammaire
- En pratique, la plupart des parseurs de production sont en recursive descent, et l’auteur recommande Crafting Interpreters
- Le Visitor pattern est résumé très brièvement comme « mauvais »
- Séparer frontend et backend, puis les relier via HTTP avec une bibliothèque SPA et une API JSON GraphQL revient presque à construire deux nids de complexité
- Il faut se méfier de la tendance à utiliser de grosses bibliothèques frontend même pour de simples sites web ou des formulaires envoyés en base de données
- Pour réduire la complexité, l’auteur a créé htmx et hyperscript
- conserver un HTML simple
- éviter beaucoup de JavaScript
- React est peut-être meilleur pour l’emploi et pour certains types d’applications, mais il est vu comme un choix qui fait entrer dans la voie de la complexité frontend
Modes, FOLD et impostor syndrome
- Le développement suit beaucoup de modes, particulièrement visibles côté frontend
- Il faut se montrer sceptique face aux nouvelles approches présentées comme révolutionnaires
- en informatique, beaucoup d’idées ont déjà été essayées au moins une fois
- de mauvaises idées peuvent revenir sous un nouveau nom
- Il est bon que des développeurs senior disent publiquement : « c’est trop complexe, c’est difficile à comprendre »
- FOLD signifie Fear Of Looking Dumb, c’est-à-dire le fait de ne pas oser reconnaître la complexité par peur d’avoir l’air idiot
- si un senior dit qu’une chose est complexe, un junior aura plus de facilité à admettre qu’il ne la comprend pas non plus
- FOLD est l’une des principales sources de pouvoir de la complexité, surtout chez les jeunes développeurs
- Les développeurs oscillent entre l’impression de tout maîtriser et celle de ne rien comprendre, et l’impostor syndrome est fréquent
- Si tout le monde se sent imposteur, alors personne ne l’est vraiment, et un jeune développeur peut poursuivre sa carrière malgré la frustration et l’inquiétude
Lectures recommandées et conclusion
- Lectures recommandées
- La conclusion finale est la même qu’au début : la complexité est très, très mauvaise
1 commentaires
Avis sur Hacker News
Il est étrange de voir des gens intelligents attirés par la complexité comme des papillons par la flamme
Il faut des années pour apprendre à combattre l’envie de surconcevoir
Une fois qu’on commence à la voir, elle devient difficile à ignorer, et désormais je peux dire immédiatement si du code est surconçu
Malheureusement, environ 99 % du code semble surconçu, et les développeurs ont de fortes incitations à maximiser leur propre caractère irremplaçable et leurs heures facturables
Même des développeurs qui paraissent totalement mécaniques et dénués d’ego tombent souvent dans la surconception, et cela fonctionne inconsciemment
Beaucoup de développeurs ne réfléchissent pas consciemment à chaque ligne de code qu’ils écrivent : ils se fixent un objectif, puis produisent le premier code qui les rapproche un peu de cet objectif, sans se rendre compte qu’à chaque étape il existait une meilleure alternative
D’abord, j’aime les puzzles intéressants. Or le code commercial, quand il est bien fait, est souvent assez ennuyeux ; inconsciemment, je finis donc par pousser des fonctionnalités amusantes à implémenter. Et par amusantes, j’entends des fonctionnalités qui rendent tout excessivement compliqué
Ensuite, quand je suis en train de programmer quelque chose, tous les choix que je fais me paraissent évidents et nécessaires. Ce n’est que plus tard, après avoir pris de la distance avec le code et tenté de le comprendre avec un regard neuf, que je vois à quel point j’ai mis le bazar
Pour la plupart des problèmes, la solution la plus visible est souvent assez complexe, et savoir où trouver une solution simple exige sagesse, savoir-faire et connaissance du domaine. Les solutions simples et propres sont rarement évidentes
« Nous sommes en train d’implémenter petit à petit notre propre demi-file de messages. Utilisons simplement une file de messages standard », « Nous sommes en train de créer un protocole de framing binaire maison plein de bugs. Utilisons simplement protobuf/msgpack », « Ne créons pas un protocole RPC maison pour récupérer les données, utilisons REST sur HTTP. Comme ça, on pourra mettre nginx au milieu pour mettre en cache les réponses du backend et jeter aussi notre cache maison »
Au bout du compte, si l’on a le temps et que l’on est récompensé pour le faire, on peut écrire du code parfait, simple et sans répétition. Mais le plus souvent, ce qui est récompensé, c’est de sortir quelque chose, et de montrer sa compétence technique par la quantité de travail, d’intelligence et de capacité de conception investie dans cette sortie
La conclusion naturelle, c’est que tout devient un amas gonflé et surconçu de solutions provisoires, réécrit tous les 3 à 7 ans
Je n’ai pas consulté de données, mais j’imagine que la « demi-vie de réécriture » est corrélée au turnover ou à la durée moyenne de présence dans l’entreprise. Même si les gens faisaient davantage d’efforts pour ne pas surconcevoir, il est de toute façon très probable que le tout soit réécrit
Pour un perfectionniste, c’est vraiment agaçant, mais il arrive que créer quelque chose de complexe et surconçu soit mieux récompensé que de réfléchir plus longtemps à la meilleure solution simple. Il existe peut-être de meilleures organisations, mais en 9 ans comme ingénieur logiciel, je n’en ai pas encore trouvé
Les projets open source sont le meilleur contre-exemple qui me vienne à l’esprit, mais même de bonnes bibliothèques sont souvent réécrites ou sortent une nouvelle version quand le mainteneur change. Les incitations financières sont très différentes entre l’open source et le fatras d’entreprise que voient beaucoup d’ingénieurs logiciels à plein temps sur HN. C’est un peu comme comparer un article universitaire bien peaufiné à un e-mail professionnel écrit à la va-vite
Je me souviens que Casey, de Handmade Hero, appelait son style de programmation « basé sur la compression ». L’idée est d’écrire d’abord le code, puis de séparer progressivement ce qui va ensemble
On abstrait quand il y a répétition, pas parce qu’on a consciemment conçu une abstraction. J’utilise de plus en plus cette approche
Cela ne veut pas nécessairement dire qu’il est faux en soi, mais s’il s’agit d’évaluer la qualité du travail des autres, il semble très probable qu’un fort biais soit en jeu
J’aime vraiment ce site, il me fait toujours rire. Ma partie préférée est surtout celle sur les microservices
« grug se demande pourquoi gros cerveau prend le problème le plus difficile, découper correctement un système, et y ajoute en plus des appels réseau. pour grug, cela semble très déroutant »
« la complexité est très, très mauvaise »
« si grug doit choisir entre complexité et combat en un contre un contre tyrannosaure, grug choisit tyrannosaure. au moins grug peut voir tyrannosaure »
J’ai quelques réserves sur la partie consacrée aux types
grug dit que la valeur d’un système de types réside à plus de 90 % dans l’apparition magique de la liste de ce qu’on peut faire quand on appuie sur le point au clavier, mais dans mon entreprise, nos juniors déploient souvent en production du code qui casse à cause d’accès à
null, et Sentry nous le signalePendant les périodes de développement intensif, on voit environ un bug d’accès à
nulldétecté par jour et par développeur juniorAvec un vrai système de types doté d’une vérification statique, l’IDE dirait « ça peut être
null, tu es sûr ? », ce qui serait extrêmement utileEt même sans typage statique, l’autocomplétion est possible
Le passage « les chamans des systèmes de types à gros cerveau disent que la précision des types est au cœur du système de types, mais grug voit que ces chamans ne déploient pas souvent de code. Le code non déployé est peut-être correct dans un certain sens, mais ce n’est pas la correction dont parle grug » est impoli et inutile
J’ai surtout déployé du code en C, PHP, Python, Haskell et Python typé, et dans les langages typés, le taux de bugs qui arrivent jusqu’en production est nettement plus bas. C’est l’une des raisons pour lesquelles j’aime les types
De plus, le refactoring devient beaucoup plus simple. Quand on modifie quelque chose de largement utilisé, on peut repérer de manière fiable en quelques secondes, dans toute la base de code, les sites d’appel cassés, ce qui aide énormément à améliorer par itérations une base de code qui grossit
Tu acceptes plutôt un système de types de compromis, qui détecte certains problèmes et fournit surtout la magie de l’autocomplétion, sans t’enliser dans tous les détails nécessaires à une preuve complète de correction
Il semble considérer que le typage statique au niveau de C ou Java est acceptable, voire souhaitable, tandis que les choses plus sophistiquées qu’on voit dans Rust ou Scala sont une perte de temps. Je pense qu’il a complètement tort, mais c’est la vie
J’ai compris « chaman des systèmes de types à gros cerveau » comme désignant non pas forcément quelqu’un qui écrit du code, mais par exemple quelqu’un qui vend des formations sur le sujet et excite les foules
Plus haut dans l’article, il emploie aussi « chaman » à propos d’Agile, et il y a pas mal de gens dont l’activité ressemble davantage à de la vente de formations qu’à du vrai développement logiciel
Travailler avec des gens obsédés par les hiérarchies de types est difficile à supporter, et leur justification reste généralement dans le monde des « et si » et des « mais ce n’est pas sound »
Une grande partie de la dégradation de qualité provoquée par les systèmes de types vient de gens qui croient qu’en mettant suffisamment de types, on peut empêcher complètement les bugs, ce qui est faux
J’ai l’impression que dans les prochains mois tout le monde va monter dans le train HTMX, que ça va secouer la tête de beaucoup de jeunes développeurs, économiser énormément d’énergie dans le monde et rendre beaucoup de gens heureux
Puis, quand ces jeunes curieux continueront à cliquer sur les liens de htmx.org et découvriront hyperscript, ce sera comme le moment où les vampires surgissent dans Une nuit en enfer
Quelqu’un se lasse de la complexité de JavaScript et crée une bibliothèque JavaScript simple, les gens affluent vers cette simplicité, la bibliothèque doit prendre en charge toutes les fonctionnalités du Web et devient complexe, puis quelqu’un d’autre, lassé de cette complexité, crée une bibliothèque JavaScript simple
J’ai commencé en JavaScript pur, je me suis battu pendant des années avec IE5/6, jQuery nous a tous sauvés, j’ai sauté AngularJS parce que ce n’était pas terrible, et quand la bêta de React est sortie, je l’ai aimée pour ses idéaux de programmation fonctionnelle. Maintenant, je me fraie un chemin à travers la transpilation, le hot reload, Typescript et des piles de lourdes bibliothèques React
J’ai aussi réalisé quelques projets avec Intercooler et HTMX. HTMX est globalement solide, mais ce n’est pas le premier train à passer par ce village
J’aimerais voir une vraie critique de htmx
Personnellement, je pense que l’un des grands défis durables du Web a été de trouver comment bien mettre les pages à jour, et que nous avons continué à tout essayer. D’où une certaine fatigue, et certaines idées deviennent radicales ou se transforment avec le temps en bric-à-brac
Htmx ressemble à une réaction façon grug : faire moins et s’en tenir à YAGNI
L’avenir est incertain, mais des travaux comme les signals semblent toujours relever d’une quête sacrée. De nombreuses tentatives sont menées dans plusieurs directions, et nous sommes encore en train d’ouvrir ce front et d’autres
MobX et Svelte ont déjà parcouru un long chemin eux aussi. Le voyage n’est pas encore terminé, et le fait de rester aux prises avec le monstre de la complexité n’est pas, selon moi, un signe de faiblesse — même si une pensée conservatrice ou grug pourrait le voir ainsi — mais l’effort nécessaire pour parvenir non pas à une approche seulement simple, mais à quelque chose de simple et bon
_="on load wait 5s then transition opacity to 0 then remove me"Ah, non
_="on htmx:error(errorInfo) fetch /errors {method:'POST', body:{errorInfo:errorInfo} as JSON} "Ah, non !
Je suis développeur depuis 30 ans, et je reconnais qu’à mes débuts j’étais arrogant et que je me croyais plus intelligent que les autres. À l’époque, j’étais du côté « gros cerveau » qui aime tous les démons de la complexité
Dix ans plus tard, je m’étais rapproché du développeur « Grug brain », et aujourd’hui je me concentre sur la solution la plus simple qui fonctionne, tout en sachant qu’elle peut ne pas être parfaite. Et ce n’est pas grave, parce que cela permet de se rapprocher de ce qui est juste et de s’améliorer par itérations
La meilleure chose qu’on puisse faire en tant que développeur, c’est supprimer du code. Là, une exigence que nous maintenions depuis deux ans vient soudain de ne plus en être une, et je suis vraiment enthousiaste à l’idée d’arracher beaucoup de code. Parce que tout va devenir plus simple
C’est comme si l’on sentait physiquement de l’espace se libérer
Grug est aussi apparu dans les commentaires de l’article Philosophy of Software Design il y a une semaine, et je trouve que la discussion y était plutôt bonne. https://news.ycombinator.com/item?id=38011938
« J’ai exactement le même ressenti à propos de grug. Je ne pense pas que les gens soient réellement d’accord sur ce qui est simple, donc faire comme si sa propre “simplicité” était une évidence qu’un homme des cavernes approuverait aussi me semble relever de la pose »
La simplicité est souvent l’une des choses les plus complexes à découvrir. J’ai vu beaucoup de gens convaincus que tout autour d’eux — sauf ce qu’ils font eux-mêmes — est complexe et doit être ramené de force à la simplicité. Ça ressemble à une posture dangereusement faible qui s’accroche à l’autorité
La philosophie du grug brain consiste à choisir la simplicité à tout prix, sauf quand elle est absolument impossible à éviter
La philosophie du gros cerveau, vue par grug, consiste à choisir la réutilisabilité à tout prix, sauf quand elle est absolument impossible à éviter
Le problème de cette philosophie est qu’elle fige les choix de conception de première génération et rend l’amélioration itérative plus difficile
Il est vrai que la simplicité est difficile à trouver, mais la clé pour la trouver, c’est l’amélioration itérative
Les minimums locaux se déplacent en fonction de la complexité de ce qu’on construit, donc plusieurs points de vue assez intelligents peuvent être vrais en même temps
Ce n’est pas un indicateur parfait, mais il pointe dans la bonne direction, et il fonctionne très bien à l’échelle logarithmique
J’ai utilisé et expliqué d’innombrables fois le concept de clôture de Chesterton, et je suis content d’en connaître le nom
C’est quelque chose qui arrive très souvent quand on travaille avec des développeurs débutants. Quand ils voient de la « vieille merde legacy », leur première réaction est de vouloir l’arracher ou tout jeter pour repartir de zéro
Dans certains cas, les laisser essayer peut aussi être formateur, mais il est bon de se rappeler que ceux qui nous ont précédés n’étaient pas tous de parfaits idiots et qu’il y avait généralement une raison à ce choix
Parfois, c’est vraiment du vieux code crade qu’il faut remplacer, mais même dans ce cas, il contient souvent une trace durement acquise de tous les recoins et cas limites qu’il faut comprendre et traiter pour construire quelque chose dans ce domaine
La partie sur les tests est vraiment bonne. Elle correspond exactement à ce que j’ai appris au fil des années
Pour trouver des bugs, les tests d’intégration sont le bon niveau
Les objets mock ont tendance à trop compliquer les choses, et même si j’en utilise encore parfois, j’évite de le faire de manière systématique
Les tests unitaires sont trop fragiles face au refactoring, tandis que les tests d’intégration aident au refactoring
Les tests unitaires sont plus difficiles à écrire et à maintenir, mais ils sont beaucoup plus faciles à comprendre et à déboguer quand ils échouent, et tiennent donc bien mieux sur le long terme
Le pire type de test, c’est le test d’intégration qui dépend en douce du fait qu’un autre test d’intégration ait été exécuté avant lui. Dans 99 % des cas ça passe, puis un changement modifie l’ordre et tout casse
Si l’équipe a du code simple, les tests sont d’une grande aide. Mais si l’équipe n’a pas de code simple — et en général ce n’est pas le cas — il vaut mieux passer son temps à simplifier le code qu’à écrire des tests
Prendre une seule fonction feuille comme unité est souvent un niveau trop bas, mais un module plus grand avec une interface relativement stable peut être une bonne unité productive à tester
« La complexité est très, très mauvaise »
« La meilleure arme contre le démon spirituel de la complexité est le mot magique “non” »
« Triste mais vrai : après avoir appris à dire “oui”, apprendre à rejeter la faute sur d’autres grug quand on échoue est le conseil de carrière idéal »
Voilà la sagesse complexe de grug
Cela avait déjà été discuté à l’époque
The Grug Brained Developer - https://news.ycombinator.com/item?id=31840331 - juin 2022, 374 commentaires