Catégorie : Technique

  • Les meilleurs commen­taires ne s’écrivent pas

    Les meilleurs commen­taires sont ceux que l’on n’a pas besoin d’écrire.

    Lorsque l’on a besoin d’écrire un commen­taire, le plus souvent, c’est que notre code n’est pas aussi clair et propre qu’il devrait l’être.

    Je suis bien d’ac­cord avec la cita­tion du dessus, mais elle n’im­plique aucu­ne­ment ce qui suit.

    Damned, un déve­lop­peur faisant une telle faute logique ? On devrait savoir que les rela­tions de cause et consé­quence ne s’in­versent pas. Si les meilleurs commen­taires sont ceux qu’on n’a pas besoin d’écrire, personne n’a dit qu’on ne devrait pas écrire les commen­taires !

    function main() {  
      let imageName = 'test.png'
    
      // Get the extension off the image filename  
      let pieces = imageName.split('.')
      let extension = pieces.pop()
    }
    

    […] ça ressemble beau­coup trop à une excuse : « Mon code est moche / compliqué mais c’est pas grave je vais l’ex­pliquer dans un commen­taire » au lieu de le nettoyer.

    Donc oui, ce commen­taire est à peu près inutile. S’il le devient c’est que le code est proba­ble­ment inuti­le­ment complexe et pour­rait être amélio­rer avec l’uti­li­sa­tion de fonc­tions tierces bien nommées.

    Si effec­ti­ve­ment vous commen­tez ainsi (pas de honte, ça arrive à tous), ça ne sert à rien.

    Par contre, un commen­taire qui dit pourquoi vous avez besoin de l’ex­ten­sion ça ne serait pas forcé­ment du luxe. Peut-être que ce commen­taire manquant me permet­trait de savoir si le compor­te­ment face à un fichier « .test.png » est une anoma­lie ou est volon­taire. Là je suis bien à mal de savoir sans lire tout le code source en détail pour cher­cher l’in­ten­tion du déve­lop­peur.

    Bref, si vous croyez qu’un code source clair remplace les commen­taires, c’est que vous n’avez pas encore compris ce qu’il faut écrire dans les commen­taires.

    /**
     * Get the extension of the file
     * 
     * @param {string} filename - The filename
     * @return {string} the extension of the file  
     */
    function getFileExtension(filename) {  
      let pieces = imageName.split('.')
      return pieces.pop()
    }

    Dites moi qu’il y a une infor­ma­tion dans ce commen­taire que vous n’aviez pas en lisant le code !

    Non. Par contre dans un IDE évolué, ce type de code me permet d’avoir confir­ma­tion du rôle de la fonc­tion quand je la tape ou quand je la lis plutôt que de devoir m’in­ter­rompre pour aller ouvrir le fichier corres­pon­dant et lire tout le code source. D’au­tant que là ce sont deux lignes mais parfois, même si c’est clair, c’est quand même plus long à lire.

    C’est aussi avec les commen­taires de @ que l’IDE me donnera le rôle des diffé­rents para­mètres. Oui, le plus souvent ils devraient être évident mais est-ce toujours le cas ? Grâce à ce jsdoc je saurais sans ouvrir la fonc­tion que je dois y rensei­gner un nom de fichier et pas un chemin complet. Bien m’en a pris parce que « ./test.png » aurait provoqué de jolies erreurs à l’exé­cu­tion de mon programme. Je saurai aussi si j’ai ou pas un argu­ment option­nel et pourquoi.

    Toujours avec un outillage évolué, la mention du string permet­tra d’iden­ti­fier des erreurs de typage malen­con­treuses. Ça pour­rait être dans le proto­type de la fonc­tion avec flow ou ici dans le commen­taire, peu importe, seule la syntaxe diffère.

    Main­te­nant même ici, le problème n’est pas avec le commen­taire mais avec ce qu’il dit. Ça n’au­rait pas été du luxe que la fonc­tion décrive que ce qu’elle consi­dère être une exten­sion dans le cas d’un « test.tar.gz ».

    Là où le code est propre le commen­taires ne sera qu’une redon­dance sans grand inté­rêt que le cerveau appren­dra vite à igno­rer.

    Et si c’était le contenu des commen­taires qu’il fallait remettre en cause et pas leur présence ?

    Sinon oui, je règle mes outils pour que les commen­taires s’af­fichent en gris clair. Pas qu’ils soient sans inté­rêt mais parce que j’ai deux niveaux de lecture suivant que je travaille le corps de la fonc­tion (et là je veux igno­rer les commen­taires) ou que je l’étu­die la première fois.

    Le seul problème que je rencontre aujourd’­hui se produit dans le cadre de project avec une docu­men­ta­tion publique auto-géné­rée. Comment éviter la redon­dance tout en faisant en sorte que la docu­men­ta­tion géné­rée à partir de mes commen­taires soit complète.

    Si la docu­men­ta­tion géné­rée pour les déve­lop­peurs a besoin des commen­taires, c’est que peut-être l’as­ser­tion comme quoi le code est aussi simple et effi­cace à lire que les commen­tai­res… est peut-être fausse. Je dis ça je dis rien.

  • [Lecture] The Real Name Fallacy

    Not only would remo­ving anony­mity fail to consis­tently improve online commu­nity beha­vior – forcing real names in online commu­ni­ties could also increase discri­mi­na­tion and worsen harass­ment.

    The Coral Project (Mozilla)

  • Attri­buer une cita­tion en HTML

    On parle de HTML 5, le web n’est qu’une multi­tude de liens, et on ne sait toujours pas attri­buer une cita­tion. Comment est-ce que je source le Au-revoir de Valéry Giscard d’Es­taing ?

    <blockquote>Au revoir.</blockquote>

    Il y a bien un attri­but cite dans <blockquote>. Je peux y mettre un lien mais ce lien ne sera ni affi­ché ni action­nable dans les navi­ga­teurs.

    Je peux aussi mettre un texte dans un attri­but data-source et l’af­fi­cher avec le lien via quelques geeke­ries CSS. C’est un peu mieux mais le lien n’est ni cliquable ni sélec­tion­nable pour un copier-coller : Plus frus­trant du meurs.

    Je ne parle même pas d’al­ler indiquer la date dans la cita­tion avec la balise <time>, là on entre­rait dans la science fiction.

    <style>
    blockquote::after { content: "-- " attr(data-source) ", " attr(cite);
    </style>

    La solu­tion du pauvre – celle que j’uti­lise sur ce blog – c’est de mettre la source direc­te­ment dans le <blockquote>. Il s’agit toute­fois d’un détour­ne­ment du sens des balises, parce que l’at­tri­bu­tion ne fait pas partie du bloc cité.

    D’autres proposent de mettre ça dans un <footer> du <blockquote>, éven­tuel­le­ment avec un <cite>. C’est un peu mieux – le <footer> est offi­ciel­le­ment fait pour être de la méta­don­née à propos du bloc parent – mais ça reste bancal : Le code ne permet pas de sépa­rer ce qu’on cite de l’at­tri­bu­tion elle-même.

    <blockquote>
      Au revoir.
      <footer>
        -- Valéry Giscard d'Estaing, 
        <cite>
          <a href="http://www.ina.fr/video/I08358793">
            dans son discours du 
            <time datetime="1981-05-19">le 19 mai 1981</time> 
            avant la passation de pouvoir à François Mitterrand
          </a>
        </cite>
      </footer>
    </blockquote>

    La balise <figure> peut venir à notre rescousse. On englobe le <blockquote> dans la <figure> et on ajoute un <figcaption> pour l’at­tri­bu­tion, avec éven­tuel­le­ment un <cite> correc­te­ment placé.

    <figure>
      <blockquote>Au revoir.</blockquote>
      <figcaption>
        -- Valéry Giscard d'Estaing, 
        <cite>
          <a href="http://www.ina.fr/video/I08358793">
            dans son discours du 
            <time datetime="1981-05-19">le 19 mai 1981</time> 
            avant la passation de pouvoir à François Mitterrand
          </a>
        </cite>
      </figcaption>
    </figure>

    Quelque part j’ai encore mal parce qu’un robot ne reliera pas l’at­tri­bu­tion et la cita­tion.

    Reste aussi que la défi­ni­tion de <figure> indique que l’em­pla­ce­ment de son contenu dans le texte envi­ron­nant n’a pas d’im­por­tance, ce qui ne me parait pas forcé­ment vrai pour une cita­tion.

    On sait expri­mer tout ça à desti­na­tion des moteurs de recherche en rdfa, en micro data ou en json-ld, le tout avec un voca­bu­laire normé, mais on n’a toujours rien pour les données visibles de l’uti­li­sa­teur. Que la spéci­fi­ca­tion HTML 5 ait été diri­gée par un éditeur de Google ne peut être qu’une coïn­ci­dence.

  • Je cherche des équipes construi­sant une progres­sive web app

    Idéa­le­ment en France ou avec un télé­tra­vailleur en France, mais n’hé­si­tez pas à en propo­ser des étran­gères qui font des choses bien

    Idéa­le­ment une équipe chez un éditeur produit et pas des pres­ta­taires de service, mais ça peut aussi être une équipe de presta dédiée et consti­tuée qui en fait sa spécia­lité (donc pas juste une SSII qui a travaillé sur un projet)

    Idéa­le­ment une équipe, mais si vous n’avez que de très bon exemples de sites, je suis preneur aussi

    Vous avez des noms ?

  • Un nouveau langage

    De temps en temps j’aime bien explo­rer quelque chose de nouveau côté program­ma­tion.

    J’ai tenté de faire une petite remise à zéro en Javas­cript il y a peu. J’y trouve plein de points posi­tifs objec­tifs mais je ne vois pas la moti­va­tion pour mes projets perso. Je n’ai pas d’atomes crochus avec la syntaxe, le langage lui-même ne m’ap­porte pas suffi­sam­ment de nouveau pour que la décou­verte me motive, et il y a plein de trucs qui me fatiguent dans l’en­vi­ron­ne­ment.

    J’ai vu Elm et j’aime bien plusieurs idées mais je cherche quelque chose qui tourne aussi en ligne de commande.

    J’ai tenté Crys­tal. Le langage est sympa : inspiré de ruby, infé­rence de types, compilé et perfor­mant, liai­sons simples avec toutes les libs en C. J’ai quelques reproches (genre l’ab­sence d’un type « Nume­ric » qui m’abs­trait des types bas niveau) mais je me suis surtout dit « à quoi bon » quand j’ai eu une excep­tion à l’exé­cu­tion lors de ma première jour­née. À quoi bon s’im­po­ser un typage statique si c’est pour que les problèmes les plus courants soient encore gérés à l’exé­cu­tion sans même un aver­tis­se­ment à la compi­la­tion ?

    Dans l’idéal j’ai­me­rais tester un envi­ron­ne­ment où quasi­ment tout est détecté en statique et qui ne soit pas aussi verbeux qu’un Java ou aussi bas niveau qu’un C. Vous avez quelque chose à me conseiller ?

  • Dis tonton, c’est quoi un déve­lop­peur ?

    C’est quelqu’un qui rédige les spéci­fi­ca­tions détaillées en langage machine d’une solu­tion à un problème. (*)

    * * *

    Coro­laires :

    • Prétendre faire coder un déve­lop­peur sans lui permettre de comprendre ce qu’il fait n’a aucun sens
    • Un cycle de travail ou un chef de projet prétend conce­voir les spéci­fi­ca­tions détaillées en amont du déve­lop­peur est au mieux drama­tique­ment inef­fi­cace
    • Quand on étudie tous les détails de tous les cas, on rencontre de nouveaux problèmes et de nouvelles solu­tions, ne pas s’au­to­ri­ser à chan­ger les déci­sions pendant la phase de déve­lop­pe­ment c’est être perdant à tous les coups

    (*) Merci à celui qui m’a distillé cette défi­ni­tion, je ne sais plus d’où elle vient mais elle rempla­cera agréa­ble­ment ma précé­dente.

  • Encore un projet perso

    Oui, comme si je n’en avais pas assez…

    Il reste que j’ai envie de présen­ter ce que je fais en photo autre­ment que par Flickr. La cible n’est pas précise. Comme les photos elles-mêmes, je le fais d’abord pour moi. Peut-être est-ce simple­ment donner corps à quelque chose qui commence à prendre de l’im­por­tance.

    Bref, je pose là pour moi-même – et un peu pour les curieux – ce que j’ai en tête.

    Un menu prin­ci­pal à trois entrées : des textes, des photos et des albums. J’ai commencé à écrire un peu autour des photos quand je les publie ici, et c’est fina­le­ment inté­res­sant de m’obli­ger à cette intros­pec­tion. Les deux autres permettent de sépa­rer le flux de photo chro­no­lo­gique en vrac de la sépa­ra­tion par albums bien pensée.

    J’ai tenté un premier jet de la page d’ac­cueil. On y met deux textes et deux albums en avant, à chaque fois un récent et un plus coup de cœur. Plus bas vient un mur d’images, avec les plus récentes et celles que j’aime le mieux (comme je suis un geek fini, j’ai déjà en tête une simili formule pour savoir ce que j’af­fiche en fonc­tion de la date de publi­ca­tion et de mes favo­ris).

    Travail en cours, le code CSS est certai­ne­ment bien moche.

  • Rempla­cer du texte par une image en CSS

    Dans les années 2007 à 2009 on avait une collec­tion d’hor­ribles bidouilles CSS pour insé­rer des images à la place de certains textes via CSS. L’idée c’est que certaines images ne sont pas du contenu mais bien de la présen­ta­tion, poten­tiel­le­ment dépen­dantes du contexte.

    Le besoin était tel que c’était un des sujets les plus en vue en CSS pendant des années avec « comment centrer un contenu verti­ca­le­ment ».

    h3.nir {
       height: 75px;
       width: 300px;
       overflow: hidden;
       margin: 0;
       padding: 0;
     }
     h3.nir:before {
       content: url(http://…/test.png);
       display: inline-block;
       font-size: 0;
       line-height: 0;
     }

    Fran­che­ment c’était de la bidouille de haut vol, avec plein de défauts. On rêvait d’un truc plus simple, qui fonc­tionne correc­te­ment quand l’image ne se charge pas et sur les lecteurs d’écran, sans flash de contenu non stylé. Je me demande même ce qui suit n’a fonc­tionné sur certains navi­ga­teurs, mais on n’y est visi­ble­ment pas encore :

    h3 { content: url(http://…/test.png); }

    CSS a beau­coup évolué, les navi­ga­teurs aussi. J’es­pé­rais qu’on avait enfin résolu ce problème ultra bateau. Visi­ble­ment non. La seule solu­tion passe par des polices de carac­tères d’icônes et des recon­nais­sances de liga­ture. Le reste n’a que peu changé en 10 ans, on a juste enlevé les besoins de compa­ti­bi­lité sur les vieux navi­ga­teurs.

    J’avoue que je ne comprends pas. On ajoute des fonc­tion­na­li­tés de folie et on ne gère toujours pas la base qui a généré des milliers de pages en bidouilles de contour­ne­ment. Qu’on m’ex­plique…

  • Variables et constantes — Javas­cript 103

    Travailler avec ES2015 c’est quelques chan­ge­ments sur les décla­ra­tions des variables.

    Premier chan­ge­ment : Les modules ES2015 sont impli­ci­te­ment en mode strict. Y utili­ser une variable non décla­rée provoque une erreur. Ce seul chan­ge­ment est une béné­dic­tion vu l’ubuesque compor­te­ment par défaut de Javas­cript. Il reste que ça ne chan­gera pas grand chose pour qui utili­sait déjà un outil d’ana­lyse de code (linter).

    Pour décla­rer les variables nous avons aussi le nouveau mot clef let en complé­ment de l’an­cien var.  La portée est alors limi­tée au bloc de code parent le plus proche (if, while, func­tion, for…) au lieu d’être éten­due à toute la fonc­tion parente.

    let a = 2;
    for(let b=1; b<3; b++) {
      let a = 3;
      a = 4;
    }
    console.log(a); // 2 et non 4

    Au début j’étais enthou­siasmé. J’ai trouvé excep­tion­nel de pouvoir travailler avec des variables jetables le temps de quelques lignes et j’ai pensé éviter de nombreuses réuti­li­sa­tions par erreur.

    À l’usage c’est un ajout sympa mais pas si révo­lu­tion­naire. Si c’est pratique c’est surtout pour gérer les ferme­tures syntaxiques (closure) au sein des boucles. Le reste du temps ça n’a que peu d’in­fluence quand on a des fonc­tions de taille et de niveau d’im­bri­ca­tion raison­nables.

    var fns = [ ];
    for(var i=1; i<3; i++) {
      fns.push( function () { console.log(i); } );
    }
    var fn = fns[0];
    fn(); // affichera 3 et non 1
    
    //----
    
    fns = [ ];
    for(let j=1; j<3; j++) {
      fns.push( function () { console.log(j); } );
    }
    fn = fns[0];
    fn(); // affichera 1

    Je me demande si ça pour­rait être la portée par défaut dans un langage. Visi­ble­ment certains pensent que non mais je n’ai pas été convaincu par l’ar­gu­men­taire.

    L’autre nouvel arrivé c’est const. Décla­rée ainsi la variable a la même portée qu’un let mais on ne peut pas y affec­ter une valeur diffé­rente.

    Là aussi c’est pas mal d’en­thou­siasme. Une variable qui est modi­fiée sans aver­tis­se­ment par une ferme­ture lexi­cale ou un module tiers, ça fait parfois des dégâts.

    Le problème c’est que ça ne protège pas vrai­ment de ça. Si on ne peut pas affec­ter de nouvelle valeur au même nom de variable, la valeur elle même n’est pas immuable. On peut toujours faire chan­ger d’état un objet ou modi­fier les éléments d’un tableau. Domma­ge…

    const tab = [ ];
    tab[3] = 4; // ne provoque pas d'erreur mais change `tab`
    
    const obj = { 
      var priv = 2; 
      this.chg = function() { priv = 3; };
    };
    obj.chg(); // `obj` vient de changer d'état silencieusement
    
    tab = [1, 2, 3]; // là par contre on génère une erreur.

    Pour obte­nir une vraie sûreté il faut utili­ser des des struc­tures de données expli­ci­te­ment prévues pour. On ne peut plus utili­ser les raccour­cis habi­tuels { } ou [ ] et l’ins­tan­cia­tion devient bien plus verbeuse. Facile d’ou­blier par inat­ten­tion et par habi­tude.

    import immutable from "immutable";
    const map = Immutable.Map({a:1, b:2, c:3});
    // map ne changera plus jamais de valeur

    Le problème c’est que tous les modules tiers conti­nuent à utili­ser les struc­tures de données variables habi­tuelles. Malheu­reu­se­ment des modules tiers, vue la pauvreté de la biblio­thèque stan­dard de Nodejs, on en utilise des tonnes,  y compris pour des fonc­tions de base.

    Pour se proté­ger vrai­ment des chan­ge­ments d’état il faudra non seule­ment utili­ser expli­ci­te­ment nos struc­tures de données immuables (aie), mais en plus faire régu­liè­re­ment des conver­sions quand on commu­nique avec des modules tiers (ouch).

    Il y a tout lieu de penser qu’on finira par avoir des données variables et d’autres immuables, suivant d’où elles viennent et comment elles sont décla­rées. Il faudra réflé­chir à chaque utili­sa­tion, parfois remon­ter à la créa­tion de la donnée. Possible même que le compor­te­ment de const avec les struc­tures de données natives nous incite plus d’une fois à nous croire en sécu­rité alors que ce ne sera pas le cas.

    Pour moi c’est le scéna­rio du pire. Non seule­ment on complexi­fie le code (plus verbeux) et la charge cogni­tive (savoir à chaque fois quel est le type de variable et le type de données), mais en plus on garde des risques.

    Pour jouer à ça il aurait fallu que le langage s’as­sure que ce qu’on déclare comme tel soit réel­le­ment immuable, jusqu’en profon­deur. Je comprends très bien pourquoi ça aurait été diffi­cile voire impos­sible, mais du coup ce const m’a l’air d’une vraie fausse bonne idée. Domma­ge…

    Pour autant je me prends quand même à utili­ser const pour les litté­raux. Ça ne coûte pas grand chose et ça fixe par écrit l’in­ten­tion que j’ai en tête. Même si je n’y suis pas obligé, je fais tout de même atten­tion à garder let quand j’uti­lise un tableau ou un objet natif. J’ai trop peur d’in­duire en erreur le prochain déve­lop­peur qui passe (d’au­tant que ce sera proba­ble­ment moi).

    Je jette­rai peut-être de nouveau un œil à immu­table.js si une partie signi­fi­ca­tive des modules s’y conver­tit. Entre temps le ratio béné­fices/(risques+­dé­fauts) me parait assez faible.


    Au delà de ces ques­tions de décla­ra­tions, j’en tire un avis plutôt néga­tif sur la propa­ga­tion des variables en Javas­cript. On fait des ferme­tures lexi­cales de partout et on ne maitrise pas bien les effets de bord. Pas éton­nant que les déve­lop­peurs cherchent à avoir des variables et des struc­tures de données immuables ! Si la propa­ga­tion des variables était plus saines au départ, ce besoin ne ferait pas surface ainsi.

    var i = 1;
    function hello10times() {
      for(i=1; i<10; i++) {
        console.log("hello ");
      }
    }
    hello10times();
    // oups ! i a changé et vaut désormais 10

    PHP est plus strict (ouch, dire ça me fait mal) : Les variables ne sont pas décla­rées mais ne sont jamais héri­tées d’un contexte parent sauf à le décla­rer expli­ci­te­ment, avec global pour les variables globales, ou use pour les ferme­tures lexi­cales. On peut toujours faire des effets de bord assez moche, mais on les voit venir assez faci­le­ment.

    $i = 3;
    $hello10times = function () {
      for (i=1; i<10; i++) {
        echo "hello ";
      }
    }
    // $i vaut toujours 3
    
    $hello10times = function () use ($i) {
     for (i=1; i<10; i++) {
     echo "hello ";
     }
    }
    // $i vaut 10 mais là c'est forcément intentionnel

    La visi­bi­lité des variables de Python est plus proche de ce que fait Javas­cript mais, sauf à le décla­rer expli­ci­te­ment, si on utilise une variable d’un contexte parent, c’est en lecture seule. On garde des effets de bord, mais c’est déjà plus limité (bon, en échange savoir si la variable utili­sée est locale ou héri­tée n’est pas toujours super expli­cite).


    D’ailleurs, quitte à parler d’ex­pli­cite, je trouve dommage d’avoir à décla­rer mes variables en Javas­cript. Il n’y a pas vrai­ment le choix vu l’his­to­rique du langage mais ça reste agaçant vue la faible valeur ajou­tée de la chose, surtout quand je vois avec Crys­tal que même un langage à typage statique peut s’en passer.

    Si j’avais à créer un langage de zéro je pense que j’ap­pré­cie­rais de ne pas avoir à décla­rer mes variables, éven­tuel­le­ment leur donner la portée par défaut de let, mais avec la décla­ra­tion expli­cite de PHP pour les ferme­tures lexi­cales (avec peut-être une excep­tion pour les petites fonc­tions anonymes d’une unique ligne/expres­sion).

    L’idée de const me plait beau­coup, mais unique­ment si le langage se révèle capable de réel­le­ment rendre la donnée tota­le­ment immuable, et ça en profon­deur. À minima le freeze de Ruby serait une demie-solu­tion (une demie seule­ment parce qu’il faut penser à faire un freeze récur­sif sur un clone de tous les objets avant leur affec­ta­tion par const, ce qui est assez pénible). Celui de Javas­cript ne me semble pas effi­cace pour bloquer les chan­ge­ments d’état d’objets qui contiennent des proprié­tés privées (implé­men­tées via des ferme­tures syntaxiques).

    Tiens, ça pour­rait même être inté­gré au langage : si l’af­fec­ta­tion se fait avec := plutôt qu’a­vec =, alors ni la variable se voit affec­ter une copie immuable de la donnée, sans possi­bi­lité de modi­fi­ca­tion ou ré-affec­ta­tion.

    Si vous déve­lop­pez le nouveau langage de demain, vous avez désor­mais mon cahier des charges :-)

  • Résoudre le call­back hell — Javas­cript 102

    Après la mise en place, il est peut-être temps de faire un premier script. J’ai tenté un petit script que j’ai fait la veille en ruby : lister toutes les images dans une hiérar­chie de réper­toires et faire un gros fichier Json qui réca­pi­tule les diffé­rentes tailles.

    Faire un petit fichier outil CLI à l’aide de comman­der.js : un call­back. Lister les fichiers d’un réper­toire : un call­back. Lire les exif : un call­back. Écrire dans un fichier JSON : un call­back.

    Bon, lire et écrire peuvent se faire en synchrone sans call­back – et dans mon cas précis ça ne chan­ge­rait proba­ble­ment rien – mais je suis là aussi pour apprendre comment faire pour plus tard dans cet écosys­tème.

    Une hiérar­chie de quatre fonc­tions de rappel pour ce qui m’a pris 5 à 10 lignes tout mouillé en Ruby, ça me fait mal. J’avoue, je suis presque surpris que la trans­for­ma­tion en JSON ne me demande pas un call­back.

    Me voici en plein call­back hell. Le problème est connu. J’ai bête­ment pensé qu’on me donne­rait une solu­tion rapi­de­ment, un outil ou un usage à suivre.

    On me pointe vers les promesses ES2015 mais l’API Node et tous les modules en ligne conti­nuent à utili­ser des call­back. Sérieu­se­ment, personne n’a cher­ché à présen­ter l’API Node direc­te­ment en promesses ?

    C’est donc à moi de trans­for­mer chaque méthode ou chaque module pour qu’il utilise des promesses. Promi­sify semble être la baguette magique pour ça. À partir de là il suffit de conver­tir chaque module pour enchaî­ner des promesses (atten­tion aux écueils).

    Fran­che­ment ça reste assez moche. Des gens biens me pointent vers les systèmes à base de géné­ra­teurs (je recom­mande la lecture de ce lien) et le module co. Le code résul­tant est déjà bien plus lisible malgré les arti­fices.

    On me rappelle alors les async / await (là aussi, je recom­mande la lecture). Je crois que c’est seule­ment main­te­nant, après cette explo­ra­tion, que je comprends l’in­té­rêt et le fonc­tion­ne­ment. Parfait, si ce n’est qu’il faut choi­sir presque au hasard entre trois plugins diffé­rents pour ajou­ter la fonc­tion­na­lité à Babel.

    Atten­tion, ce n’est pas magique. Il faut se rappe­ler que ce n’est qu’une surcouche aux promesses, et il y a quelques écueils (lien indis­pen­sable si vous comp­tez utili­ser async/await) à bien connaitre là ici aussi, entre autres pour ne pas perdre les excep­tions dans un trou noir.

    Je me retrouve avec un code qui a l’air rela­ti­ve­ment élégant mais la réalité me rattrape : Visi­ble­ment quasi aucun code en produc­tion ne fonc­tionne ainsi. Une majo­rité des gens utilisent encore des call­backs, les autres se sont conten­tés des promesses. Est-ce une bonne idée de déjà viser les async/await ?


    Il reste aussi que j’ai l’im­pres­sion de retrou­ver le mode multi-tâche coopé­ra­tif de Micro­soft Windows 3.1 en moins bien inté­gré. Je ne vois aucune raison pour que la biblio­thèque stan­dard m’im­pose des call­backs, des promesses ou des async/await à tout bout de champ plutôt que de gérer ça en interne.

    L’OS sait déjà passer à un autre proces­sus quand mon programme est en attente d’une i/o. Si la machine virtuelle du langage veut gérer plusieurs fils d’exé­cu­tion en interne pour opti­mi­ser le proces­seur, qu’elle le gère elle-même via l’API mise à dispo­si­tion. C’est à elle d’iden­ti­fier que je veux ouvrir un fichier et de savoir qu’elle peut favo­ri­ser un autre fil d’exé­cu­tion en atten­dant que le disque me remonte la donnée. Je trouve ahuris­sant que ces méca­nismes débordent sur mon code et le complexi­fient ainsi.

    Oui, les promesses ne servent pas qu’à gérer la lenteur des i/o et faire coopé­rer les diffé­rents fils d’exé­cu­tions de la machine virtuelle V8 mais c’est quand même pour ça qu’on me les impose partout dans l’API de Node.js. Ça en devient même un style de program­ma­tion et les modules proposent des call­backs partout et pour tout (à vue de nez, y compris là où ça n’a pas vrai­ment de sens, à mon humble avis par mime­tisme).

    Promesses, async, call­backs… J’adore tous ces concepts, mais quand j’en ai besoin moi, pas pour compen­ser les choix d’ar­chi­tec­ture du moteur sous-jacent.

    Javas­cript a énor­mé­ment évolué, dans le bon sens. Côté syntaxe ES2015 et suivant donnent un résul­tat qui m’at­tire beau­coup. Le fonc­tion­ne­ment et l’API de Node.js me semblent pour l’ins­tant gâcher tout ce résul­tat. Un beau langage avec un boulet aux pieds.