Tapez le code vous-même
(haskellforall.com)- Taper le code soi-même et s’entraîner à le reconstituer de mémoire vérifie plus rigoureusement la compréhension et la mémoire que le simple copier-coller
- Le freecoding est la capacité à écrire du code caractère par caractère en gardant en tête la syntaxe, les types et les noms, et cela reste nécessaire même à l’ère des outils
- La syntaxe n’est pas un bruit qui gêne la pensée de haut niveau, mais un moyen de condenser un sens précis pour rendre possible une réflexion de niveau supérieur
- Si l’on ne fait que consulter vaguement les types et schémas, la conception du système devient floue, et sans compréhension du modèle de types, les échappatoires comme
as anyse multiplient - Quand la mémoire des noms et la compréhension du travail existant font défaut, les agents ont plus de chances de produire des implémentations redondantes, et il devient aussi plus difficile de relire les sorties et les tests
Pourquoi il faut taper le code soi-même
- Dans les cours “Learn X the hard way” de Zed Shaw, il était conseillé de ne pas copier-coller les exemples mais de les saisir soi-même, et plus récemment il recommande plus fermement encore de les supprimer une fois l’exercice terminé puis de les reconstruire de mémoire
- En psychologie cognitive, le fait que la compréhension soit meilleure quand on produit activement un contenu que lorsqu’on le consomme passivement est appelé l’effet de génération
- Comme le disait Richard Feynman, « Ce que je ne peux pas créer, je ne le comprends pas » : s’entraîner à reconstruire du code à partir de la mémoire met à l’épreuve à la fois la compréhension et la mémoire
- Même à l’ère du coding avec agents, cela ne signifie pas qu’il faille renoncer aux outils de développement, mais qu’il faut parfois développer la capacité d’écrire du code caractère par caractère sans le confort de ces outils
- Ce type d’entraînement vise à pouvoir “freecoder” en gardant en tête les éléments de détail de la programmation, comme la syntaxe, les types et les noms
Le freecoding et la connaissance détaillée gardée en tête
- Le freecoding est la capacité à écrire directement du code de mémoire, ce qui suppose de garder en tête des éléments fondamentaux comme la syntaxe, les types et les noms
-
Syntaxe et structure
- Il faut être à l’aise avec les mots-clés, la ponctuation et les constructions du langage
- Il ne s’agit pas d’une simple mémorisation grammaticale, mais d’une capacité à se représenter précisément la forme du code
-
Types et schémas
- Il faut être familier et à l’aise avec le système de types et le modèle de données
- Si l’on en reste à consulter à chaque fois les tables, colonnes, relations et structures de types du projet, il devient difficile de concevoir au niveau du système
-
Noms
- Il faut pouvoir se rappeler avec précision les noms des fonctions, méthodes, classes,
import, fichiers et packages - Quand le projet et ses dépendances changent, cette connaissance doit elle aussi rester à jour
- Si l’on n’est pas capable de taper avec un certain niveau de précision le code qu’on imagine mentalement, on est probablement moins dans une compréhension claire que dans l’illusion de comprendre
- L’anglais n’est pas un langage aussi précis que le code, et cela rejoint un autre texte, A sufficiently detailed spec is code, selon lequel une spécification suffisamment détaillée finit par ressembler à du code
- Il faut pouvoir se rappeler avec précision les noms des fonctions, méthodes, classes,
La syntaxe rend possible la pensée de haut niveau
- Même si les IDE ou les agents de code peuvent corriger la syntaxe, la capacité à la manipuler directement reste importante
- Si l’on a du mal à apparier des parenthèses, on peut aussi s’interroger sur sa capacité à relier avec fluidité les prémisses logiques et les conclusions d’autrui
- L’attitude qui consiste à négliger les détails peut mener à une analphabétie fonctionnelle où l’on communique à l’ambiance plutôt qu’en distinguant clairement le sens des mots
- Les exemples de prompts LLM paraissent plausibles en surface, mais à la lecture attentive ils contiennent parfois en même temps des consignes contradictoires
- « Ne propose pas d’outils externes ni d’alternatives qui ne figurent pas parmi les skills listés ci-dessus »
- « Si la tâche exige des capacités qui dépassent les skills disponibles, dis-le »
- La capacité à traiter avec précision les petits éléments de grammaire, d’orthographe et de structure n’est pas séparée de la capacité à comprendre correctement la vue d’ensemble
- La syntaxe n’est pas un détail qui entrave la pensée de haut niveau, mais un outil mental qui compresse et rend possible une pensée de niveau supérieur
- Une annotation de type peut être plus précise et plus concise qu’une explication en langage naturel
x est un tableau d’objets, et chaque objet possède une propriété `domain` obligatoire qui stocke une chaîne de caractères et une propriété `port` optionnelle qui stocke un nombrex : { domain: string, port?: number }[]
Les types et les schémas sont des indices centraux de la conception d’un système
- Dans The Mythical Man-Month, Fred Brooks dit qu’en montrant les tables, la structure devient généralement claire même sans organigramme
- Si l’on utilise une base de données, il faut connaître sur le bout des doigts les tables, les noms de colonnes et les relations du projet
- Au lieu de ne récupérer ces informations qu’au moment du besoin, il faut les comprendre à l’avance et les garder en tête pour pouvoir faire une conception au niveau système efficace
- Sans cet effort, la confusion de la pensée se reflète facilement dans un schéma de base de données dénormalisé, rempli de données redondantes ou similaires
- L’expérience des langages fortement typés comme Rust ou Haskell met bien en évidence les avantages d’un modèle mental solide des types
- S’entraîner à développer un « vérificateur de types mental » précis ou un « borrow checker mental » aide aussi lorsqu’on utilise des langages faiblement typés
- Sans cet effort de raisonnement abstrait, on risque de passer à côté de bases de la modélisation de données comme rendre les états invalides inexprimables
- Si l’on ne comprend pas comment les types s’articulent, on finit par parsemer son code TypeScript de
as any - Si l’on n’accepte pas l’inconfort de penser aux types sur le chemin normal, le chemin anormal du débogage des erreurs de type sera encore plus difficile à supporter
- Cela ne veut pas dire qu’un Haskeller ou un Rustacean écrit toujours un meilleur code, mais à conditions égales, être à l’aise avec les types aide
Il faut se souvenir des noms pour pouvoir réutiliser
- Il faut pouvoir retrouver facilement les noms des fonctions, méthodes, classes,
import, packages et fichiers souvent utilisés dans un projet ou ses dépendances - C’est une forme particulière d’un principe plus général : bien connaître ce qui existe déjà, autrement dit le travail antérieur (prior art)
- Si beaucoup de gens s’en remettent aux agents de code, c’est parce qu’ils ne connaissent pas les travaux réutilisables qui font déjà ce qu’ils veulent, ce qui conduit l’agent à réinventer la roue
- Si l’on ignore l’existence des SaaS boilerplate projects, on peut facilement croire que l’agent doit faire tout le scaffolding depuis zéro
- Pour ce type de besoin, cloner un projet open source éprouvé conçu à cette fin est plus rapide, moins cher et plus fiable que de demander le même travail à un agent
- Quand quelqu’un prédit qu’un LLM pourra construire un navigateur complet d’ici quelques années, on peut objecter qu’en forkant Chromium c’est déjà possible aujourd’hui, avec en plus des modifications et une maintenance plus faciles
- La mémoire des noms est aussi importante pour la réutilisation du code à l’intérieur d’un même projet ou d’une même entreprise
- Si l’on ne sait pas quoi chercher, on ne peut pas construire sur le travail de ses collègues
Relire la sortie des agents exige une compréhension humaine
- Les agents peuvent aider à explorer les noms et à générer du code, mais une nouvelle question se pose : peut-on relire leur production de manière réellement pertinente ?
- Si l’on ne connaît pas les fonctionnalités existantes, il devient difficile de juger si l’agent duplique une implémentation déjà présente
- Si l’on comprend moins bien le code que l’agent, il devient aussi difficile de relire correctement la qualité de sa sortie
- On peut demander à un agent de générer des tests, mais si l’on n’examine pas soigneusement ces tests, ils peuvent eux-mêmes n’être qu’un code vide de sens
- L’exemple réel montrait des tests qui, au lieu d’appeler le code d’implémentation, appliquaient directement
someouincludesà des tableaux et des chaînes pour ne vérifier que des valeurs attenduesdescribe("abort detection logic", () => { it("detects aborted stopReason in messages", () => { const messages = [ { role: "assistant", stopReason: "aborted", content: [] }, ]; const isAborted = messages.some((m: any) => m.stopReason === "aborted"); expect(isAborted).toBe(true); }); it("detects abort in error string", () => { const error = "The operation was aborted"; const isAborted = error.includes("abort"); expect(isAborted).toBe(true); }); it("does not false-positive on normal errors", () => { const error = "Network timeout"; const isAborted = error.includes("abort"); expect(isAborted).toBe(false); }); it("does not false-positive on normal stop reasons", () => { const messages = [ { role: "assistant", stopReason: "stop", content: [] }, ]; const isAborted = messages.some((m: any) => m.stopReason === "aborted"); expect(isAborted).toBe(false); }); }); - Le développement logiciel comporte beaucoup de frictions ordinaires, et si l’on choisit de ne pas dépasser la petite friction qui consiste à se souvenir des noms, on risque aussi de ne pas dépasser la friction plus grande qu’implique la relecture des tests
- Comme les agents de code prennent les instructions de l’utilisateur pour contexte principal, un utilisateur intellectuellement paresseux peut facilement pousser l’agent dans la même direction
Persévérance et maîtrise ne sont pas séparées
- L’eustress est un stress bénéfique : se pousser à faire des choses nouvelles et difficiles développe une tolérance aux petits inconforts et aide ensuite à franchir des inconforts plus grands
- Si l’on évite toujours l’inconfort, on entre dans un cercle vicieux d’impuissance et de frustration croissantes
- Développer dans un domaine la précision, la mémoire et la pensée structurée améliore aussi les capacités dans d’autres domaines
- De même que les LLM généralisent à partir de leurs données d’entraînement, les humains généralisent eux aussi d’un domaine à l’autre les habitudes et compétences qu’ils y ont acquises
- Le développement logiciel implique par nature de sortir régulièrement de sa zone de confort, dans la même veine que cet autre texte : Software engineers are not (and should not be) technicians
1 commentaires
Avis sur Lobste.rs
Tout à fait d’accord. Après avoir terminé un exercice, effacer ce qu’on vient de faire et le refaire de mémoire est vraiment important
Si on bloque, on peut regarder un indice, mais il y a peu d’habitudes plus importantes que d’essayer de reconstruire de mémoire, autant que possible, ce qu’on vient juste de faire
Il vaut mieux taper soi-même les messages de commit et la documentation
Les programmeurs n’aiment pas ce type d’écriture, donc il est facile de se dire « un LLM peut bien l’écrire à ma place », mais l’écrire soi-même oblige à confronter au même endroit l’expérience utilisateur et les choix d’implémentation. Cela amène des remises en question du type : « pour faire X, il faut passer
-Y… attends, est-ce vraiment la meilleure solution ? » « ici, Y corrige X… mais est-ce qu’on ne pourrait pas aussi le faire avec Z ? »J’ai ri au passage disant que « si quelqu’un a du mal à équilibrer des parenthèses, on peut douter de sa capacité à relier avec aisance les prémisses logiques de quelqu’un d’autre à ses conclusions », mais je me suis aussi senti un peu visé
Pour ma défense, il arrive que les fonctions deviennent vraiment énormes
Corriger des déchets de vibe coding qu’on ne comprend pas est aussi, en pratique, une bonne manière d’apprendre. Ça force à beaucoup taper, et à travailler dans un vrai contexte plutôt que dans le vide
Le réécrire à la main m’a servi à retrouver des réflexes de programmation qui s’étaient rouillés ces 8 derniers mois. J’aime le résultat de la réécriture, et ça marche réellement mieux. Les LLM restent utiles pour expliquer des choses ou débloquer certains points, mais c’est bien plus agréable d’avoir l’impression de connaître l’ensemble du codebase
Je ne vois pas bien pourquoi le prompt « ne suggérez jamais d’outils externes ni d’alternatives qui ne figurent pas dans les capacités listées. Si une fonctionnalité dépassant les capacités disponibles pour cette tâche est nécessaire, dites-le » contiendrait des consignes contradictoires
Dire « je ne peux pas faire cela avec les seules capacités fournies » est cohérent avec les deux consignes. Il y aurait conflit si la dernière phrase disait « dites quelles capacités sont nécessaires », mais telle qu’elle est formulée actuellement, je n’y vois pas de contradiction
La deuxième phrase peut se lire comme une instruction demandant au modèle non pas d’impliquer négativement l’existence d’un outil externe ou d’une alternative, mais d’en affirmer constructivement l’existence
Dire que « les personnes incapables de s’exprimer avec une clarté fonctionnelle ont presque sans exception aussi du mal à écrire des phrases correctes sur le plan orthographique ou grammatical » me semble être un préjugé assez brutal envers les personnes atteintes de dyslexie ou simplement celles qui pensent différemment
Bien sûr, ce n’est pas forcément affirmer en retour que mal écrire l’orthographe ou la grammaire signifie automatiquement manquer de clarté fonctionnelle, mais dans un sens comme dans l’autre, la formulation manque de nuance
Pour le voir de manière plus constructive, on peut penser aux éditeurs nodaux. Les systèmes à base de nœuds ont beaucoup de problèmes dans leurs implémentations actuelles, mais bien conçus, ils peuvent encadrer la manière d’écrire des programmes au point d’éliminer certains types d’erreurs de syntaxe. Par exemple, si un nœud attend une chaîne de caractères, on ne peut pas lui passer un nombre. Non pas parce qu’une contrainte est imposée au moment du build ou à l’exécution, mais parce qu’il devient tout simplement impossible de « dire » un nombre à cet endroit. On peut aussi rendre structurellement impossibles des erreurs comme une mauvaise plage de boucle, un mauvais nombre d’arguments ou un déséquilibre des parenthèses
Écrire du logiciel avec des outils qui imposent structurellement certaines contraintes ne signifie pas qu’on ne comprend pas ces contraintes. Cela signifie simplement qu’on n’a plus à s’inquiéter de faire par inadvertance ce type d’erreur. Et si l’on trouve frustrant qu’un outil ne prenne pas en charge des détails syntaxiques comme le nombre d’accolades d’une fonction ou l’indentation d’un bloc logique, cela ne veut pas non plus dire qu’on ne comprend pas pourquoi ces éléments syntaxiques importent
Si j’ai pris l’exemple des systèmes nodaux, c’est parce qu’ils retirent l’aspect « on jette et on oublie » des LLM ainsi que la dimension de vibe coding sans réfléchir, et qu’ils isolent uniquement la question syntaxique. Si on enlève les LLM de l’équation, l’argument centré sur la syntaxe devient assez faible
Je suis d’accord avec le reste du texte, mais considérer la maîtrise de la syntaxe comme un indicateur fondamental de la compréhension du code de quelqu’un ou de sa capacité à écrire du bon code me paraît être une très mauvaise direction
Je comprends aussi que la remarque soit faite de bonne foi, et je ne veux pas paraître sur la défensive. Je pensais avoir essayé de formuler cela de manière à ne pas donner l’impression d’un propos aussi peu nuancé, mais s’il existe une autre tournure ou une autre structure qui fasse mieux passer la même idée, je suis preneur
Cela dit, je ne voudrais pas supprimer entièrement ce point. L’idée essentielle que je cherche à transmettre est que, lorsqu’une personne commence à éviter expérientiellement un inconfort mental, ce sont en général l’orthographe et la grammaire qui se dégradent en premier. Je pense qu’il doit être possible d’ajuster l’argument pour que les personnes dyslexiques n’en fassent pas les frais