Auteur/autrice : Éric

  • Cherche à discu­ter orga et mana­ge­ment

    Je cherche à discu­ter orga­ni­sa­tion et mana­ge­ment d’une équipe tech­nique / produit, et donc à rencon­trer des gens qui sont ou ont été partie prenante dans des équipes de taille signi­fi­ca­tive (on va dire de l’ordre de 20 à 50 personnes en tech­nique).

    CTOs, leads, mana­gers, si vous vous retrou­vez dans cette descrip­tion vous voulez bien me lais­ser un message pour qu’on discute un peu ? Merci pour l’aide.

  • Qui comprend le nommage des Kobo Aura ?

    Le nommage des liseuses Kobo Aura me semble des plus étranges.

    La Aura One est la troi­sième liseuse de la gamme Aura (logique hein ?). Elle a aussi un écran de plus haute défi­ni­tion et plus haute réso­lu­tion que la Aura HD.

    On voit arri­ver une Aura 2. La Aura 2 est la quatrième liseuse de la gamme Aura. On peut trou­ver ça natu­rel si la Aura One est la troi­sième liseuse de la gamme, mais la Aura 2 n’est pas la suite de la Aura One. En fait Aura One et Aura 2 sortent presque en même temps sur le marché, sur deux formats diffé­rent. Pour ajou­ter à la clarté, la Aura 2 a un plus petit format que la Aura One.

    Le couple Aura / Aura HD corres­pond à respec­ti­ve­ment à des liseuses format stan­dard (6″) et moyen format (6.8″) de même géné­ra­tion mais le couple Glo / Glo HD corres­pond à deux liseuses du même format stan­dard (6″) de géné­ra­tion diffé­rente.

    La Aura était le haut de gamme 6″, contenu simi­laire à la Glo mais avec un design de boitier plus cher, plus haut de gamme. Elles sont rempla­cées respec­ti­ve­ment par la Aura 2 et la Glo HD mais la Glo HD, bien que sortie bien avant, a un écran plus haut de gamme et se retrouve au même prix que la Aura 2.

    Quelqu’un 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 :-)

  • [Commen­taire] Limi­ter le chif­fre­ment

    Ne croyez donc pas qu’ils soient incom­pé­tents. C’est faux. Ils sont compé­tents. Ils sont entou­rés de gens brillants. Ils ont été aver­tis, par les bonnes personnes, qu’il ne fallait pas faire ça. Et ils le font quand-même.

    Toute analyse qui s’ap­puie sur l’idée que nos ministres sont idiots est inva­lide. Toute analyse qui s’ap­puie sur le fait qu’ils soient incom­pé­tents, ou mal infor­més, cherche à leur trou­ver une excuse qui n’est pas la bonne.

    Mais alors… Alors l’ana­lyse est plus compliquée à poser.

    — Benja­min Bayard

    J’ai­mais bien la maxime qui disait en gros « ne cher­chez pas l’in­ten­tion maligne là où il peut n’y avoir que de l’idio­tie ». Elle était beau­coup ressor­tie du temps de Georges W. Bush et elle permet de rester sur terre : Nos diri­geants font parfois des choses que nous jugeons idiotes mais c’est non seule­ment réflé­chi mais en plus quasi­ment toujours avec une bonne

    Donc, oui, ils ne sont pas fous, pas au sens « je fais n’im­porte quoi ». Le lais­ser croire c’est se mettre des œillères.

    Non. Ils ont peur qu’on leur reproche leur inac­tion. Ils ont peur qu’il y ait encore des atten­tats, et qu’on dise que c’est de leur faute. Alors il faut bien faire quelque chose. Inutile, dange­reux, tota­li­taire, n’im­porte quoi, mais quelque chose.

    Ça j’y crois beau­coup. Parfois c’est d’ailleurs dit expli­ci­te­ment sous le ton « les français ne compren­draient pas » ou « il faut agir ». Cepen­dant l’at­taque contre le chif­fre­ment arrive dans un espace vide, pas sous la pres­sion. C’est le gouver­ne­ment qui amène lui-même le sujet. Personne ne lui aurait repro­ché de ne pas le faire.

    C’est une superbe raison pour moultes inter­dic­tions et annu­la­tions, pour l’état d’ur­gences et bien d’autres choses. Ici ça me semble moins perti­nent.

    Bran­dir le tout sécu­ri­taire, agiter les peurs et les haines, c’est une stra­té­gie pour récol­ter les votes des gens qui ont peur.

    C’est fait tous les jours, même si prin­ci­pa­le­ment par ceux qui ne sont pas au pouvoir – ceux qui sont au pouvoir doivent aussi rassu­rer pour prou­ver qu’ils ont agit ou que ce qu’ils font va tout solu­tion­ner, diffi­cile exer­cice d’équi­li­briste.

    Pour autant je n’y crois pas là non plus. Le sujet ne tourne pas, ne rassure pas l’élec­to­rat conser­va­teur. Si le débat était établi, incon­tour­nable, pourquoi pas. Là ça va durer maxi­mum deux semaines. Ça ne vaut vrai­ment pas le coup.

    Si notre gouver­ne­ment propose de sucrer le chif­fre­ment c’est qu’ils veulent vrai­ment le faire. Ce n’est d’ailleurs pas neuf.

    Enfin, il reste l’angle d’ana­lyse le plus raison­nable. Nos diri­geants veulent surveiller le peuple pour s’as­su­rer de rester au pouvoir quoiqu’il advienne. Oh, pas forcé­ment eux indi­vi­duel­le­ment, mais leur caste.

    Là on est direc­te­ment dans l’in­ten­tion maligne, limite dans le complot. Je ne crois pas une seconde qu’il y ait une réflexion consciente à faire un choix poli­tique pour que le pouvoir reste aux mains d’une caste qui inclut aussi le parti d’en face.

    On exclu­rait qui ? Le peuple ? mais il en est déjà exclu de toutes façons, par défi­ni­tion. Ceux qui arrivent dans le jeu poli­tique à un niveau sérieux ne sont déjà plus « le peuple ».

    Non, par contre je crois à cette distinc­tion « nous » – « le peuple ». Quand ils coupent le chif­fre­ment, ils n’ima­ginent pas une seconde que ça va les impac­ter eux. Le chif­fre­ment sera encore légi­time pour les services de l’État et des collec­ti­vi­tés, pour proté­ger les secrets des entre­prises. Leurs commu­ni­ca­tions ne risquent rien. Ça ne concerne que le peuple, les autres, ceux en qui on ne peut ni ne doit avoir confiance.

    On le voit faci­le­ment aujourd’­hui dans les débats où l’op­po­si­tion demande la fin de l’État de droit et des arres­ta­tions sans motifs. Ils n’ima­ginent pas un instant que eux pour­raient être empri­son­nés ainsi sur une simple note confi­den­tielle d’un service sous l’au­to­rité hiérar­chique directe du Premier ministre, bref, sur simple volonté de la personne qu’ils combattent. Je crois que ça veut tout dire.

    Nos diri­geants sont coupés de tout, et sont alimen­tés en continu d’in­for­ma­tions anxio­gènes par des hauts fonc­tion­naires des services de police, parfois (souvent ?) avec des visées sécu­ri­taires ou tota­li­taires, typique­ment Alain Bauer et ses semblables. Ça peut suffire à perdre les pédales.

    Je ne nie pas qu’ils soient coupés de tout, et parfois de la réalité. Je doute que ça soit une expli­ca­tion de la lutte contre le chif­fre­ment. Certes on peut s’em­bal­ler mais s’ils ont des conseillers, ils ont aussi des gens pour filtrer, trier, résu­mer et remettre en contexte l’in­for­ma­tion.

    Si on se dit qu’ils ne peuvent pas igno­rer que leur solu­tion est erro­née vu le nombre de conseillers brillants qu’ils ont, alors ils ne devraient pas non plus pouvoir perdre les pédales par simple amas d’in­for­ma­tions anxio­gènes, pour la même raison.

    Le truc : écoutent-ils ces conseillers ? Ce qu’on lit régu­liè­re­ment laisse plutôt à penser qu’ils écoutent un ou deux conseillers favo­ris, qui n’ap­par­tiennent juste­ment pas au corps de fonc­tion­naires, et eux-seuls. Je me rappelle aussi cet article de presse qui rele­vait des propos de E. Valls disant en gros qu’il éprou­vait une fierté à avoir raison seul contre tous et à mener sa poli­tique ainsi.

    Énorme égo et préjugé de supé­rio­rité mons­trueux. Ça j’y crois faci­le­ment et ça casse toute l’ar­gu­men­ta­tion liée aux conseillers brillants. Encore faudrait-il que ces conseillers soient écou­tés et leurs avis pris en comp­te…

    Pire, encore faudrait-il que ces conseillers ne soient pas noyés dans ceux qui se font une joie de flat­ter les avis de la personne au pouvoir pour faire avan­cer leur carriè­re…

    Voilà ce qui me parait fina­le­ment le plus probable, parce que le plus humain et ne néces­si­tant aucune inten­tion maligne : Ces gens croient avoir raison, envers et contre tous, surtout contre ces igno­rants de citoyens qui ne comprennent pas la complexité et les respon­sa­bi­li­tés que eux portent sur les épaules. Égo déme­suré, compor­te­ment d’une caste de privi­lé­giés.

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

  • Recom­mençons à zéro — Javas­cript 101

    PHP a été mon langage favori pendant presque 10 ans. Ruby l’a suivi pour à peu près la même durée. Javas­cript a été l’ou­til secon­daire pas très atti­rant pour quand il n’y a pas d’autre choix, c’est à dire sur navi­ga­teur.

    Avant-hier j’ai eu un petit pince­ment de frus­tra­tion en cher­chant à déstruc­tu­rer un diction­naire lors d’une affec­ta­tion. Ruby n’a toujours qu’une demie solu­tion pas très élégante. PHP et Javas­cript ont tous deux énor­mé­ment évolué entre temps, au point qu’on ne les recon­nait qu’à peine.

    Si Ruby garde des capa­ci­tés inéga­lées pour faire de la méta-program­ma­tion, 10 ans c’est peut être le bon moment pour reprendre un autre langage de zéro.

    Je fais du web, j’aime beau­coup l’idée de l’iso­mor­phisme, il me faudra donc quelque chose qui sache compi­ler en Javas­cript. Elm pour­rait me faire du pied vu sa gestion des types mais c’est un pari osé consi­dé­rant qu’il est encore absent côté serveur.

    Ça sera donc Javas­cript. D’abord pour quelques scripts en ligne de commande, puis peut-être des appli­ca­tions plus sérieuses.

    Reprendre de zéro c’est l’oc­ca­sion de lais­ser le passé derrière soi et recom­men­cer comme si c’était un nouveau langage. Je ne prends que les dernières versions et outils récents dans la chaîne, voire ce qui n’est pas encore sec mais qui arri­vera demain.

    Il s’agit aussi de reprendre de zéro, pour apprendre. Exit donc les boiler plate et autres kits de démar­rage rapide.


    Première étape : instal­la­tion de npm (3.10.3) et nodejs (6.3.1).

    # Sur Mac avec Homebrew (http://brew.sh/)
    brew install nodejs

    et initia­li­sa­tion du projet (un peu de doc si besoin pour aider à remplir)

    mkdir my-js-project
    cd my-js-project
    npm init

    Ensuite l’idée c’est d’uti­li­ser le nouveau Javas­cript moderne et ne cher­cher aucune compa­ti­bi­lité passée. Instal­la­tion de Babel pour gérer ES2015 et + :

    npm install --save-dev babel-cli

    La plupart des sites recom­mandent des preset pour ES2015 ou React mais visi­ble­ment Nodejs 6.x gère déjà l’es­sen­tiel des fonc­tions nati­ve­ment. Il existe au moins trois preset spéci­fiques pour Nodejs 6 mais la seule confi­gu­ra­tion commune aux trois est le plugin qui trans­forme les modules ES2015 en modules Commonjs. Je suis donc reparti de là :

    npm install --save-dev babel-plugin-transform-es2015-modules-commonjs

    Puis l’édi­tion du .babelrc :

    {
      "presets": [ ],
      "plugins": [ "transform-es2015-modules-commonjs" ]
    }

    Si quelque chose manque à Nodejs 6, il faudra que j’ajoute le plugin corres­pon­dant. Voici les plugins sur lesquels mes trois presets étaient en désac­cord :

    • trans­form-es2015-func­tion-name,
    • syntax-trai­ling-func­tion-commas,
    • trans­form-es2015-destruc­tu­ring,
    • trans­form-es2015-para­me­ters,
    • trans­form-object-rest-spread,
    • trans­form-es2015-sticky-regex,
    • trans­form-es2015-unicode-regex,
    • trans­form-es2015-modules-commonjs,
    • et trans­form-class-proper­ties.

    Je n’ai pas pris le temps de les tester un par un pour voir lesquels étaient réel­le­ment néces­saires pour pas. Si quelqu’un a le courage de faire le travail…

    Reste à enfin permettre d’exé­cu­ter un premier script. J’ai tenté de suivre les usages en mettant les sources dans src/ et les fichiers compi­lés dans lib/ avec un index.js comme fichier prin­ci­pal.

    mkdir lib
    echo "Compiled files will go here." > lib/README.md
    echo "Leave these files untouched"  >> lib/README.md
    echo "and modify ../src/* instead." >> lib/README.md
    
    mkdir src
    echo "Source files will go here." > src/README.md
    echo "They should be compiled before any use." >> src/README.md
    touch src/index.js

    Et la confi­gu­ra­tion du package.json pour lancer tout ça (notez le main qui prend en compte notre nouveau chemin et le scripts qui liste nos deux nouvelles actions) :

    {
      "name": "my-project",
      "main": "./lib/index.js",
      "scripts": {
        "build": "babel src -d lib --source-maps",
        "watch": "babel src -d lib --watch --source-maps"
      },
      "devDependencies": {
        "babel-cli": "^6.11.4",
        "babel-plugin-transform-es2015-modules-commonjs": "^6.11.5"
      }
    }

    Un npm run build permet de compi­ler tous les fichiers, un npm run watch permet de surveiller en temps réel les modi­fi­ca­tions des fichiers sources pour mettre à jour les fichiers desti­na­tion corres­pon­dants.


    J’ai ajouté un README, le .giti­gnore proposé par Github pour un projet Nodejs, une licence, et ‘op, vous trou­ve­rez le tout sur Github.

    Ça fait déjà pas mal pour toujours aucune ligne de Javas­cript utile.

    Quelques feed­back après ce tout petit premier pas :

    1– C’est long et complexe

    Oui, j’ai cher­ché les ennuis, il existe des boiler plate tout faits, mais je ne crois pas avoir le même problème avec Python, Ruby, PHP ou d’autres.

    Le fait d’avoir une étape de compi­la­tion avec Babel n’aide pas mais Java pour­rait en dire tout autant. Pourquoi n’existe-t-il pas un babel init qui lit la version courante de Nodejs, m’ins­talle un .babelrc adapté à cette version et me modi­fie mon package.json pour m’ajou­ter les raccour­cis build et watch ?

    Oui, je pour­rais faire une pull-request, mais fallait-il m’at­tendre ?

    2– La doc aide peu

    Fran­che­ment c’est la plaie. Je ne dirais pas qu’il n’y a aucune doc, mais il y en a dans tous les sens. La plupart ne sont pas à jour, toutes semblent incom­plètes, et il est bien diffi­cile de savoir si telle ou telle a pris en compte les dernières évolu­tions.

    Peut-être n’ai-je pas trouvé la bonne réfé­rence ? Dites-moi.

    Rien que le npm init n’était indiqué sur aucune doc que j’ai croisé. Pire : si on l’ou­blie il n’y a pas de message rouge très expli­cite pour indiquer que les npm install –save-dev n’au­ront pas l’ef­fet demandé. Il a fallu comprendre qu’il fallait créer un package.json, puis décou­vrir qu’il n’était pas néces­saire de le faire à la main.

    Ce n’est que le début. Quand il va s’agir de choi­sir une biblio­thèque ou des outils, je sens que ça va être toute une histoire pour d’y retrou­ver. La doc de setup de Babel en donne un premier aperçu.

    J’ai l’im­pres­sion qu’à chaque étape la roue est en pleine recons­truc­tion, et qu’on en a fait plusieurs versions diffé­rentes en paral­lèle, pour tout.

    3– Qui a eu l’idée d’uti­li­ser des fichiers de config JSON ?

    Je suis aussi assez peu fana aussi des config dans des fichiers Json. J’ai l’im­pres­sion de retrou­ver les fichiers de confi­gu­ra­tion XML de Java. Je n’ai pas l’im­pres­sion que ce soit beau­coup plus lisible.

    La grosse diffé­rence c’est que Java a créé ces confi­gu­ra­tions avec tout un outillage autour. Le déve­lop­peur n’avait que rare­ment besoin d’y plon­ger manuel­le­ment. C’était géré auto­ma­tique­ment par les IDE et les scripts.

    J’ai ajouté un plugin au .babelrc décrit plus haut. Ce plugin a une option. Je me retrouve avec un Json de 7 lignes dont 4 qui contiennent autre chose que des crochets et acco­lades fermantes.… et déjà un diction­naire dans un tableau dans un tableau dans un diction­naire. Rien que ça.

    Même mon petit package.json me parait déli­cat à mani­pu­ler malgré l’in­den­ta­tion. Heureu­se­ment que les dépen­dances sont ajou­tées auto­ma­tique­ment par npm lors de leur instal­la­tion.

    Là, dès qu’on dépasse le simple clef valeur, j’ai l’im­pres­sion de me retrou­ver avec une double peine : Un fichier de confi­gu­ra­tion peu aisé à mani­pu­ler, mais pas pour autant d’ou­til pour le faire à ma place.

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

    J’ai cher­ché à agen­cer des vignettes de photo de façon harmo­nieuse sur une page web. Le problème à l’air simple mais j’ai des photos de tous formats, dont certains vrai­ment atypiques.

    La grille

    La méthode la plus simple c’est de choi­sir un format d’images, choi­sir un nombre de colonnes, et de s’y tenir. Si une image n’a pas le bon ratio, il suffira de couper ce qui dépasse. 500px utilise encore ce système pour la plupart de ses vues.

    grillePour aller plus loin on peut mettre quelques photos en grande taille en prenant la place de plusieurs autres. On casse la mono­to­nie tout en permet­tant de mettre en avant les images les plus impor­tantes.

    En prévoyant plusieurs agen­ce­ments diffé­rents prédé­ter­mi­nés on peut réus­sir à caser des images en format diffé­rent, et ne pas trop déna­tu­rer  les formats portraits ou les images très étirées. On reste toute­fois fixés à des formats prédé­ter­mi­nés.

    Le système de grille est rapide et effi­cace. La seule contrainte est de choi­sir entre la capa­cité de respec­ter scru­pu­leu­se­ment l’ordre des photos et celle de choi­sir manuel­le­ment lesquelles seront mises en avant.

    L’al­go­rithme de Packery va encore plus loin sur ce chemin. À partir d’une grille fixée, il propose de défi­nir un nombre de lignes et de colonnes pour chaque image et de la placer à l’es­pace le plus adapté. L’ordre n’est alors qu’in­di­ca­tif et on doit toujours rogner les images pour les faire tenir sur un nombre fixe de lignes et colonnes, mais on y place des formats et des tailles très diffé­rentes. Pas de secret toute­fois, cet agen­ce­ment lais­sera forcé­ment des blancs. À vous de voir si c’est accep­table, quitte à tenter de les combler par quelques mots.

    Quel que soit le système de grille, le réel enjeu est de savoir ce qu’on peut couper ou pas dans chaque image pour qu’elle colle aux formats prévus. Certains algo­rithmes y arrivent main­te­nant assez bien, surtout quand il y a des visages.

    Même si mon cas d’usage me permet­trait de choi­sir manuel­le­ment comment décou­per chaque image au cas par cas, intel­lec­tuel­le­ment ça me gêne de couper des pixels que j’avais volon­tai­re­ment choisi de garder lors de la créa­tion initiale de l’image. Je crains aussi que le visi­teur s’en fasse une idée faus­sée et au final n’ouvre pas l’image dans son format voulu. C’est parti­cu­liè­re­ment vrai pour les images très en hauteur ou très en largeur, qui ne pour­ront jamais donner le même ressenti si elles sont tronquées.

    On empile

    L’autre méthode est d’em­pi­ler les photos par lignes ou par colonnes en respec­tant leur ratio.

    Tumblr le fait par colonnes en mettant chaque image sur la première place dispo­nible. On obtient une sensa­tion de vrac où l’ordre des images n’est qu’à moitié respecté mais le résul­tat est parfait pour leur cas d’usage. Toutes les images ne terminent pas à la même hauteur mais c’est là encore tout à fait légi­time pour le système de flux sans fin que repré­sente un Tumblr.

    On peut imagi­ner de mettre en avant des images en les passant sur deux colonnes mais, sauf à espé­rer un cas excep­tion­nel où les deux images du dessus s’ar­rêtent pile à la même hauteur, il faudra soit lais­ser du blanc soit couper un peu la plus longue des deux.

    Avec un algo­rithme un peu intel­li­gent on peut tenter de repé­rer quand deux images arrivent presque à la même hauteur et donc ne couper que quelques pixels qui ne se verront pas, mais ça veut aussi dire que l’image mise en avant est quasi­ment lais­sée au hasard. La proba­bi­lité d’en avoir une dépend direc­te­ment de la quan­tité de pixels qu’on accepte de rogner sur les images.

    Pour quelque chose de plus struc­turé Flickr a choisi une dispo­si­tion par lignes. On choi­sit une hauteur cible et on empile toutes les images une à une jusqu’à la fin de la ligne. Ça ne tombe jamais juste mais Flickr se permet alors de faire varier légè­re­ment la hauteur de la ligne à la hausse ou à la baisse. Si on respecte les ratios des images concer­nées, on finira forcé­ment par tomber sur la largeur de ligne souhai­tée. On peut choi­sir de garder la dernière image ou pas (respec­ti­ve­ment en dimi­nuant ou augmen­tant la hauteur de ligne) en fonc­tion de la dispo­si­tion la plus proche de la hauteur idéale.

    Avec un peu de complexité on doit pouvoir éviter les lignes incom­plètes en fin de page. Il suffit de tenter plusieurs combi­nai­sons sur les x dernières lignes puis voir laquelle respecte le mieux la hauteur cible pour chaque ligne parmi celles qui n’ont aucune ligne incom­plète. Je ne suis cepen­dant pas tota­le­ment certain que ça vaille le coup, et ça peut faire varier signi­fi­ca­ti­ve­ment la hauteur des dernières lignes.

    Ce système permet des mises en avant simples en mettant une image en pleine largeur de temps en temps. On peut même, si on le souhaite, avoir des mises en avant à largeur arbi­traire. Il suffit alors de mettre les mises en avant sur un des bord et de reprendre l’al­go­rithme stan­dard sur la largeur restante. Une fois arrivé proche du bas de l’image mis en avant, on la réduit ou l’agran­dit légè­re­ment (avec pour effet d’agran­dir ou de réduire propor­tion­nel­le­ment l’es­pace hori­zon­tal sur le côté, et donc la hauteur corres­pon­dante) jusqu’à ce que les deux corres­pondent.

    On peut aussi imagi­ner ne pas se limi­ter à une seule mise en avant par hauteur et les empi­ler sur un ou deux côtés, y compris sur des hauteurs diffé­rentes. La contrainte va être de toujours avoir les plus hautes à l’ex­té­rieur.

    Il reste que la dispo­si­tion en colonnes de Tumblr flatte les images verti­cales et vigné­tise à l’ex­cès des images orien­tées format paysage. La dispo­si­tion en lignes de Flickr fait l’op­posé et rend diffi­cile la lecture des images au format portrait.

    Si un format est très forte­ment majo­ri­taire, on peut imagi­ner utili­ser le système des mises en avant pour compen­ser.

    Je n’ai pas vu d’adap­ta­tion de l’al­go­rithme Flickr en ce sens. Il faut dire que ça complexi­fie­rait nette­ment un système qui est sinon rela­ti­ve­ment simple. Si j’ai un peu de temps, je vais peut-être tenter l’ex­pé­rience.


    Quelques liens si le sujet vous inté­resse :

  • [Posi­tif] Venti­la­teur silen­cieux

    Et si on disait du bien ?

    91LEjCQKCLL._SL1500_Une semaine sans clima­ti­sa­tion par forte chaleur, dix venti­la­teurs de comman­dés sur Amazon. La bonne surprise c’est qu’ils sont *vrai­ment* silen­cieux – silen­cieux, pas juste peu bruyant ou très lent – tout en ayant un bon débit d’air. On peut travailler ou même dormir à côté.

    Oui, c’est indiqué sur la boite, et le prix est en consé­quence, mais ma confiance dans les indi­ca­tions marke­ting est parfois réduite.

    Donc voilà, c’est le Rowenta VU2640F0 Turbo silence. 40 cm pour 85 € (oui, quand même).

  • Choi­sir notre monde

    Je vois les poli­tiques gesti­cu­ler dans une esca­lade à celui qui reniera le plus les valeurs qu’il prétend défendre, et la popu­la­tion qui cherche à qui la faute.

    J’ai mal, parce qu’a­voir arrêté un camion qui se lance sur la foule en tout juste deux minutes, c’est une sacré réus­site, un exploit même. Pas dit que le lance roquette de Henri Guaino aurait fait mieux.

    Oui, c’est une réus­site de nos services de police, malgré le lourd bilan.


    Bon, c’est aussi un énorme coup de chance mais quand l’au­teur prépare ça sur quelques jours sans histo­rique ni connexion avec le milieu terro­riste, il est illu­soire de penser faire mieux.

    Dès que quelqu’un est prêt à mourir, il pourra toujours faci­le­ment tuer des gens au hasard dans la rue, poten­tiel­le­ment beau­coup, quoi qu’on fasse.

    Nous pouvons mettre des check­points tous les deux kilo­mètres, des blocs de béton en zigzag sur tous les axes, des patrouilles mili­taires lour­de­ment armées en surnombre à tous les carre­fours, une surveillance totale sur toutes les commu­ni­ca­tions, des fouilles systé­ma­tiques à chaque bâti­ment, un empri­son­ne­ment préven­tif et sans procès, des recon­duites à la fron­tières en masse, un contrôle de la reli­gion et une inter­dic­tion de tout prosé­ly­tisme d’une opinion non caution­née par le pouvoir en place…

    Nous pouvons, mais ça ne chan­ge­rait rien. Si nous pouvions combattre le terro­risme ainsi, à voir les moyens déployés en ce sens du Moyen-Orient à l’Afrique du Nord, la paix aurait été obte­nue depuis long­temps. Au lieu de cela, nos morts sont presque anec­do­tiques face aux leurs.


    Ne rien faire n’est pas une solu­tion non plus, mais il y a un équi­libre à trou­ver. Aujourd’­hui j’ai l’im­pres­sion que nous l’avons large­ment dépassé.

    Il y a bien des causes en France qui provoquent plus de 300 drames par an et pour lesquelles on ne déploie même pas le dixième des moyens actuels. Des causes pour lesquelles nous n’au­rions même pas besoin de renier nos valeurs. Des causes pour aider et permettre plutôt que pour empê­cher et humi­lier.

    De quels moyens aurions-nous besoin pour accom­pa­gner ses parents isolés qui viennent de perdre leur conjoint et qui ne savent comment faire face aux besoins de la famille ? De quels moyens aurions-nous besoin pour éviter que 500 SDF meurent dans nos rues chaque année ? De quels moyens aurions-nous besoin pour accom­pa­gner quelques milliers de syriens qui fuient la guerre que nous menons chez eux plutôt que de les lais­ser se noyer ou mourir en chemin ? Certai­ne­ment beau­coup moins, autant au niveau finan­cier qu’au niveau symbo­lique.

    On me dira que ça n’a rien à voir. Je ne suis pas d’ac­cord. C’est un choix. À part que les gens qui prennent les déci­sions ne sont ni dans le besoin ni SDF ni syriens, il y a-t-il vrai­ment une bonne raison de plutôt conti­nuer d’in­ves­tir dans l’écra­se­ment inutile de nos valeurs et de nos liber­tés ?


    Mon fils a commencé à toucher au maté­riel élec­tro­nique à l’âge de deux ans. J’ai tenté de proté­ger en mettant des choses devant mais ça n’a été qu’une complexité à résoudre, rien qui n’a changé l’is­sue. J’ai surveillé le maté­riel en sa présence, évité qu’il n’ap­proche. Je me suis épuisé mais lui a conti­nué à profi­ter de chaque inat­ten­tion, et surtout il y a trouvé plein d’autres trucs que je ne voulais pas qu’il touche. Évidem­ment j’ai inter­dit mais à cet âge ça lui passe au-dessus. Quoique… au moins il savait quoi faire quand il avait envie de faire une bêtise. J’ai eu une période diffi­cile, avec oppo­si­tion systé­ma­tique. Je ne suis pas fier, j’ai même du crier trop fort ou punir quand je n’en pouvais plus.

    Il y avait d’autres solu­tions. Il y avait lui accor­der plus de temps, jouer avec lui plutôt que travailler à côté sur l’or­di­na­teur, lui donner à manger quand il a faim mais avant qu’il ne le demande lui-même, lui faire faire la sieste quand il a sommeil plutôt que de le lais­ser vaquer, lui ensei­gner des choses, éveiller son esprit, lui permettre et lui propo­ser de faire d’autres choses plutôt que de lui inter­dire de faire des bêtises, l’ac­com­pa­gner plutôt que de le sanc­tion­ner. La réus­site était d’au­tant plus écla­tante.

    Si vous avez eu un enfant, vous savez proba­ble­ment de quoi je parle. C’est évident pour tout le monde mais aussi telle­ment facile de se lais­ser entrai­ner dans la mauvaise boucle si on n’y prête pas garde. Parfois un peu de fatigue suffit.


    Non, ça n’a rien à voir.

    Ça n’a rien à voir mais je ne peux m’em­pê­cher de voir que toute une classe poli­tique inves­tit dans la réponse puni­tive, dans les mesures de protec­tion, de police et de contrôle.

    On s’étonne de géné­rer nos propres oppo­sants mais nous faisons tout pour éviter qu’ils aspirent à vivre ici et s’y sentent épau­lés.

    La défiance de la popu­la­tion envers la police est au plus haut depuis quelques mois. La défiance de l’ad­mi­nis­tra­tion envers les admi­nis­trés a atteint un point de non-sens total. La défiance des poli­tiques envers tout le monde et de tout le monde envers les poli­tiques ne date pas d’hier. Vu les décla­ra­tions de ces derniers après l’at­ten­tat de Nice, de l’aban­don assumé de l’État de droit à l’em­pri­son­ne­ment arbi­traire 24h/24 sans procès en passant par l’his­toire du lance-roquette, j’ai du mal à ne pas parti­ci­per moi-même à cette défiance géné­ra­li­sée.

    Certains diront que je vis chez les bisou­nours. Moi j’ai peur qu’ils veuillent faire ressem­bler notre monde à leurs peurs et leurs cauche­mars.


    AMENDEMENT N°17

    présenté par Mme Attard

    ———-

    ARTICLE PREMIER

    Suppri­mer cet article.

    EXPOSÉ SOMMAIRE

    Les chiffres du minis­tère de l’In­té­rieur et les rapports parle­men­taires ont démon­tré que l’état d’ur­gence n’a plus d’in­té­rêt au-delà des 15 jours initiaux déci­dés par le Président de la Répu­blique. De nombreuses audi­tions l’ont confirmé. Comme son nom l’in­dique, l’état d’ur­gence doit être réservé aux situa­tions d’ur­gence. C’est pourquoi il est néces­saire de suppri­mer cet article, afin de lutter effi­ca­ce­ment contre le terro­risme. Cette lutte doit passer par un accrois­se­ment des moyens finan­ciers et humains consa­crés à l’enquête de proxi­mité, à l’édu­ca­tion et à la justice. La suren­chère sécu­ri­taire et l’agi­ta­tion média­tique ne consti­tuent pas une poli­tique effi­cace.

    Merci. Merci d’es­sayer de faire vivre notre société, de la faire progres­ser, de penser au futur plutôt qu’au jeu média­tique.

  • Aldiko, Mantano, TEA, Bookeen et Pocket­book je vous propose un deal

    Aujourd’­hui encore, je ne peux pas char­ger un livre numé­rique sur une liseuse, lire un chapitre et espé­rer conti­nuer ma lecture sur smart­phone.

    Je ne demande même pas à envoyer mon livre dans un cloud ou à synchro­ni­ser des systèmes de lectures de vendeurs diffé­rents. Ce serait top mais je suis prêt à char­ger manuel­le­ment le livre sur tous les appa­reils avant de pouvoir en synchro­ni­ser les posi­tions de lecture, et je suis prêt à devoir télé­char­ger l’ap­pli­ca­tion asso­ciée à la liseuse.

    Visi­ble­ment, en 2016, rien que ça c’est encore de la science-fiction niveau inter­opé­ra­bi­lité.

    Certains écosys­tèmes savent bel et bien synchro­ni­ser les posi­tions de lecture entre diffé­rents appa­reils, mais unique­ment si vous ache­tez les livres chez eux. Côté inter­opé­ra­bi­lité c’est par contre service mini­mum.

    Les plus inter­opé­rables restent Apple et Amazon puisqu’à priori ils permettent de synchro­ni­ser les livres tiers et leurs posi­tions de lecture entre leurs diffé­rents appa­reils. Il faudra cepen­dant enle­ver les DRM au préa­lable, faire une conver­sion préa­lable sur Kindle et faire une croix sur la possi­bi­lité d’avoir une liseuse pour Apple (ouch). Apple et Kindle en exemple d’in­te­ro­pé­ra­bi­li­té… ça me fait mal quand même…

    Chez les autres, au mieux je peux char­ger manuel­le­ment mon livre sur chaque appa­reil indi­vi­duel­le­ment – et encore, parfois après conver­sion – mais certai­ne­ment pas profi­ter de la synchro­ni­sa­tion des posi­tions de lecture, et encore moins de la synchro­ni­sa­tion du livre lui-même.

    Et si on était sérieux cinq minutes ?


    Alors, Aldiko, Mantano, TEA, Bookeen et Pocket­book (*) je vous propose un deal.

    Je connais le sujet, les enjeux, les problé­ma­tiques, les fausses solu­tions, les parti­cu­la­ri­tés des diffé­rents maté­riels.

    Si au moins un éditeur de liseuse et un éditeur d’app mobile y sont prêts je veux bien défi­nir le proto­cole, aider à l’im­plé­men­ta­tion et même déve­lop­per la partie serveur sous licence ouverte. S’il y a deux inter­ve­nants diffé­rents je suis même prêt à monter une struc­ture asso­cia­tive pour que ce soit géré indé­pen­dam­ment d’un acteur parti­cu­lier.

    Ce peut tout à fait être un méca­nisme option­nel. L’in­te­ro­pé­ra­bi­lité est ma seule condi­tion.

    Tout est discu­table. Si nous en discu­tions ?

    L’ef­fort de déve­lop­pe­ment ne serait pas nul mais ce n’est pas non plus l’in­ves­tis­se­ment de l’an­née. Ce qui est certain c’est que sans un mini­mum de travail ensemble, ce sont toujours les mêmes qui vont conti­nuer à sortir leur épingle du jeu.


    Si, lecteur, vous soute­nez l’ini­tia­tive, lais­sez un commen­taire ici. Savoir qu’il y a une demande, même faible, peut toujours aider si des discus­sions s’en­gagent.

    (*) Je n’ai pas mis Kobo ou Google. Je n’ai ni les contacts ni l’es­poir qu’ils jouent le jeu. Si quelqu’un a des connais­sances là bas en réelle capa­cité d’au moins en discu­ter, qu’il n’hé­site pas à m’en parler pour voir ce qu’on peut imagi­ner.