Vite, un chtijug !

Je me demande si je n’ai pas déjà utilisé ce titre …

En attendant, hier soir, c’était chtijug spécial quickies.

HTTPS Everywhere avec let’s encrypt

Le HTTPS c’est mieux pour la confidentialité des utilisateurs. Let’s encrypt est une autorité de certification, dont le client essentiel est certbot.

certbot

Tourne sur n’importe quel Unix (oui oui). Il y a des plugins pour tous les serveurs web, même sur le Raspberry.

Démonstration avec un site Apache

S’ensuit une jolie démonstration avec des poneys en ascii-art. Et tant mieux, parce que certbot a une interface ncurses ! On note tout de suite les problèmes classiques liés à du https : le mixed content (images ou scripts chargés en http, …). Je note également le point « magique » de Let’s Encrypt : obtenir un certificat à la volée, c’est quand même vachement plus rapide que de le réclamer physiquement à un service de sécurité.

Validation du certificat

La partie intéressante de Let’s encrypt, c’est le mode de génération de certificat. Plutôt que d’utiliser la méthode traditionnelle avec échange de mail, ils reposent sur l’exposition d’un challenge en http sur le site pour lequel on veut un certificat. C’est assez malin, car plus facilement automatisable. Et j’imagine que certbot doit pouvoir automatiser ça

Démonstration avec nginx et webroot

Histoire de montrer les capacités de certbot, on refait la démo, mais avec une configuration manuelle, pour nginx.

Intérêt ?

Le certificat est renouvellé automatiquement tous les 90 jours ! Du coup, plus de problème d’expiration. Et ça, pour les noobs de la sécurité comme moi, c’est vraiment cool. Un point important à noter : Let’s encrypt ne fournit que des certificats de classe 1, donc avec une sécurité « moyenne ». Les classes 2 et 3 impliquent des vérifications physiques, qui sont évidement manuelles.

Point bonus : il y a une interface permettant de révoquer les certificats depuis le site de Let’s Encrypt, ce qui provoquera sans doute leur renouvellement automatique.

Ce que la revue de code m’a apporté

Julien commence par nous raconter sa vie de jeune développeur. Et, personnellement, je me reconnais mal là-dedans :

  • la fierté du code produit
  • la propriété du code (c’est le code de Julien)
  • Et enfin, il veut que son code soit beau longtemps

Du coup, ils ont mis en place chez Axa des revues de code avec des rôles identifiés pour limiter les procès en sorcellerie. Malheureusement, j’ai peur que ça ne suffise pas. Du coup, il faut apprendre plusieurs choses (qui, il me semble, font partie de l’expérience du développeur). La première étant évidement de faire preuve de bienveillance envers ses collègues, le fameux « dur avec le code, doux avec les gens ».

Axa consomme environ 5% de son temps à faire de la revue de code. C’est assez peu, vu que ça permet de détecter des bugs (en plus d’assurer une cohérence stylistique des livrables).

A priori, il faut environ 3 mois pour que les revues soient « apaisées ».

A la réflexion, il y a à mon avis quelque chose de complètement biaisé dans le fait que le développeur vienne présenter lui-même son code à un procès en sorcellerie. Il vaudrait sans doute mieux que le code soit défendu par un « avocat » sans que le développeur à l’origine du code puisse être reconnu. Parce que, comme je le dis toujours, le code qui est dans Subversion/Git n’est plus ton code, c’est celui de l’équipe. Et c’est ce qui le rend magiquement sale.

lunrjs

lunrjs est un portage de Lucene pour javascript, utilisé chez Decathlon. Et sur le site de Decathlon, actuellement, quand on change un filtre de recherche, la page est visiblement rechargée (ce qui n’est pas terrible en termes de performances). Un portage, mais un peu restreint, puisqu’on perd par exemple les recherches de termes approchants.

A noter qu’actuellement, le catalogue produits de Decathlon est hébergé en SAAS, ce qui est … osé, je trouve.

Cela dit, je n’ai pas trouvé ça si impressionnant. Parce qu’il existe déja des tonnes d’API javascript pour exploiter le local storage « correctement ». En fait, le seul intérêt de lunrjs, c’est de compléter les recherches disponibles dans Lucene pour les déconnexions, mais je trouve le cas d’utilisation assez rare pour ne pas investir spécifiquement dessus. A mon sens, travailler sur une vraie API client/serveur dans le navigateur permettrait plus facilement d’attaquer ce type de problème. Sauf, bien sûr, si l’objectif du projet est précisément d’étendre Lucene, mais c’est plus de l’ordre du patch que de l’évolution en profondeur.

Cerberus

Donc, cerberus est un outil de test fonctionnel automatique. Des outils comme ça, il y en a … déjà … des tonnes. Alors pourquoi La Redoute s’est lancée dans cette guerre des tranchées ? Comme d’hab, l’hubris (autrement dit « il n’existait pas de solution correspondant à leur besoin »). Cerberus se place donc entre les différentes équipes, pour fournir un référentiel commun. ce qui implique également que les tests puissent être décrits par les fonctionnels ou les développeurs. Et comme un outil comme HPQC, il offre tout un tas de fonctionnalités, comme le support multi-technologies, multi-langues, multi-environnements l’exécution adaptative des tests, la génération de rapports ou l’intégration dans les outils de développement du SI (IC, bug tracker, …).
Bon, j’avoue, j’ai décroché lors de la démo. Parce que vraiment, on est face à de l’outil de test fonctionnel très haut niveau, où les étapes peuvent être effectuées manuellement ou automatiquement. Ce qui ne m’inspire qu’une chose : ces outils ne sont pas faits pour le monde d’aujourd’hui, mais pour les bonnes grosses applications traditionnelles des entreprises qui ont encore des équipes dév, fonctionnelles, test, différentes, et des processus de livraison longs et lourds. Dans ce cadre, j’imagine que ça doit marcher. Mais dans le cadre hyper-mouvant du web de 2016, je ne suis pas sûr que ça bouge assez vite.

Conclusion

Je peux paraître un peu dur avec certains des talks, mais ça n’est pas mon but. Le contenu ne m’a peut-être pas autant intéressé que les orateurs l’auraient souhaité, mais ça n’ôte rien à leur prestation. Les quatre présentations étaient en effet bien préparées, construites, bien organisées. C’est juste que chaque auditeur met ses propres filtres sur les sujets qui lui sont présentés … Bravo encore au chtijug qui arrive toujours à trouver des choses intéressantes à nous présenter (eh oui, ça n’est pas parce que ça ne m’a pas plu que ça n’était ps intéressant).

Pas de chti jug sur Typescript pour moi

Ce soir, c’est chtijug sur Typescript. Et en plus, le lieu a l’air sympa.

Pas parce que je n’aime pas Cyril et ses amis, bien au contraire, je trouve le boulot du chijug vraiment chouette.

Mais plutôt parce que … comment dire … tout cet écosystème Javascript me fatigue à un point fou.

Je vous explique.

J’ai fait ma première page web avec du Javascript en 1999 … ou 2000. Bon, la wayback machine a une version datant de juillet 2001. Enfin bref. A l’époque, faire du Javascript était un sale boulot.

Heureusement, jQuery a tout changé. Et pendant quelques années, faire du web dynamique était raisonnablement simple conceptuellement et techniquement.

Et puis un jour, l’apocalypse de la sur-architecture s’est pointée sous les traits de nodejs. Je ne vais pas refaire l’article contre nodejs, parce qu’il suffit de regarder quelques twits de Mario Fusco ou Sam&Max pour comprendre

Et c’est quoi le rapport avec Typescript ?

Pour être honnête, Typescript n’est pas une solution, mais un élément du problème.

En effet, de mon point de vue, les langages modernes ont été créés pour permettre aux gens d’être plus productifs que l’assembleur ou le C, par exemple. Seulement, et au risque de choquer mes camarades Javaistes, le Javascript n’est pas ce genre de langage.

Non.

Comme l’écrivait Douglas Crockford il y a … un moment, le javascript n’est pas le langage qu’on croit. Et franchement, une fois qu’on comprend que le Javascript est un langage fonctionnel s’exécutant dans un environnement peu commode, il se passe une certaine épiphanie qui permet de mieux en comprendre la réelle simplicité. Une simplicité qui rend des monstruosités comme Angular, React, ou Typescript, aussi pratiques qu’un 38 tonnes en ville.

C’est aussi pour ça (en plus de ne pas assister à une conf sans doute intéressante sur un langage qui doit sans aucun doute avoir de bons côtés) que j’ai décidé de ne plus me lancer dans des projets front-end en utilisant autre chose que des bibliothèques simples (voire élémentaires) qui remplissent proprement une fonction simple et claire. Des outils comme

  • RequireJS
  • RactiveJS
  • jQuery
  • underscoreJS

Et sorti de là, comme disait il y a bien longtemps mon prof d’info, point-barre. Du coup, forcément, ce talk sur Typescript présentait un problème d’intérêt fondamental : comment diable pouvais-je m’intéresser à un langage dont la finalité actuelle est précisément de faire quelque chose qui me répugne au plus haut point ?

#devoxxfr – l’ISS sur mon portable

Comme le types algébriques est annulé (le speaker s’est perdu dans Devoxx), on passe tout de suite à l’ISS sur le portable d’Audrey Neveu.

Et à priori, il sera question d’ionic … déjà vu au chtijug il me semble. Et pour alimenter ionic, Audrey va utiliser streamdata.io (entreprise chez laquelle Audrey est évangéliste). Comme ionic est déjà vu, je vous le laisse de côté …

Cela dit, pour les données, il faut faire du temps réel. Pour faire du temps réel, on va semble-t-il prendre du server-side-events, solution sur laquelle se base streamdata.io. Et manifestement, c’est une solution qui fait tout un tas de trucs bien malins.

Et c’est parti pour le dev ionic/cordova/angular/streamdata/…
Et ça va très très vite jusqu’à la fin .. qui montre bien la position de l’ISS en temps réel.

Cela dit, je retiens évidement l’intérêt de streamdata (que je ne connaissais pas) et de ces server-sent-events. ca a l’air bien pratique pour faire de la notification en HTTP plutôt que de l’échange bidirectionnel façon websocket.

#devoxxfr Boucles de feedback du développeur

Et donc le but du talk, c’est de permettre au développeur de rester dans sa zone de concentration … en évitant les pertes de temps liées au redéploiement.

Donc pour être rapide, ils vont utiliser peut-être un tomcat en prod, mais surtout en jetty intégré avec maven, et c’est bien parce que ça démarre très vite. Et pour être honnête, j’ai personnellement déja joué avec le plugin maven-jetty-plugin et les scaninterval … Mais je n’avais pas réussi à lui faire prendre en compte les modifications de code source. Et puis, pour être honnête, on n’est pas encore au niveau de …. Wisdom \o/.

Alors avec maven-jetty-run on peut relancer l’appli. Mais pour les tests, on fait comment ? J’imagine qu’ils vont me parler d’infinitest … bingo ! C’est vrai que je sais qu’il existe depuis …. qu’Eric Lefevre en a parlé il y a bien longtemps.

Et c’est tout pour le serveur. Passons maintenant au client. Notez qu’encore une fois, quand je change mon code Javascript dans Wisdom, il est relinté, recompressé, et peut-être même retesté à la volée. Mais quand même … Il y a aussi des outils qui permettent de modifier le JS dans le navigateur, et de le voir modifié dans le projet source.
Avec Chrome dev tools, on peut créer des « workspaces » qui associent à des fichiers fournis en HTTP des fichiers sur le filesystem. C’est bien, parce qu’on peut directement bosser dans le navigateur avec tout son outillage, et avoir les modifications effectuées sur les fichiers source. D’un autre côté, avec grunt browserSync, on peut demander au navigateur de se rafraîchir. Et c’est assez génial, puisque la page web se rafraîchit très très très vite. Franchement, j’aimerais bien voir ça dans …. Wisdom ! En plus, browserSync, permet de synchroniser la navigation entre plusiurs navigateurs. Et évidement, c’est incompatible avec les workspaces : le workspace modifie le fichier, browserSync recharge la page, le workspace détecte à nouveau la modification, …

En bonus, côté Javascript, on peut aussi faire des tests avec Karma/Jasmine. Et on peut également mettre un watcher … du coup le test sera rejoué. Et pour ne pas regarder la console, Karma a un plugin growl … Ca, ça fait plaisir !

isomorphique de quoi ?

La semaine denrière, c’était chtijug.

Oui, je suis un peu en retard, mais c’est pas trop grave, parce que pendant ce temps, l’orateur a eu le temps de mettre ses slides sur internet.

Session un peu particulière, en particulier avec son titre assez … ronflant : « réalisation d’applications isomorphiques avec spring boot, React et Nashorn ».

En vérité, c’est beaucoup plus simple à décrire que ça : vous savez que votre JVM intègre, et depuis un moment, un interpréteur Javascript ? Non ? Eh bien c’est pourtant le cas, grâce à la JSR 223 (l’une des meilleures à mon avis), qui permet de lier sous une interface commune la plupart des interpréteurs pour la JVM. Ainsi, exécuter du javascript (grâce à Rhino ou Nashorn), du Python (grâce à Jython), du … Groovy (funky baby) ou même … oui, même … du Java interprété (grâce à Beanshell) est vraiment très facile.

Donc, la présentation de Sébastien utilise cette percée, et la disponibilité en masse de frameworks javascripts, pour remplacer le beaucoup trop vieux et trop moisi rendu JSP par un rendu fait grâce à mustache (que je connais bien grâce à Ractive) ou React. Je ne vais pas vraiment m’éterniser sur React, parce que franchement, le JSX, c’est la pire idée à laquelle je puisse penser. En revanche, conceptuellement, c’est assez élégant.

Je m’explique.

Quand vous faites votre application web, vous avez votre joli modèle Java bien typé. Et c’est bien. Mais, au moment où vous faites le rendu dans votre JSP (ou votre template thymeleaf si vous utilisez Wisdom, par exemple), vous passez dans le monde moche et pénible du string typed. Tout est string, et vos objets Java n’ont plus d’autres intérêt que d’e^tre des struct capables d’émettre du String. Et dans ce cas, passer par du Javascript … n’est pas idiot. Parce que le travail énorme réalisé dans le monde du javascript ne se contente plus du client. Et que node.js reste une assez piètre idée, assez peu scalable. Du coup, joindre le meilleure du Java (le modèle, les capacités de traitement d’entreprise) au meilleur du javascript (tous ces outils de templating conçus par et pour le web) est vraiment chouette.

D’ailleurs, ça me donne des idées à propos de ractive/requirejs/Wisdom (mon trio de choc). Des idées qui n’attendent plus que deux choses

  1. Facile : le fameux bout de code transformant un require() en chargement de ressources depuis le CLASSPATH (d’après ce que j’ai compris, Sébastien travaille dessus)
  2. Moins facile : passer un template HTML plutôt que Javascript. Parce que s’il est question de rendu isomorphe, j’aimerais autant que ce soit le même fichier qui soit rendu de la même façon (ou presque) côté client et côté serveur.

Ce soir, c’est service workers, mais sans moi

Hélas, je ne suis pas au chtijug ce soir, et c’est bien dommage, parce que les service workers, ça m’a l’air bien intéressant. J’essayerai de chopper la présentation d’Hubert demain …

Et pourquoi je n’y suis pas ? Parce que je ferai demain une démo d’une application développée avec Wisdom, JCR, requirejs, Ractivejs, jQuery et Bootstrap. Tout ça a l’air d’une hypitude révoltante, c’est vrai, mais en fait c’est beaucoup plus simple  manipuler que ce qu’on croit. Si je voulais faire un rapide bon/pas bon, je dirais (même si vous le savez déja)

Bons côtés

  • Grosse productivité du live-reload de Wisdom incluant évidement les modifications du Javascript, du HTML, et même du POM
  • RequireJS est toujours aussi pratique pour ajouter des librairies Javascript sans se poser la question de la page dans laquelle ce Javascript est inclus … ou pas.
  • RactiveJS permet vraiment de faire facilement des interfaces modernes (surtout quand les templates Mustache sont chargés séparément via RequireJS).

Mauvais côtés

  • L’implémentation de wisdom-JCR interdit le live-reload. Et même si je suis en contact avec les développeurs de cette extension, c’est vraiment moche.
  • Dans le même ordre idée, avec wisdom, il ne fut jamais mettre un objet Java en cache, parce que quand on le charge après un reload, ce n’est plus le même objet Class, et du coup ça fait tout planter.
  • J’ai eu besoin de générer des images à partir de ppt/pttx. Eh bien curieusement, il n’y a aucune librairie qui ait vraiment le niveau pour faire ça de façon professionnelle.

Les mauvais côtés ont quand même bien failli tuer ce projet. Heureusement, ils ne l’ont pas encore tué … On verra demain soir.

Uploader un fichier en ajax sur un serveur Wisdom

Je pose ça là pour bien être sûr que j’ai bien tout essayé.

Donc, j’ai un scénario assez basique : dans une popup, écrite avec du Ractivejs/Bootstrap, j’ai un formulaire avec lequel je veux pouvoir uploader un fichier sur mon serveur écrit en Wisdom. Facile, non ?

Sauf que pour l’instant, ça ne marche pas.

Tout le code est dans ce gist (que WordPress ne semble vouloir inclure via ses smartcodes)

Le formulaire HTML semble correct. Et le javascript a l’air tout aussi normal.

En bonus, quand je passe en mode debug, j’arrive bien dans la bonne méthode de Wisdom.

Du coup, je jette un oeil à l’onglet network de Chrome, qui me donne ces infos

2015-05-24 10_41_46-p

Et là, si je ne me trompe pas, ça semble vouloir dire (en particulier, par exemple, Content-Length:44) que le fichier que je veux envoyer n’est pas là.

OK, donc c’est un problème côté client …

Et en fait, c’est une sale histoire entre jQuery et FormData. Ca me soulage : j’ai eu peur que Wisdom soit de la partie. Il me reste maintenant à corriger ce problème de Javascript … Qui se corrige en remplissant le Formdata avec le contenu de fileInputChooser.

Comme ça :

var file = $('#fileInputChooser')[0]
var formData = new FormData();
// Seems like auto-loading a FormData from a form do not work that well ... crap !
formData.append("fileInputChooser", file.files[0])

Ionic framework ?

Eh mais la semaine dernière, il y avait …

Et je n’en ai pas encore parlé ? C’est MOCHE.

Donc, ionic framework …

pour lequel Loïc fournit les slides :

Comme ça, je n’aurais pas à vous résumer le truc, mais juste à donner mon avis.

Ionic est donc une surcouche d’Apache Cordova pour y faciliter l’intégration d’AngluarJS et d’autres trucs. Ca permet de faire facilement des applis hybrides pour mobiles.

Les applis hybrides étant, pour ceux qui ne le sauraient pas, des applications web packagées pour ressembler aux applications système.

Au passage, un petit tacle à ceux qui croient que c’est moche : les jeux de chez Wargaming utilisent ce type d’application pour les garages de World of Tank/Warplanes/Battleships. Et pourtant, ça ressemble assez peu à un site web, il me semble. Donc dire que l’hybride est forcément une mauvaise solution me paraît un peu abusif.

Bref. On retrouve donc avec Ionic la possibilité de construire une appli mobile en web. Et, malheureusement, avec Angular. je dis malheureusement, parce que franchement, angular me sort autant par les yeux que JSF, et c’est pas peu dire.

Cela dit, la présentation était sympa.

J’ai même été particulièrement bluffé par l’intégration de Firebase. Je savais que cette base de données « as a service » existait. Mais je ne savais pas que c’était aussi chouette. Tellement que ça a éclipsé dans mon esprit toutes les idées du genre « mais pourquoi ne pas remplacer angular par Ractive ? »

Donc, une présentation réussie, mais pas pour son sujet principal.

Après deux mois de Javascript, on se sent comment ?

La question peut paraître … curieuse. Elle n’en demeure pas moins valide : quand on est comme moi un développeur Java un peu expérimenté, et qu’on passe d’un coup à ce langage aussi ubiquitaire que malaimé, qu’est-ce qui surprend ? Qu’est-ce qui étonne ? Qu’est-ce qui déçoit ?

J’ai vu des choses …

Avant d’aller plus loin, une petite mise au point. Je ne vais pas vous parler du dernier projet à la mode de lad ernière startup qui démarre. Non. J’ai fait du Javascript ces deux derniers mois pour la même raison qui m’avait forcé à faire du Flex pendant trois ans en pointillés sur le même projet : si vous voulez faire une extension pour indesign CC 2014, vous n’avez pas vraiment le choix, vous devez faire du HTML+Javascript. Alors du coup, je ne vais pas vous parler de Javascript qui communique avec son serveur via HTTP, mais de Javascript qui communique avec une extension Java/C++ via le système de communication créé par Adobe. Et, il faut le dire, Adobe fait des choix techniques … surprenants (j’y reviendrais).

En dehors de ces contraintes techniques spécifiques, l’application sur laquelle j’ai bossé n’a pas vraiment de spécificités. Enfin, pas trop 🙂

Alors, grunt, bower, npm ?

hrm hrm …

Je vais essayer d’expliquer ça de façon claire, même si ça va choquer.

Le projet pour lequel on fait cette interface est un projet multi-module de taille « moyenne » : 32 modules différents, compilant et générant tout un tas d’artefacts. Est-ce que j’allais introduire dans ce gros paquet de modules, et dans mon Jenkins, un autre outil, ou plutôt ensemble d’outils ? Non. Je voulais (peut-être de façon dogmatique) que cette interface soit packagée par maven.

Tester du JS dans maven, c’est possible ?

A la lumière de mes expériences avec Wisdom, je me suis dit que j’allais jeter un oeil à frontend-maven-plugin histoire de profiter de ses fonctionnalités (en particulier les tests). Mais, curieusement, je n’ai pas réussi à lui faire faire quoi que ce soit. Alors j’ai arrêté de faire le mariole, et j’ai dit à l’un de mes collègues de faire un système de test Javascript à base de Fluentlenium (qui est devenu pour une raison que j’ignore du Selenium pur et dur) et de JunitParams.

Autrement dit, pour chaque test Javascript, on crée un fichier HTML le chargeant via requirejs (j’y reviendrai) et on récupère grâce à Selenium le résultat du test via un peu de Javascript. Ca pique un peu les yeux la première fois, mais ça marche en fait très bien (même si tester du code asynchrone avec Jasmine est un peu compliqué).

Et les dépendances ?

Bon, évidement, comme notre projet n’utilise pas HTTP, nos dépendances Javascript (pour lesquelles Webjars rempalce très avantageusement NPM) nécessitent un peu de travail, essentiellement pour faire une translation de chemin qui les rende facilement utilisables.

Je m’explique.

Notre projet a (par exemple) ces dépendances :

		
	<dependency>
            <groupId>org.webjars</groupId>
            <artifactId>requirejs</artifactId>
            <version>2.1.14-3</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>requirejs-text</artifactId>
            <version>2.0.10</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>log4javascript</artifactId>
            <version>1.4.9</version>
        </dependency>
		

Comment je fais pour utiliser log4javascript sans m’emmerder à mettre son numéro de version partout ?

Parce que, par exemple, avec Wisdom (désolé de prendre cet exemple de façon systématique, mais son utilisation m’a appris quelques trucs vraiment chouettes), je n’ai pas besoin de mettre le numéro de version grâce au WebJarController.

Eh bien c’est … assez compliqué, et ça se fait en plusieurs étapes

  1. On a un script groovy (encore merci à gmaven) qui nous permet de créer pour les dépendances Javascript des propriétés maven. Les artefacts mentionnés me donnent donc les propriétés org.webjars:requirejs:javascript:require, org.webjars:requirejs-text:javascript:text et org.webjars:log4javascript:javascript:log4javascript qui deviennent faciles à inclure dans un <script src="${org.webjars:log4javascript:javascript:log4javascript}"></script>
  2. Le même script maven crée également une grosse variable ${requirejs.dependencies.compile.paths} qui sera bien utile pour générer le shim de requirejs.
  3. Et tous nos artefacts javascript sont dézippés grâce à amven-assembly-plugin pour générer l’application.

Alors évidement, toutes ces technologies sont infiniment moins hypes que les build tools Javascript, mais elles nous permettent d’intégrer proprement des dépendances Javascripts dans notre build et ça, ça fait plaisir.

Et requirejs, c’est vraiment bien ?

Vous allez rire (ou pas), mais pour l’instant, deux choses ont été embêtantes (mais résolues)

  1. Si vous chargez tous vos scripts avec le protocole file://, vous serez limités par la longueur maximale des chemins de Windows. Et si vous avez des gros chemins, par exemple pour des classes Java dans des packages profonds pour lesquelles vous générez des stubs Javascript à l’aide de flexmojos (essentiellement parce que GraniteDS intègre un super générateur pour les entités et les services – et ne me demandez pas comment je transforme mes fichiers .as en .js), eh bien vous allez pouvoir vous amuser à écrire un algorithme de translation de chemin et un plugin amven (ou un script gmaven) pour copier les bons fichiers aux bons endroits au bon moment (parce que amven-assembly-plugin est clairement dépassé, là).
  2. Et si vous avez des dépendances en scope compile et d’autres en scope test, ça ne posera pas vraiment de problème à requirejs, mis à part bien sûr qu’il faudra distinguer le data-main de l’un et de l’autre.

Mais dans l’ensemble, require me réconcilie vraiment avec le côté « packageless » de Javascript. Je n’ai pas besoin de faire ces fameuses fonctions anonymes auto-appelées. Je déclare chacun de mes fichiers presque comme je le ferais en Java, et tout (ou presque) est explicite. Le fait de travailler dans un environnement contrôllé donne un sentiment de sécurité asssez plaisant, et des fichiers déclarés selon une syntaxe vraiment agréable.

Et Ractive, c’est pas du flan ?

Ce qui est assez marrant, c’est que plus je m’en sers, moins je comprends les mecs qui font de l’angular (oui, ça sonne comme du bashing, mais c’est plutôt de l’incompréhension).

Il nous a été assez facile d’écrire des composants pas forcément triviaux, et à chaque fois qu’on se dit que Ractive pose un problème, il s’agit en fait d’un problème entre la chaise et le clavier (une erreur ID10T comme dirait mon collègue).

Et le fait de ne pas s’embarasser d’une gestion du modèle nous a permis d’utiliser ce fameux protocole de communication Adobe sans « trop » de problèmes.

Ah bon, alors vous faites pas de JSON ?

J’ai dit protocole, je n’ai pas dit format d’échange.

En fait, on utilise du JSON, mais sans passer par la librairie JSON fournie par Adobe (et je vous conseille de faire de même parce que cette librairie est buggée).

En revanche, échanger du JSON entre du Java et du javascript pose une question sérieuse : on part d’un monde typé, dans lequel chaque objet peut avoir des méthodes associées, méthodes pour lesquelles on aimerait bien disposer d’équivalents en Javascript. Par exemple, l’un de nos objets doit s’afficher en utiliser le resourceBundle fourni, on a donc envie de mettre la méthode dans le fichier Javascript généré par Flexmojos (pas de panique, Flexmojos en génère en fait deux : un qui sera réécrit à chaque build pour contenir les champs définis par le Java, et un autre généré une seule fois, dans lequel on peut ajouter notre code).

Mais comment fait-on pour que le JSON reçu du Java s’interprète non pas sous forme de hash anonyme, mais grâce à notre classe ?

Eh bien là, c’est vraiment compliqué :

  1. On demande à Jackson d’envoyer les informations de type dans le flu JSON grâce à son système de déserialisation polymorphe (on a utilisé jsonMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_OBJECT))
  2. Du coup, côté Javascript, on récupère des hashes qui associent à une classe le hash correspondant à l’objet, et là, c’est l’enfer : on a dû écrire un système qui « unmarshalle » ces hashes anonymes pour retourner des instances des classes Javascript correspondant aux aux classes Java. Et comme ça passe par require, il faut faire ce truc qui fait toujours peur : du code récursif asynchrone. Heureusement que Deferred est là, parce qu’il me semble que de tout le code Javascript, c’est la partie la plus compliquée que j’ai eu à écrire. Un enfer, je vous dit
  3. Ah, et en bonus, il ne faut pas oublier le code inverse : celui qui va prendre des objets Javascript ou des hashes anonymes pour créer de beaux obejts Java à l’autre bout du fil … Pas gagné.

Tiens, d’ailleurs, c’est le moment idéal pour vous rappeler que, comme les maps javascript n’ont pas de clés non string, ça ne peut pas être le cas non plus pour le JSON. Alors comme vous ne voulez pas réécrire tout votre code serveur pour votre nouveau client moderne, eh bien vous aller devoir vous taper la (dé)sérialisation des maps sous forme de tableaux de tableaux … Bon courage 😉

Autrement dit, comme d’habitude, la couche de communication va vous plonger dans un enfer sans nom, et surtout sans aucune raison valable.

Oui mais alors, le fait que ce soit pas compilé, qu’il n’y ait pas vraiment d’objets, c’est galère ?

Pour être honnête, oui.

Et pour être encore plus honnête, c’est pas trop grave.

Parce qu’en fait, il s’agit vraiment d’une interface HTML/Javascript : la partie complexe de l’application est bien au chaud, dans du code Java qui est correctement testé, qui a été écrit de façon à être raisonnablement robuste et qui est surtout déja utilisé en prod, donc qui a passé l’épreuve du feu.

Du coup, même si on galère parfois sur des histoires de types, ou de paramètres manquants/mal typés que Javascript ne voit pas parce que ça n’est pas son problème, ça n’est pas vraiment dramatique.

Et donc tu referais sans hésiter la même chose en plus gros ?

A dire vrai, mon Wiko a une version portable de Firefox qui fait fonctionner Ractive sans problème (comme Chrome, d’ailleurs). Alors du coup, demain, si je dois développer une application web, je peux vous assurer que le serveur se cantonnera à envoyer du JSON à mon client require/Ractive qui me fera, lui, une chouette interface.

Au passage, le bonus caché de Ractive, c’est que la philosophie est vraiment très proche de celle des web components, ce qui est loin d’être avantage mineur.

Eventuellement, j’ajouterais un coup de Facebook Flow pour valider mon code, et peut-être aussi que j’utiliserais plus frontend-maven-plugin pour minifier et toutes ces sortes de choses, mais dans l’ensemble, je comprend mieux ces histoires de microservices : si le client peut s’occuper d’aggréger et de présenter les données, pourquoi s’embêter à utiliser toute la pile JavaEE là où Wisdom suffit largement ?

Procrastination ?

Le terme pourrait venir à l’esprit, si vous pensiez par exemple que j’ai la flemme d’écrire quoi que ce soit sur ce blog.

Et, en un sens, ce serait vrai.

Parce qu’il n’y a pas grand chose à se mettre sous la dent, il faut le dire.

D’un autre côté, je ne rends pas compte de grand chose, peut-être parce que, pour l’instant, je construis …

Enfin, je construis, façon de parler.

J’ai déja dit que je faisais pas mal de Javascript en ce moment. Je devrais plutôt dire que je ne fais que ça. Et, en un sens, je prends un pied conséquent à jouer avec la pile construite pour l’occasion.

Parce qu’il s’avère (essentiellement grâce au duck typing), qu’il est d’une simplicité terrifiante d’y faire rentrer des ronds dans des carrés, et de mélanger plus ou moins proprement des paradigmes objets et fonctionnels.

Tiens, je vais vous donner un exemple un peu tordu.

Vous avez entendu parler des Deferred en javascript ? Non. Bon, je ne vais pas vous expliquer ça plus avant qu’en vous disant que ça revient à pouvoir dire à du code Javascript « quand on te dit go, tu go ». Je ne vais pas non plus rentrer dans la polémique des Promises/A vs Promises/B.

Non.

J’avais ce matin un problème bizarre.

Je voulais utiliser l’API de jQuery Deferred pour avoir une espèce de Deferred réexecutable. Il s’avère, et je le comprend tout à fait, que ça n’est pas possible. Parce que le Deferred, une fois qu’il s’est exécuté, est tout bonnement terminé. Je me suis donc creusé la tête un moment avant d’écrire mon petit module requirejs qui me fournit la classe qui va bien :

Evidement, ça n’a pas l’air de grand chose. Mais là, grâce à ce « truc », j’ai toute l’API de Defferred qui m’intéresse, et je peux créer le « vrai » objet sans problème.

Je dois bien reconnaître que c’est bien plus simple que d’implémenter une interface, ou quoi que ce soit d’aussi compliqué.

Alors, procrastination ? Sans doute, dans la mesure où ce code est fondamentalement asynchrone 🙂