4 points par GN⁺ 2023-10-07 | 1 commentaires | Partager sur WhatsApp
  • La keynote de Julia Evans à Strange Loop explique pourquoi des techniques qui semblent « fondamentales », comme DNS, Bash, HTTP ou SQL, restent longues à apprendre, et comment abaisser les barrières à l’apprentissage
  • La difficulté de Bash vient du grand nombre de petites exceptions et pièges, comme le fait que set -e soit désactivé dans un appel de fonction à l’intérieur d’une condition ||, ainsi que du fait que beaucoup de gens n’utilisent Bash qu’occasionnellement, ce qui rend sa maîtrise difficile à mémoriser avec précision
  • HTTP et SQL cachent, derrière une surface simple, une implémentation de navigateur de 20 millions de lignes, de nombreux en-têtes et drapeaux, ainsi que l’écart entre l’ordre d’écriture et l’ordre d’exécution en SQL, ce qui alourdit l’apprentissage
  • Pour DNS, les bibliothèques, les caches et la communication avec les serveurs de noms autoritaires sont peu visibles pour l’utilisateur, et la sortie de dig est elle aussi complexe, d’où l’importance d’outils et de démonstrations qui rendent les mécanismes cachés visibles
  • Un bon accompagnement de l’apprentissage consiste à partager des outils et des références, à réduire les grandes listes à de petites listes réellement utiles, à expliquer dans l’ordre chronologique ce que fait l’ordinateur, et à partager aussi bien les récits d’échec que les notes sur les bugs

Pourquoi des technologies qui semblent « fondamentales » prennent si longtemps à apprendre

  • La keynote Strange Loop Making Hard Things Easy traite de la manière de rendre plus accessibles des techniques difficiles à apprendre
  • Le point de départ, c’était DNS
    • Trouver l’adresse IP d’un nom de domaine semble simple, mais l’autrice explique qu’elle rencontrait encore des problèmes en configurant des sites web 7 ans après avoir commencé à apprendre DNS, et qu’au total cela lui a pris environ 10 ans
    • Ses amis rencontraient les mêmes difficultés à répétition, et beaucoup de gens vivaient cela comme un problème personnel, en pensant qu’ils « auraient déjà dû comprendre »
  • Pour expliquer plus simplement ce type de sujets, l’autrice a lancé une petite maison d’édition appelée Wizard Zines, en prenant Bash, HTTP, SQL et DNS comme exemples

Bash : les exceptions difficiles à retenir doivent être prises en charge par les outils

  • Bash est un langage de programmation, mais c’est aussi l’un de ceux que l’autrice utilise qui présente le plus de comportements étranges
  • Dans l’exemple de script, même si mv ./*.txt /tmmpp échoue, Bash ne s’arrête pas par défaut et exécute quand même echo "success!"
    • Avec set -e, on peut faire en sorte que le script s’arrête en cas d’échec
    • Mais si une fonction est appelée dans une condition comme f || echo "failed!", alors set -e est désactivé globalement à l’intérieur de cette fonction, et success s’affiche de nouveau
    • Ce comportement n’est pas un bug de Bash : il est documenté
  • L’une des raisons pour lesquelles Bash est difficile, c’est que beaucoup de gens n’écrivent des scripts Bash qu’une fois tous les six mois environ avant de passer à autre chose
    • Lorsqu’un système rarement utilisé est rempli de connaissances dispersées et de pièges, il devient difficile de l’utiliser correctement
  • La réaction « personne ne sait utiliser Bash » n’est pas exacte
    • Beaucoup de gens utilisent Bash, et même sans être parfaits, ils parviennent souvent à faire le travail
    • L’objectif est d’aider quelqu’un qui se retrouve face à une montagne de pièges à atteindre un état où il peut l’utiliser de façon « globalement correcte »
  • ShellCheck est un outil qui mémorise à la place des humains les pièges de Bash difficiles à retenir et les signale
    • shellcheck -o all bad-again.sh affiche l’avertissement SC2310, indiquant que set -e est désactivé pour une fonction appelée dans une condition ||
    • Ce contrôle n’apparaît qu’avec -o all
    • Ce genre d’outil réduit la charge cognitive en laissant l’ordinateur gérer les connaissances dispersées

Les récits d’échec aident davantage au jugement que les « best practices »

  • Même sans créer d’outil soi-même, il est important de faire connaître à ses amis ou collègues les outils utiles que l’on utilise déjà
    • L’autrice dit avoir découvert ShellCheck tardivement, et avoir été contrariée de réaliser qu’elle n’avait pas eu besoin de tout garder en tête pendant tout ce temps
  • Partager des pièges et des récits d’échec relève presque d’un service rendu à la communauté
    • L’exemple de désactivation de set -e dans Bash vient d’une expérience racontée quelques semaines plus tôt par son ami Jesse
    • Connaître les échecs des autres permet d’éviter le même problème sans avoir à le vivre soi-même
  • Des avis tranchés comme « personne ne devrait utiliser Bash » sont moins utiles que des récits concrets sur les problèmes que Bash a réellement causés
    • En entendant la même histoire, certaines personnes décideront d’utiliser ShellCheck et de conserver de petits scripts Bash simples
    • D’autres concluront qu’elles ne veulent pas utiliser Bash du tout
    • Et il est normal que les réactions diffèrent face au même cas

HTTP : il faut le comprendre en supposant un navigateur de 20 millions de lignes

  • Une réponse HTTP peut sembler avoir une structure simple : code de statut, en-têtes et corps
  • Mais la question « pourquoi faut-il définir cet en-tête ? » mène très vite au comportement du navigateur
    • Firefox représente environ 20 millions de lignes de code
    • Les navigateurs ont évolué depuis les années 1990, et leur modèle de sécurité a lui aussi continuellement changé pour suivre les attaques et les évolutions du web
  • Pour comprendre pourquoi un sujet est difficile, il faut parfois regarder s’il repose sur une base de code énorme
    • Il ne s’agit pas seulement de HTTP, mais aussi de CSS, JS, etc., et la complexité des navigateurs modernes aide à expliquer la barrière d’apprentissage de HTTP
  • Les grandes listes sont plus faciles à comprendre lorsqu’on les réduit à de petites listes
    • La liste des en-têtes de requête HTTP compte plus de 43 éléments, sans compter les en-têtes non officiels
    • Dans sa BD sur les en-têtes de requête HTTP, l’autrice présente les 15 en-têtes qu’elle connaît et utilise
    • Les « en-têtes les plus importants » ne constituent pas une liste objective, mais une liste subjective fondée sur ce que l’on connaît et utilise
    • Par exemple, il suffit souvent de savoir que définir Accept-Encoding à gzip permet d’obtenir une réponse compressée
  • On peut aborder les outils en ligne de commande de la même manière
    • La page de manuel de grep contient de nombreux drapeaux, mais même après 20 ans d’usage, l’autrice ne les connaît pas tous
    • Pour un débutant, il est utile qu’une personne expérimentée dise : « dans ce système, je n’en connais que 7, et les voici »
    • Une autre personne expérimentée pourra en connaître 7 autres

Les références doivent refléter honnêtement ce qu’on utilise vraiment

  • Quand une information ne peut pas tenir dans la tête, il faut une bonne référence
  • L’autrice explique avoir appris CSS de manière intermittente pendant 20 ans, tout en ne découvrant CSS-Tricks que récemment, il y a environ 2 ans, et pense qu’elle aurait été aidée si elle l’avait connu plus tôt
    • CSS-Tricks semble avoir cessé de publier de nouveaux articles depuis avril après son rachat, mais les anciens contenus restent utiles selon elle
  • Pour HTTP, elle utilise beaucoup Mozilla Developer Network
  • Parmi les références officielles pour HTTP figurent RFC 9110, 9111, 9112, 9113 et 9114, rédigées en 2022
    • On peut y retrouver des détails comme le comportement exact de l’en-tête Connection
    • Sa référence principale reste généralement MDN, mais elle apprécie le fait que les RFC officielles soient bien structurées
  • Lorsqu’on partage des références, il faut distinguer celles qu’on diffuse parce qu’elles ont l’air prestigieuses de celles qu’on utilise réellement au quotidien
    • Même si l’on utilise en pratique des références « moins élégantes » comme w3schools, il est important de dire honnêtement ce qu’on consulte vraiment

SQL : expliquer dans l’ordre chronologique ce que fait l’ordinateur

  • En SQL, l’ordre dans lequel on écrit une requête diffère de l’ordre conceptuel réel d’exécution, ce qui peut dérouter les débutants
  • Le modèle mental SQL utilisé par l’autrice suit cet ordre
    • FROM
    • WHERE
    • GROUP BY
    • HAVING
    • SELECT
    • ORDER BY
    • LIMIT
  • Les bases de données réelles sont plus complexes à cause des optimisations, mais ce modèle chronologique reste utile dans la plupart des cas
    • L’ordre ressemble presque à celui de la requête écrite, sauf que SELECT arrive en cinquième position
  • La question « qu’est-ce que l’ordinateur fait réellement en premier ? » peut s’appliquer à d’autres sujets
    • Pour CORS, on peut comprendre le mécanisme en écrivant, dans l’ordre chronologique, tous les échanges entre le navigateur et le serveur
    • L’autrice cite sa BD sur CORS comme exemple de cette approche
  • Les explications chronologiques paraissent simples, mais elles sont en réalité difficiles à produire, ce qui les rend utiles en collaboration
    • Behind Hello World on Linux décrit ce qui se passe lorsqu’on exécute « hello world » sur Linux
    • L’autrice avait déjà écrit un article similaire il y a 10 ans, mais celui de 2023 était environ 6 fois plus long
    • Elle n’y voit pas le signe que Linux est devenu plus complexe, mais plutôt qu’en 2013 elle comprenait moins bien ce qui se passait dans le temps
  • Dans une équipe, construire ensemble une timeline chronologique de ce qui se passe quand une requête arrive sur un endpoint API permet aussi de relier les connaissances de chacun

DNS : il faut rendre visible le système caché pour développer une intuition

  • DNS est un système où le navigateur, la fonction de bibliothèque qui envoie la requête DNS, les caches et les serveurs de noms autoritaires travaillent ensemble
  • Le problème, c’est qu’une grande partie de cela est cachée à l’utilisateur
    • Il n’est pas facile de savoir quel code de bibliothèque envoie réellement la requête DNS
    • Les caches stockent des données qu’il est difficile d’inspecter facilement, et l’utilisateur ne les contrôle pas
    • La communication entre les caches et les serveurs de noms autoritaires n’est pas visible non plus
  • Avec son amie Marie, l’autrice a créé un petit serveur DNS appelé Mess With DNS
    • L’utilisateur peut y créer des enregistrements DNS pour un domaine
    • Chaque fois qu’une requête arrive depuis un résolveur, le service montre quels messages ont été reçus
    • Dans la démo Strange Loop, elle a créé un CNAME appelé strangeloop pointant vers orange.jvns.ca, et a constaté que le résolveur DNS canadien utilisé par le navigateur demandait les enregistrements A et AAAA
  • Un autre exemple d’outil qui montre ce qui est caché est float.exposed
    • On peut y modifier la significand et l’exponent d’un nombre flottant 32 bits pour voir le nombre flottant suivant et la variation des écarts
  • Une autre raison de la difficulté de DNS est qu’il s’agit d’un immense système distribué
    • L’autrice dit en substance que « plus de 5 millions d’ordinateurs peuvent être impliqués », que l’utilisateur n’en contrôle pas la plupart, et que certains peuvent se comporter autrement que prévu

Quand les outils eux-mêmes deviennent une barrière à l’apprentissage, comme la sortie de dig

  • La sortie des outils DNS peut elle aussi accroître la confusion
  • dig possède le drapeau +norecurse
    • Il permet de demander au résolveur de ne renvoyer que des résultats déjà présents dans son cache
    • dig +norecurse jvns.ca peut servir, par exemple, à vérifier si ce résolveur a mis ce domaine en cache au cours des 5 dernières minutes
  • La sortie de dig peut donner aux débutants l’impression que DNS est plus complexe qu’il ne l’est réellement
    • L’autrice considère que cela tient surtout au maintien d’un format de sortie assez arbitraire, défini dans les années 1990
  • Les « eraser eyes » consistent à ignorer tout le reste d’une sortie complexe pour ne garder que la partie que l’on regarde vraiment
    • Dans l’exemple, il s’agit de se concentrer uniquement sur le code de réponse SERVFAIL
    • D’après la compréhension de l’autrice, SERVFAIL signifie ici à peu près « ce n’est pas dans le cache »
  • Lorsqu’on fait la démonstration d’un outil, il est utile d’expliquer quelle sortie ou quelle partie de l’interface on regarde, et laquelle on ignore
    • dig a une sortie rude, mais ses avantages sont nombreux : beaucoup de fonctionnalités, la prise en charge de +norecurse, sa disponibilité partout et sa stabilité sur la durée

Les rôles qui permettent de rendre les choses plus faciles ensemble

  • Rendre une technologie plus facile ne nécessite pas forcément un blog : cela peut aussi se partager autour de soi
  • Voici les approches résumées par l’autrice
    • partager des outils utiles
    • partager les références réellement utilisées
    • raconter dans l’ordre chronologique ce qui se passe dans l’ordinateur
    • réduire les grandes listes à de petites listes que l’on utilise réellement
    • montrer les comportements cachés
    • faire la démonstration d’outils déroutants en expliquant quelle partie on regarde
  • Il existe aussi plusieurs types de personnes utiles
    • le « vieil utilisateur râleur » raconte ce qui a mal tourné par le passé et aide à éviter des difficultés
    • le « débutant bruyant » pose la question « comment ça marche ? », ce qui soulage aussi les autres
    • lorsqu’un développeur senior pose publiquement une question sur ce qu’il ne sait pas, cela aide aussi ceux qui craignent d’être jugés incompétents
    • le « documentaliste des bugs » note ce qui s’est passé pour qu’un même bug ne revienne pas
    • le « fabricant d’outils » écrit du code pour rendre un problème durablement plus simple, plutôt que de le réexpliquer sans cesse
    • la « personne qui partage ce qu’elle a appris aujourd’hui » diffuse un nouvel outil, un bug rencontré ou une nouvelle fonctionnalité d’une bibliothèque
    • la « personne aux 700 onglets ouverts » sait probablement déjà où chercher l’information
    • il faut aussi des gens qui répondent aux questions et d’autres qui écrivent les réponses pour qu’on puisse les retrouver plus tard
  • Avoir du mal avec des choses qui paraissent fondamentales n’est pas un problème individuel
    • Beaucoup de gens bloquent aux mêmes endroits pour les mêmes raisons
    • Une fois qu’on comprend les causes de la difficulté, on peut mieux y remédier, comme on corrige un bug dans un programme
  • Les causes de la difficulté peuvent être une masse immense de connaissances dispersées et de pièges, 20 millions de lignes de code, des systèmes cachés ou encore une sortie d’outil confuse qui n’a pas été améliorée
  • L’autrice dit qu’elle ne comprend pas encore très bien pourquoi Git est difficile, mais que c’est un sujet sur lequel elle veut continuer à réfléchir

1 commentaires

 
GN⁺ 2023-10-07
Avis de Hacker News
  • Ce qui m’a le plus parlé, c’est l’idée de montrer ce qui est habituellement caché.
    Ce genre d’outils rend la situation plus claire presque immédiatement. Si l’on pense aux outils de développement des navigateurs web, à « l’âge des ténèbres » où ils n’existaient pas, c’était affreux : il fallait deviner ce qui se passait sans pouvoir le voir.
    Un outil comme Wireshark, qui montre les octets des paquets réseau accessibles et en analyse même la structure, est très utile non seulement pour déboguer le réseau, mais aussi pour enseigner les concepts réseau, précisément parce qu’il ne cache rien.
    C’est aussi pour cela que j’aime les logiciels open source. On peut lire le code source pour comprendre l’origine d’un bug, combler les lacunes laissées par la documentation, ou en apprendre davantage sur des concepts de programmation ; rien n’est caché.

    • Dans le développement de jeux, l’outil qui correspond à cela est renderDoc. Quand j’ai découvert son existence, j’ai été vraiment impressionné.
    • Wireshark est excellent, mais il ne montre pas tous les octets transportés par le réseau.
      Par exemple, il ne montre jamais le préambule Ethernet, ne montre qu’occasionnellement la somme de contrôle des trames Ethernet, et ne montre jamais l’intervalle intertrame, qui est pourtant un élément essentiel du protocole Ethernet.
      On s’en approche beaucoup, mais cela montre qu’il y a toujours davantage de détails cachés quelque part.
    • Le rêve, c’est de rendre tout visualisable à l’exécution. Si l’on pouvait faire cela, l’ensemble de l’informatique deviendrait très simple et beaucoup moins complexe, à mon avis.
      On le visualise déjà dans notre tête, et toute explication informatique finit par être représentée sous forme de diagramme. Pourtant, quand on code, il n’y a aucun diagramme.
      Il suffirait d’instrumenter dynamiquement tout le code et d’envoyer des messages à une GUI.
    • Contrairement à l’idée de « montrer ce qui est habituellement caché » et au fait que « ces outils rendent la situation claire presque immédiatement », les outils DevOps d’aujourd’hui semblent au contraire cacher de plus en plus de choses.
      Les experts qui possédaient ces connaissances et pouvaient les enseigner ne sont désormais plus dans les organisations, mais concentrés dans les entreprises qui fabriquent ces outils.
    • C’est exactement ce que j’aime dans Magit pour Emacs. L’UI est vraiment ingénieuse et fluide, peut-être la meilleure interface Git que j’aie utilisée, mais la façon d’interagir avec elle consiste à activer ou désactiver des flags et des options qui correspondent aux arguments réels de la ligne de commande Git en interne.
      Du coup, quand on passe naturellement à la ligne de commande, on peut l’utiliser directement avec familiarité.
  • Julia me semble être l’une des personnes les plus attachantes de l’industrie tech.
    Chaque fois que je lis ses textes, je retrouve l’excitation que je ressentais enfant, quand je commençais à percer les secrets du réel à travers de petites expériences. C’est vraiment adorable.

    • Les personnes qui combinent une connaissance technique profonde et d’excellentes capacités pédagogiques et de communication sont rares. Une autre personne qui me vient à l’esprit est Andrej Karpathy.
      Heureusement, ces derniers temps, je découvre davantage de personnes qui correspondent à ce profil.
    • Pendant un instant, j’ai cru qu’il s’agissait du langage Julia :)
    • Je suis tout à fait d’accord. En général, je n’aime pas trop les billets de blog ou tutoriels excessivement enthousiastes du genre « omg awesomesauce », et je préfère de loin les textes secs, concis, beaux, avec un fort rapport signal/bruit, à la Landau & Lifschitz.
      Mais tous les textes de Julia me font ressentir cette excitation dont il est question plus haut.
    • En personne aussi, elle était vraiment adorable. Je lui ai fait signer mon livre How DNS Works.
  • Je ne pense pas qu’il faille prendre au pied de la lettre la phrase : « quand un junior dit “c’est difficile”, une personne expérimentée répond “oui, bash est inutilisable, personne ne le connaît vraiment” ».
    Le sens est plutôt : « nous n’avons pas une compréhension très solide du code bash que nous avons écrit, ni une grande certitude qu’il se comportera comme prévu dans des situations que nous n’avons pas testées ».
    Cela veut dire qu’on s’attend, dans une certaine mesure, à ce que quelque chose casse dès qu’un cas un peu inhabituel se présente, et qu’un nouveau fait appris sur bash nous fasse frissonner ou taper si fort sur un objet à proximité qu’on se fasse mal.
    Bash est un langage complexe, et il est très différent des autres langages que la plupart des programmeurs utilisent au quotidien. Dans la plupart des entreprises, il y a un peu de bash quelque part en production, mais souvent personne n’en a écrit suffisamment pour vraiment bien le connaître.
    À mon avis, ce n’est pas un hasard si les outils de build, les outils de CI et les outils d’orchestration cloud évoluent dans le sens d’une réduction du besoin de scripting shell.

    • Je pense que la complexité d’outils comme bash vient d’un manque d’évolution.
      Comme expérience de pensée, ne pourrait-on pas ajouter à bash de meilleures instructions d’affectation ? Par exemple, dans un mode du type set --goodass, si l’on pouvait écrire a = string1 + '.' + string2, on pourrait supprimer une bonne partie des problèmes de quoting du shell.
      Des outils comme make en bénéficieraient aussi. Passer six mois à donner à make des variables utilisables, une façon claire de manipuler chemins et noms de fichiers, et des targets plus pratiques, pourrait être préférable à passer six mois à créer des Makefile complexes.
    • Le problème est de savoir si le junior comprendra ce sens implicite, ou s’il le prendra plus littéralement que prévu.
      En particulier, l’idée que « pour la plupart des programmeurs, bash ne ressemble à aucun langage qu’ils utilisent habituellement » n’est pas quelque chose qu’un débutant peut nécessairement déduire. Il faut assez d’expérience pour distinguer « peu courant » de « extrêmement obscur ».
  • À ce sujet, la plupart des logiciels sont surconçus.
    Je pense que c’est aussi dû à la centralisation de l’industrie. On pousse tout le monde vers un petit nombre d’outils, au bénéfice d’un petit nombre de personnes qui les contrôlent, et beaucoup de ces outils deviennent ainsi des « outils pour tout », couvrant bien plus de cas d’usage que nécessaire.
    Les entreprises veulent que tous les développeurs connaissent les mêmes outils. Ainsi, ils sont facilement interchangeables entre projets et entreprises, ce qui affaiblit leur pouvoir de négociation dans l’industrie.
    Résultat : il ne reste qu’une seule branche dominante dans le logiciel, tandis que les approches alternatives sont exclues, sans débouchés. L’industrie voudrait naturellement se décentraliser, mais elle n’y parvient pas.
    Pour voir le bon côté des choses, des approches non dominantes bien supérieures apparaîtront un jour et grignoteront l’approche dominante. La technologie n’est pas des mathématiques, et elle n’est pas non plus comme la science ; elle peut parfaitement soutenir de nombreuses branches résolvant le même problème de différentes manières.

    • Je suis d’accord. À certains égards, j’ai même l’impression que le développement web a régressé depuis les débuts d’ASP.NET ou l’époque de Rails.
      À l’époque, les guerres de navigateurs nous occupaient beaucoup, mais aujourd’hui, alors que les navigateurs sont globalement compatibles, nous avons créé une énorme complexité frontend pour des applications web qui, la plupart du temps, n’en ont pas besoin.
      Pour des éléments comme DNS, IP ou HTTPS, on ne peut pas vraiment y échapper, car ce sont des technologies fondamentales mêlant compatibilité ascendante et enjeux politiques.
      Malgré tout, j’ai le sentiment qu’apprendre correctement ces choses est un meilleur investissement qu’apprendre des frameworks. Si j’en dis plus, je vais finir par parler de jetons d’innovation.
  • Pour rendre les choses difficiles faciles, il faut trouver la bonne abstraction. Il s’agit de garder en tête une partie du sujet difficile et les détails qu’on utilise souvent, puis d’aller chercher le reste quand c’est nécessaire
    Le problème, c’est que les gens ne prennent pas la peine de créer une compression cognitive d’un grand sujet tant qu’ils n’en ont pas vraiment besoin. Comme ils portent déjà une autre grosse charge cognitive, ils résistent à l’idée d’en ajouter une nouvelle
    Si l’on peut s’appuyer sur quelqu’un d’autre qui connaît bien un sujet X, on peut simplement le faire, et éviter de faire l’effort d’en savoir assez sur X. La meilleure façon, pour quelqu’un qui connaît bien X, de réduire les demandes d’aide est d’aider les autres à en comprendre le minimum
    set -e est cassé, la nécessité de mettre tout entre guillemets est cassée elle aussi, et le globbing devrait être une fonctionnalité à demander explicitement. En ligne de commande ce serait pénible, mais dans les scripts c’est une autre histoire ; aujourd’hui, si l’on désactive globalement le globbing, il devient difficile de l’utiliser aux endroits où on le veut
    Ces mauvais réglages par défaut ne concernent pas seulement Bash, mais l’ensemble des shells de la lignée Ksh et Bourne shell
    Beaucoup de gens aimeraient aussi changer l’ordre des clauses en SQL. Il n’y a pas de raison que ce soit impossible, et cela semble être une modification relativement petite des parseurs SQL existants pour autoriser des clauses dans un autre ordre
    Personnellement, je n’ai toutefois pas ce problème cognitif, probablement parce que je sais qu’il faut d’abord regarder la source des tables

    • Les trois pièges — set -e cassé, l’obligation de mettre tout entre guillemets et le fait que le globbing devrait être explicite — sont corrigés par OSH, tout en exécutant les scripts shell existants
      Ajoutez shopt --set ysh:upgrade en haut du script, et ces trois problèmes disparaissent
      Si vous voulez aider le projet, ce serait bien de télécharger le tarball, de vérifier ces affirmations et d’écrire un billet de blog
      Les détails se trouvent dans https://www.oilshell.org/release/latest/doc/error-handling.h... et https://www.oilshell.org/release/latest/doc/simple-word-eval...
      La documentation est complète, mais la plupart des gens ne veulent pas ce niveau de détail ; il serait donc utile que quelqu’un teste et en fasse un court résumé
      Si je n’ai pas activement poussé Oils pendant un temps, c’est parce qu’il avait une dépendance à Python ; désormais, il est en C++ pur et, depuis cette semaine, il bat bash sur certains benchmarks centrés sur le calcul
      Les scripts centrés sur les entrées-sorties ont toujours eu la même vitesse, comme c’est le cas pour la plupart des scripts shell. Il peut y avoir un peu de confusion pendant un moment, car la documentation doit encore remplacer Oil par YSH : https://www.oilshell.org/blog/2023/03/rename.html
    • Le problème, c’est qu’on continue à utiliser ces anciens shells alors qu’il en existe de meilleurs. Les utilisateurs ne devraient pas perdre du temps à mémoriser des savoirs ésotériques comme set -e. Cela dit, on a désormais les moteurs de recherche
    • Une façon assez radicale de corriger l’ordre des clauses SQL pourrait être d’introduire project, qui se comporterait comme select mais pourrait être placé au bon endroit
    • Quand une explication contient des détails inutiles, cela devient très confus. Comme le fusil de Tchekhov, on essaie sans cesse de les faire entrer dans l’intrigue, mais ça ne colle pas
      Mon super-pouvoir, c’est une mémoire épouvantable. Donc, pour mémoriser quelque chose, je dois absolument le comprendre, c’est-à-dire que j’ai besoin d’une compression cognitive. Je ne peux pas simplement apprendre comme une personne normale
    • Il faudrait pouvoir enlever la couche SQL et accéder à la couche inférieure
  • Aujourd’hui, j’ai appris : dans une liste && ou ||, à l’exception de la commande située après le dernier && ou ||, le shell ne se termine pas même si l’une des commandes exécutées échoue
    Référence : https://www.gnu.org/software/bash/manual/bash.html#index-set

    • L’« échec » est un concept de plus haut niveau que ce dont le shell se préoccupe. Les conditions d’échec et les réactions relèvent entièrement du choix du programmeur, et ne sont pas intégrées comme hypothèses dans le shell
      Tout ce que fait /bin/false, c’est retourner 1. Est-ce un échec ? Non. Il a été conçu pour se comporter ainsi, et c’est littéralement l’objectif de cet outil
      J’ai écrit des centaines de scripts shell, et beaucoup de commandes y retournent tout à fait normalement une valeur non nulle pour faire leur travail, par exemple vérifier qu’une chaîne correspond à un certain motif
      Un programme peut retourner le code de sortie qu’il veut dans n’importe quelle situation ; par convention, le succès est 0 et l’échec une valeur non nulle. Mais la seule chose qui intéresse le langage shell, c’est que 0 est évalué comme « vrai » et une valeur non nulle comme « faux »
      Si le shell se terminait chaque fois qu’un programme retourne une valeur non nulle, les instructions if et les boucles deviendraient impossibles, ce qui serait très gênant
      Si un script attache de l’importance au code de retour d’un programme donné, il doit le vérifier et le traiter explicitement. Comme dans le lien, il existe des options qui font quitter le shell lorsqu’une commande interne retourne une valeur non nulle, et beaucoup d’auteurs de scripts shell débutants ou intermédiaires affirment de façon dogmatique qu’il faut les utiliser dans tous les scripts
      Mais dans les scripts complexes, j’ai l’impression qu’il y a beaucoup de cas limites un peu hacky et difficiles à gérer. Si vous avez besoin de ce genre d’options à chaque fois, autant utiliser un Makefile
    • C’est parce que && et || sont souvent utilisés comme des conditionnelles
      [ -e README ] && cat README évite une erreur quand le fichier README n’existe pas, et [ -e README ] || echo "You should write a README!" fait l’inverse
      Le problème plus subtil, c’est que même en supposant set -e, dans un pipeline le shell ne se termine pas si la dernière commande n’échoue pas
      grep foo README | sort n’échoue pas si README n’existe pas, sauf si vous utilisez aussi set -o pipefail
    • Je considère cela comme l’un des plus gros défauts de conception du langage shell. Une fonction peut produire des résultats différents selon le contexte dans lequel elle est appelée, indépendamment de ses arguments
      Même si vous définissez explicitement set -e à l’intérieur de la fonction, cela est écrasé
      J’en avais déjà donné un exemple : https://news.ycombinator.com/item?id=22213830
    • Le shell contient beaucoup de savoir ésotérique à apprendre. À un moment, il faut hausser les épaules et accepter que c’est un outil correct pour obtenir des résultats rapides, mais pas adapté à l’écriture de programmes robustes
  • C’est un article qui décrit bien des choses qui semblent ne pas devoir être difficiles, mais qui recèlent en réalité beaucoup de complexité
    Cela dit, la partie sur SQL semble pousser plus loin un échec conceptuel plutôt que de dissiper le mystère
    La logique d’une requête est déclarative et définit la sortie. Ce qui a un ordre d’exécution ou un caractère procédural, c’est le plan de requête. C’est cela qu’il faut apprendre en premier
    Ensuite, on peut apprendre les zones plus ambiguës, comme les sous-requêtes corrélées. Si l’on peut voir que not exists et un anti-join sont équivalents, on peut les comprendre et raisonner dessus
    Les analogies qui consistent à comprendre une requête écrite de manière procédurale ne font que repousser le problème, et lorsqu’on se retrouve bloqué sur quelque chose de plus complexe, on n’a plus de moyen de défaire ce mensonge bien intentionné

    • La partie sur SQL parlait d’un modèle mental utile pour comprendre les requêtes, et mentionnait aussi que les bases de données réelles ne les traitent probablement pas de cette façon
    • Épisode récent lié à Postgres, mais que l’on peut souvent étendre par analogie à d’autres bases de données : https://www.se-radio.net/2023/09/se-radio-583-lukas-fittl-on...
  • C’était une excellente présentation. Il est vrai que Bash est rempli de « pièges » et de connaissances anecdotiques difficiles à mémoriser entièrement, mais je pense qu’il vaut aussi la peine d’en mémoriser une partie
    Par exemple, j’oubliais souvent l’ordre des arguments de la commande find, et il m’arrivait de perdre du temps à me rappeler la syntaxe devant une machine sans connexion Internet immédiate
    J’ai donc décidé d’apprendre et de mémoriser les outils de ligne de commande les plus courants et certains de leurs pièges, en utilisant Anki et quelques moyens mnémotechniques. Le retour sur investissement en valait largement la peine, à mon avis

    • Anki est ma bouée de sauvetage pour comprendre des sujets difficiles comme le DNS
      En fait, après avoir vu une recommandation de livre sur jvns.ca, j’ai lu Networking for System Administrators de Michael W. Lucas, et j’en ai extrait des cartes Anki mêlant connaissances techniques et une bonne dose de sagesse d’administrateur système
      Aujourd’hui, quand je débogue des problèmes de couche transport, je me souviens immédiatement comment utiliser des outils comme netcat et tcpdump ; c’est donc peut-être l’un des livres que j’ai lus avec le meilleur retour sur investissement
    • Je maintiens un fichier qui rassemble les commandes que je n’utilise pas souvent. Par exemple des commandes pour augmenter le volume avec ffmpeg, ou ajouter une bordure à une image avec convert
      J’ai aussi créé un raccourci pour ajouter à ce fichier la dernière commande exécutée, et un autre pour y effectuer une recherche
    • Les pages man sont immédiatement disponibles
      La page man de bash est énorme et complexe, mais exhaustive. Si l’on connaît les grandes sections et l’aspect visuel du texte, on peut la parcourir rapidement et trouver l’information exacte dont on a besoin, ce qui s’est révélé très utile
      Cette méthode est souvent plus rapide que d’utiliser un moteur de recherche sur Internet
    • Pour ne pas dépendre d’Internet tout en évitant de mémoriser une mauvaise conception, il peut être préférable d’investir dans une documentation ou des antisèches plus générales
      Par exemple en convertissant les vieilles pages man dans un format plus convivial pour les éditeurs de texte, ou en utilisant de meilleurs outils comme tldr ou Dash. Parce que find n’est pas le seul cas concerné
    • Il faut arrêter d’utiliser Bash et employer TypeScript à la place. Bash est horrible
  • Je ne sais pas pourquoi, mais j’avais envie de ne pas aimer cet article. Peut-être parce que jvns apparaissait trop souvent sur HN, ou parce que j’étais de mauvaise humeur.
    Mais c’est vraiment un excellent texte et, en tant que personne avec 20 ans d’expérience en développement, je trouve qu’il est assez proche de la vérité parmi les discussions de méta-niveau sur la programmation.
    L’idée de vision sélective s’applique vraiment aussi bien à dig qu’aux pages man. Je ne compte plus les fois où j’ai ouvert man et où j’ai été submergé par une infinité d’options de configuration et de flags en ligne de commande.
    L’astuce que j’utilise dans man, c’est la recherche façon Vim avec /. Par exemple, si je veux retrouver comment faire afficher par grep le numéro de ligne de chaque correspondance et que je ne m’en souviens plus, j’ouvre man grep, puis je tape /line et j’appuie sur Entrée pour rechercher les occurrences de « line » dans la page man. La correspondance suivante, c’est simplement /.
    Je suis aussi un peu triste d’apprendre que Strange Loop est terminé. Je ne l’ai découvert que l’an dernier environ, et beaucoup de conférences m’ont semblé d’une qualité exceptionnelle.

  • Je ne suis pas du tout d’accord avec le point de vue sur bash. La meilleure solution n’est pas d’ajouter des outils par-dessus bash ni d’en mémoriser les bizarreries, mais de ne pas utiliser bash.
    C’est le seul moyen d’éviter les pièges.

    • Je n’ai pas encore trouvé de vrai remplaçant à bash, surtout pour les scripts.
      Les alternatives les plus courantes sont 1) utiliser un nouveau shell comme Oil shell [0], ou 2) utiliser un langage de programmation comme Python, JavaScript ou PHP.
      Le problème des nouveaux shells, c’est qu’il faut installer ce shell partout où l’on veut exécuter les scripts. À l’inverse, bash est partout. Et si ce n’est pas un script que vous maintenez seul, vous demandez aussi aux autres d’apprendre ce shell pour pouvoir le maintenir.
      Le problème des autres langages de programmation, c’est que bash offre rarement une aussi bonne ergonomie pour ce qu’il fait bien : chaîner des commandes, gérer les entrées/sorties des commandes et manipuler des fichiers.
      Dès qu’on essaie de faire ça dans un autre langage, cela devient soudain beaucoup plus complexe, ou au moins plus verbeux.
      Donc j’utilise encore bash, tout en reconnaissant que sa force est d’exécuter d’autres commandes et de gérer les entrées/sorties. Pour une logique complexe qui n’a pas de rapport avec ça, je la délègue à un autre langage. Parfois, il ne s’agit pas d’éviter complètement bash, mais simplement d’appeler un script Python depuis bash.
      Si une autre approche a mieux fonctionné pour vous, ce serait bien de la partager.
      [0] https://www.oilshell.org
    • C’est un point valable. bash est un outil excessivement complexe, et c’est étrange d’écrire encore un autre outil par-dessus pour rendre bash moins complexe.
      D’autant que ce nouvel outil n’aura pas bénéficié des décennies de débogage qu’a connues bash lui-même. Le problème, c’est bash lui-même.
      Nous avons tendance à sous-estimer la facilité d’utilisation et à surestimer « l’intelligence ».
      L’exemple emblématique, c’est Git. C’est un outil très ingénieux, mais son ergonomie est épouvantable. Pourtant, comme il a été créé par Linus et que Linus est brillant, on a l’impression que le problème vient de nous.
      Nous obtenons ce que nous valorisons. Nous devrions accorder plus de valeur à la facilité d’utilisation.
    • Je suis un fervent adepte de shellcheck et j’ai vraiment utilisé bash en profondeur, mais aucun linter ni aucun outil au-dessus de bash ne peut corriger ça.
      La meilleure solution est simplement de s’en tenir éloigné. Vraiment, il faut arrêter. Il ne faut pas jouer les machos.
      Tout le modèle du langage est fondamentalement cassé : types centrés sur les chaînes, commutateurs de mode globaux, flags d’un seul caractère pour les opérateurs de comparaison de base, erreurs ignorées par défaut un peu partout, et surtout les fonctions.
      Une seule de ces bizarreries suffirait à écarter un langage ; bash les a toutes, et plus encore.
    • Si bash est bizarre, c’est parce que ce n’est pas un langage généraliste. Les points mentionnés dans l’article ont aussi leurs raisons d’être. Par exemple, le fait que set -x puisse casser le comportement attendu de || et &&.
      Quel langage entre en conflit simplement parce qu’une fonction renvoie false ? Il y a des langages qui lèvent des exceptions, mais « false » n’est-il pas une valeur de retour valide ?
      On observe la même chose avec les Makefile. Les gens ne comprennent pas ce qu’ils font, n’ont jamais vraiment réfléchi aux systèmes de build, et s’attendent à ce qu’ils se comportent d’une certaine manière.
      Par exemple, l’affectation récursive de Make fait trébucher presque tout le monde.
      FLAGS=-b, COMPILE=compile $(FLAGS), $(info compile command=$(COMPILE)), FLAGS=-a, myfile:, echo $(COMPILE) $? -o $@ affiche compile -b lors de la première sortie d’information, mais l’exécution réelle devient compile -a -o myfile.
      Pour autant, si l’on rendait toutes les affectations évaluées immédiatement afin de les aligner sur les autres langages de programmation, on se priverait d’un outil très utile. Plus on comprend ces outils, mieux on sait où les utiliser et combien d’efforts y consacrer.
    • Ce n’est pas aussi simple que ça en a l’air, et supprimer complètement bash ne vaut pas toujours le temps et les efforts nécessaires.
      Je suis tout de même globalement d’accord. J’essaie de déléguer tout ce qui est un peu complexe à des scripts écrits dans un langage moins bizarre.
      Dans ce cas, les outils qui aident à éviter les erreurs dans les 5 % restants qui demeurent en bash sont très utiles.