Catégorie : Développement web

  • Un espace de publi­ca­tion chif­fré côté client

    Je ne veux plus gérer de serveur en ligne. Je me sens de moins en moins capable d’as­su­rer la sécu­rité d’un tel envi­ron­ne­ment 24/7 seul et sur mon temps person­nel. Je n’en ai pas la moti­va­tion, ne souhaite pas y inves­tir le temps néces­saire. Ne parlons même pas de la possi­bi­lité de prendre des congés deux semaines hors de France sans connexion Inter­net ni veille sécu­rité. Rien qu’a­voir ce blog sous word­press me gêne.

    Je vais dépla­cer mes services sur un envi­ron­ne­ment mutua­lisé, géré par des profes­sion­nels qui ont les moyens, le temps et les compé­tences. Je vais en profi­ter pour passer à peu près tout en fichiers HTML statiques. Publier des fichiers html, css et images sur un espace à 2€, ça limite pas mal la main­te­nance.

    * * *

    Mon problème c’est que j’ai aussi des parties de site à accès restreint, avec des docu­ments qui ne doivent pas sortir n’im­porte où.

    Je peux faci­le­ment trou­ver un héber­ge­ment mutua­lisé qui me permet de faire des accès restreints par authen­ti­fi­ca­tion HTTP ou avec un bout de PHP en façade, mais j’ai une confiance limi­tée dans la confi­den­tia­lité des fichiers que je peux poser sur un héber­geur mutua­lisé.

    Du coup j’ima­gine utili­ser du chif­fre­ment côté client, avec un croi­se­ment entre Jekyll/Peli­can et 0bin/cryp­to­pad. Je chiffre les conte­nus lors de la géné­ra­tion et je les envoie chif­frés sur l’hé­ber­ge­ment. Les conte­nus sont déchif­frés dans le navi­ga­teur du client avec un gros bout de JS, en utili­sant un dérivé de mot de passe ou une clef cachée dans l’URL.

    Le seul défaut que je vois c’est inter­dire l’ac­cès à ceux qui désac­tivent volon­tai­re­ment Javas­cript, et impo­ser un peu d’at­tente aux autres pour déver­rouiller les conte­nus : Pas idéal, pas perti­nent pour tous les usages, mais ici ça me semble accep­table.

    * * *

    Il y a 0bin et Cryp­to­pad (ainsi que d’autres) qui fonc­tionnent un peu sur ce prin­cipe, mais bran­cher ça dans Jekyll ou Peli­can me semble néces­si­ter un peu de travail, surtout si je veux avoir plus que du texte et que je veux présen­ter à l’uti­li­sa­teur unique­ment les liens auxquels il a accès.

    Si vous connais­sez un CMS à publi­ca­tion statique qui a envi­sagé quelque chose du genre, je suis preneur.

  • [Aide] Commu­ni­ca­tion entre une page et une exten­sion navi­ga­teur

    J’ai une page qui fait des trai­te­ments javas­cripts basés sur des appels XHR authen­ti­fiés vers son origine et sur des commu­ni­ca­tions en window.postMes­sage avec des <iframe>. Elle n’a besoin d’au­cune permis­sion privi­lé­giée, c’est juste une page web avec une origine normale.

    J’ai­me­rais pouvoir inter­ro­ger cette page depuis une exten­sion Fire­fox et qu’elle me commu­nique le résul­tat de ses trai­te­ments, mais sans que ça n’af­fiche la page à l’uti­li­sa­teur.

    Au départ j’ima­gi­nais que l’ex­ten­sion pouvait lancer une <iframe> cachée et discu­ter avec elle en postMes­sage. On me dit que ce n’est pas possible.

    Embarquer direc­te­ment le code de la page dans l’ex­ten­sion n’est pas envi­sa­geable pour des raisons de sécu­rité (et on ne ferait que repor­ter le problème vu que cette page lance elle-même des iframes pour commu­niquer avec elles).

    Dis, public, est-ce que tu aurais une sugges­tion ou une piste à explo­rer ?

  • La base de travail pour 2018

    Une progres­sive web app prévue d’abord pour mobile, fonc­tion­nant tota­le­ment hors ligne avec une synchro à la prochaine recon­nexion et des données chif­frées côté client.

    Oui, votre besoin a peut-être des usages ou des contraintes qui ne cadrent pas avec ce stéréo­type mais ça mérite proba­ble­ment d’y réflé­chir deux fois avant d’écar­ter un des éléments.

    Quand je vois nombre de projets sans chif­fre­ment des données ou quasi­ment inutiles une fois hors ligne, j’ai l’im­pres­sion de retrou­ver les projets d’il y a quelques années qui consi­dé­raient le mobile comme acces­soire.

  • Et si on agençait des photos sur une page web mobile ?

    J’ai commencé à vouloir mettre en pratique mes études sur l’agen­ce­ment de photos dans une page web et… j’ai tout repris à zéro.

    Quand je donne un lien vers mes photos, il est quasi­ment toujours ouvert en premier sur mobile. Sauf à y faire des minia­tures illi­sibles, on peut y mettre une ou deux photos maxi­mum en largeur. La vue à la Flickr n’a aucun sens.

    Du coup je suis reparti d’une vue mobile, avec des agen­ce­ments prédé­ter­mi­nés. J’ai en trouvé quatre, même si bien évidem­ment certains peuvent s’in­ver­ser :

    Tech­nique­ment les calculs pour que les agen­ce­ments avec plusieurs images tombent « juste » sont les mêmes que dans la vue Flickr décrite au précé­dent billet.

    * * *

    La vraie ques­tion c’est le choix de l’agen­ce­ment en fonc­tion du format des diffé­rentes photos et de leur ordre d’ap­pa­ri­tion.

    La mauvaise idée de départ c’était tenter de faire des règles complexes pour choi­sir l’agen­ce­ment en fonc­tion des prochaines images et de leur format. L’ap­proche naïve était simple mais le résul­tat assez mauvais visuel­le­ment. Il aurait fallu faire plus complexe que verti­cal / carré / hori­zon­tal mais si je commence à distin­guer sept caté­go­ries, les combi­nai­sons explosent.

    Autant calcu­ler les quatre agen­ce­ments possibles et voir lequel est le plus perti­nent. J’ai pris deux axiomes :

    1– L’im­por­tant visuel­le­ment c’est la surface affi­chée de chaque image plutôt que sa taille en largeur ou hauteur.  Trop gros est aussi mauvais que trop petit. Je compare donc la surface de l’image à évaluer à celle d’une image de réfé­rence (une hori­zon­tale au format 3/2 affi­chée en pleine largeur).

    2– Il suffit d’une seule image illi­sible pour tout gâcher. Je calcule donc le score de chaque image indi­vi­duel­le­ment et le score d’un agen­ce­ment de plusieurs images corres­pond au plus mauvais score des images concer­nées.

    Le résul­tat est plutôt réussi. J’ai tenté de bidouiller et ajou­ter d’autres règles complexes mais ça n’a pas donné des amélio­ra­tions visuelles signi­fi­ca­tives.

    * * *

    Je calcule la gale­rie au fur et à mesure. Parfois il me reste une image verti­cale à la fin et je n’ai plus qu’à l’af­fi­cher en grand, même si c’est déme­suré. Une solu­tion pour­rait être de calcu­ler réel­le­ment toutes les combi­nai­sons pour toute la gale­rie avant de faire mon choix. Ça risque d’être un peu lourd pour ce seul défaut, surtout pour des gale­ries assez longues, donc pour l’ins­tant je ne suis pas allé sur ce chemin.

    Aujourd’­hui je garde l’ordre des photos. Je pour­rais aussi éven­tuel­le­ment iden­ti­fier les cas où tous les agen­ce­ments testés sont mauvais, et tenter de modi­fier un peu l’ordre des images avec celles juste après, pour voir si c’est mieux.

    Tant que je ne repère pas de cas vrai­ment moche, je vais toute­fois rester sur du simple.

    * * *

    Le choix assumé c’est de faire du mobile-first. Si j’ai plus d’es­pace hori­zon­tal je peux tenter de faire deux colonnes avec ce même algo­rithme.

    Si je trouve un point pivot et que je découpe la gale­rie en deux sections, je pour­rai choi­sir de les enchaî­ner verti­ca­le­ment ou hori­zon­ta­le­ment sans avoir besoin de calcu­ler quoi que ce soit en javas­cript.

    Si j’ai vrai­ment une grande surface en hauteur et en largeur, un mur d’images à la Flickr est peut-être plus perti­nent mais je ne m’in­ter­dis pas de simple­ment garder deux colonnes de grande largeur. Je vais attendre de voir ce que ça donne avant de faire mon choix.

     

  • 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 ?

  • 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.