Utiliser PlantUML dans la preview Asciidoc de VS Code

Oui, parce que vendredi, j’ai craqué.

Malgré la haine persistante que j’ai pour l’idée d’installer un navigateur web et un serveur Node.js pour éditer des fichiers textes, j’ai enfin installé l’un de ces « nouveaux éditeurs de texte ».

Et comme Windows, c’était mon idée, j’ai choisi le pire de la world company : Visual Studio Code. Dans l’ensemble, c’est pas trop mal. Mais parfois, ça surprend. Par exemple, il y a une chouette extension pour faire de l’asciidoc dans Code. Mais elle utilise asciidoctor-js et ne supporte donc pas asciidoctor-diagram. Comment changer ça ?

Facilement (ou presque).

D’abord, installez ruby et asciidoctor-diagram (il installera automatiquement asciidoc).

Ensuite, dans vos paramètres de Visual Studio Code, ajoutez (merci à ce ticket)

// make sure Asciidoc extension shows diagrams !
"AsciiDoc.use_asciidoctor_js": false,
"AsciiDoc.asciidoctor_command": "asciidoctor -r asciidoctor-diagram -o-",

Redémarrez votre VS Code

Et vous pourrez mettre du PlantUML dans vos fichier asciidoc et avoir des previews comme ça.

2018-05-14 11_24_54-● configuration.adoc - Sans titre(Espace de travail) - Visual Studio Code

Par contre, vous n’aurez pas de coloration syntaxique du contenu PlantUML, bien qu’il existe également une extension VS Code pour ça. Et là, à mon avis, en utilisant un include asciidoc, on doit pouvoir marier le meilleur des deux mondes …

Publicités

Devoxxfr – java.lang.Invoke

Finir Devoxx avec Rémi, c’est toujours cool.

On va s’intéresser aux loggers quand ils ne loggent pas. Et plus précisément quel est le coût d’exécution d’un logger qui ne logge pas ? Avec JMH, on a le résultat : ça prend 1 ns avec log4j2.

Et avec une lambda ? Ou un logger.isDebugEnabled() ? Ca prend autant de temps.

Normalement, le logger.isDebugEnabled() est un ensemble d’appels à des valeurs constantes. Et ça prend du temps parce que …​

La JVM ne croit pas que les champs final sont des constantes.

A cause de la …​ (de)serialization !!! Autrement dit, comme la JVM peut (dé)sérialiser tous les champs final ne peut pas inliner leurs appels.

java.lang.invoke

Avec cette API, on peut appeler du code dynamiquement d’une façon plus efficace que l’introspection pour plusieurs raisons :

  • Mise en cache de la sécurité
  • Pas de boxing

L’API est plus riche pour implémenter des langages. Elle est utilisée pour les lambdas, et pour la concaténation de chaînes de caractères en Java9.

Avec cet API on crée un MethodHandle qui est une espèce de pointeur de fonction. Il permet aussi de faire de l’invocation partielle. Et l’élément sur lequel il sera bindé sera considéré par le JIT comme une constante. En plus, il permet d’ajout des arguments qui ne seront pas passés à la méthode. Et de créer des MethodHandle vides ou de placer des gardes sur le MethodHandle.

Avec tout ça, Rémi recréée son Logger en utilisant exclusivement des MethodHandle. Le code est verbeux, mais on sent bien qu’il est particulièrement optimisé.

Bon, ça marche pas aussi bien que prévu. Allons donc voir le code source …​ de la JVM !

Le seul cas qui soit exploitable, c’est celui des classes anonymes (au sens de la JVM, pas du langage). Et ces classes anonymes au sens du langage sont les lambdas.

Ca marche bien.

Allons voir plus loin.

Avec une simple boucle et un logger.debug(…​) mais cette fois-ci avec log4j, on se retrouve avec des temps d’exécution différents là où il ne devraient pas être différents. Le tout à cause d’un volatile dans log4j. Ca amène Rémi à nous parler de SwitchPoint.

Et tout ce code est dans le projet Beautiful Logger. Qui lui est capable de ne pas logger sans consommer de temps CPU. En utilisant les mêmes techniques, Rémi a créé un projet de classes exotiques.

Mon avis

Je savais que ça allait dépoter, et je n’ai pas été déçu. Rémi nous en a mis plein la tronche avec des phrases qui se retrouveront sur son compte Twitter (ça n’est pas vraiment lui qui twitte).

Devoxxfr – A brief history of API

Vous pouvez retrouver les slides de la présentation sur Google Drive.

Pourquoi ?

Parce qu’un juge fédéral lui a demandé quand les API sont apparues dans l’histoire.

Quand sont apparues les API ?

Le terme subroutine a été inventé à l’époque de Von Neuman par celui-ci et un collègue. Ils expliquent dans la publication où apparaît le terme que les programmes se décomposent en opérations simples et réutilisables. Ce qui est curieux, c’est que Wilkes a reçu un prix Turing pour une idée similaire …​ mais surtout pour l’avoir implémenté. La machine utilisée était EDVAC, un énorme ordinateur de 1949. 1 million de fois plus lent que nos ordinateurs, avec 512 séries de 17 bits de mémoire …​ Et tout un tas d’autres éléments qui montrent à quel point il était rudimentaire. Et il a réussi à aller plus vite que Von Neuman en créant un ordinateur plus simple. Plus simple, mais qui a été mis à jour plusieurs fois. En codant son premier programme, Wilkes se rend compte qu’en l’état, il devrait corriger ses erreurs pour le reste de sa vie. Pour éviter ça, il demande à un de ses doctorants de travailler sur une architecture de sous-routines. Son code supportait de multiples niveaux de sous-routines, le passage de fonctions comme arguments.

Le concept a été introduit dans le premier livre sur la programmation : « The preparation of programs for an electronic digital computer« .

Et dans l’article présentant leur bibliothèque, ils expliquent aussi le besoin de debugger (qui fonctionnait sur leur ordinateur !). Il y explique également que la documentation de ces sous-routines est peut-être la tâche la plus complexe. Tout ça dans un papier de seulement deux pages !

Pourquoi Wilkes et Wheeler ne parlaient pas d’API ? C’est simple : il n’y avait qu’un ordinateur. Donc ils n’avaient pas besoin d’interagir avec d’autres ordinateurs. Par contre, quand ils ont recodé leurs fonctions dans la version améliorée d’EDVAC, ils ont donné vie à la notion d’API.

Par contre, le mot semble être apparu en 1968. Ils comprenaient bien que l’API avait un sens au-delà de son implémentation. Mais aussi que les API apparaissent dès qu’il y a une bibliothèque de code. En quelque sorte, elles en sont une propriété émergente.

Qu’est-ce qui constitue une API ?

Une API est ensemble de fonctionnalités indépendantes de leur implémentation, afin de permettre des implémentations variables.

Quelques exemples

  • L’API Fortran créée en 1954 contenait 28 fonctions mathématiques …​ et est toujours une partie de l’API standard de ce langage.
  • Kernigham & Ritchie écrivaient dans la doc du C que leur API doit être portable, afin de permettre aux programmes de s’exécuter sur de multiples plateformes sans changer le code. Comme Java, en fait.
  • Sur les terminaux VT100, une API permettait de se déplacer sur l’écran. La même qui est encore utilisée dans les émulateurs de terminaux modernes.
  • Le bios d’un PC fournit des API pour communiquer avec le hardware.
  • Dans un téléphone portable, le processeur central parle au processeur radio en utilisant l’API des modems.
  • Adobe PostScript pose la question : est-ce un langage ou une API. Autrement dit y a-t-il une différence entre un langage et une API ?
  • Sur le web, des sites comme delicious fournissent des API web qui permettent de les utiliser.

Qu’en retenir

Les API viennent en multiples formes. Elles sont éternelles. Elle peuvent créer des industries entières. Et enfin elles sont les moyens pour un composant d’un système informatique pour en utiliser un autre. Elles sont la glue qui tient le monde numérique.

Petite digression légale

On a toujours pu réimplémenter les API d’autres fournisseurs. Et chacun des exemples présentés a donné lieu a des réimplémentations. Même l’EDSAC a été réimplémenté, en 1959, au Japon !

Evidement, depuis le proccès Oracle/Google, les API sont sous la menace légale.

Si Oracle gagne, il ne sera plus possible de réimplémenter une API. Ou tout au moins, il faudra l’accord de l’auteur initial. Des produit comme GNU, Wine, Android, Samba, …​ ne pourraient pas exister.

Autrement dit, le droit de réimplémenter des API est crucial pour de multiples raisons.

Conclusion

Les API existent depuis toujours, et sans ça, l’informatique n’existerait pas. Et ce serait bien de leur permettre de continuer à exister.

Mon avis

Du début à la fin, la présentation était excellente. Vive, bien menée, claire dans son propos (qui est avant tout une histoire de l’API), c’était vraiment une bonne façon de rentrer dans le sujet.

Devoxxfr – Lazy Java

Mario vient nous parler de la progammation lazy, fortement utilisée en programmation fonctionnelle, mais rare en style impératif. Qu’est-ce que c’est ? C’est une stratégie d’évaluation qui fait en sorte que la valeur ne soit calculée que quand elle est utilisée. En programmation fonctionnelle, une fonction stricte évalue ses valeurs immédiatement, quand une fonction lazy évalue ses valeurs uniquement quand elles sont nécessaires.

Et donc, globalement, Java est un langage strict …​ A quelques exceptions près (les opérateurs booléeans, l’opérateur ternaire, certaines structures de contrôle, et les streams). Mais on peut rendre Java beaucoup plus lazy. Ca rend par exemple l’opérateur ternaire difficile à remplacer par une fonction …​ sauf en utilisant des lambdas (en l’occurence les Supplier<T>). C’est utilisé dans les apis de log modernes, par exemple (voir dans log4j 2).

Et franchement, c’est une sacrément bonne méthode d’optimisation : rien ne va plus vite que de ne pas appeler le code !

Et les streams utilisent ça : on peut créer un stream d’entiers infini : IntStream.iterate(1, i → i+1). Et du coup, un stream, ça n’est pas une structure de données, mais la spécification de données qu’on peut obtenir. Et grâce à ça, l’aspect lazy du code des streams permet la séparation des responsabilités. Et pour Mario, c’est cet aspect, plus que la compacité du code, qui rend les streams utile.

Et là, Mario nous sort un exemple de calcul de nombre premiers classique d’abord, puis récursif avec un head et un tail sur la liste des nombres. Cet exemple ne marche pas …​ Parce qu’un stream ne peut être terminé qu’une fois. Et que sa récursion n’est pas lazy, du coup, pouf, une boucle infinie ! Alors qu’en Scala, il y a une lazy concatenation (l’opérateur #::) qui aurait permis au premier exemple de marcher.

Donc, Mario recrée une liste lazy à base de head/tail et de Supplier<T>. Et je comprend à peu près comment ça marche ! L’explication graphique du code mérite vraiment d’être vue.

Et pour les afficher, on peut utiliser une itération externe ou interne. Et sur sa collection magique, on peut aussi (et surtout) utiliser la récursion. La récursion, c’est pratique. Mais en Java, ça peut conduire à des StackOverflow. Parce que Java n’implémente pas la tail call optimization, qui permet des récursions infinies en enlevant certaines méthodes de la pile d’appel. Et Scala l’implémente également, bien sûr (par contre il faut annoter les méthodes où on veut l’appliquer).

Par contre, la tail recursion ne marche que si la méthode récursive est appelée en dernier.

Heureusement, on peut utiliser la technique des trampolines pour permettre cette récursion infinie. En fait, le trampoline, c’est une manière de transformer une récursion en une suite d’appels de méthodes, à grand coups de Supplier<T>.

Et pour finir, Mario se propose de nous implémenter de l’injection de dépendances lazy. Et honnêtement, qund il fait la liste des défauts de l’injection de dépendances classique, ça fait peur.

Et pour ça, il introduit la monade Reader qui est une façon commode d’invoquer une fonction dans un contexte.

Et ça marche d’une façon très chouette, voire même lisible.

Conclusion

L’approche lazy, c’est quand même la meilleure des optimisations parce que ça permet de n’exécuter que le code vraiment utile. Par ailleurs, la démarche fonctionnelle apporte souvent des intérêts en remettant au moment de la compilation des comportements qui doivent y être traités.

Mon avis

j’avais déja vu sur Twitter les slides de Mario, je crois, ou au moins une partie, que je n’avais alors pas parfaitement compris. Avec la présentation en live, j’ai beaucoup mieux compris, et j’ai pris une claque. C’est vraiment chouette.

Devoxxfr – Les exceptions, oui, mais pas n’importe comment

Evaneos est une boîte d’une dizaine d’années, avec un code qui a le même âge. Charles a mené des campagnes de refactoring pour faire évoluer le code, et a beaucoup lutté contre les exceptions. Dans la plupart des systèmes, les exceptions sont simplement loggées. C’est une traduction de l’exception, et ça peut ne pas être bonne idée. Et ça pollue les logs. En bonus, quand les logs sont émis en critique, ils génèrent des alertes (et déclenchent potentiellement des astreintes et de la fatigue). Donc, il faut utiliser le bon niveau de log. De la même manière, attraper toutes les exceptions sans détail, ça peut avoir des effets indésirables. Donc, il vaut mieux traiter les exceptions de façon indépendante. Mais ça fait vite beaucoup de code. Et n’hésitez surtout pas à traduire les exceptions d’un contexte à l’autre, pour les rendre compréhensibles par les utilisateurs de votre code.

Mon avis

Je m’attendais à plus de cette présentation. Mais si elle a marché, c’est qu’il y a du public, et donc qu’on peut faire mieux.

Devoxxfr – Quand une documentation devient un problème (et que faire alors)

D’abord, la doc, il faut en écrire, mais il ne faut pas répondre RTFM aux utilisateurs.

Chez Criteo, ils ont donc une stack classique : Jenkins, Gerrit, Perpetuo/Rundeck, …​ Avec de la doc (environ 250 pages dans Confluence) raisonnablement bien faite : de la doc utilisateur, de la doc de référence.

Pourtant, chaque jour, il y a des utilisateurs qui posent des questions sur Slack …​ qui ont déja la réponse dans la doc. Parce que les utilisateurs ne lisent pas la doc. D’ailleurs, la FAQ non plus n’est pas lue.

Et quand les gens lisent la doc, parfois ils n’y croient pas. Ou alors ils la dupliquent. Et c’est mal. Et enfin, elle n’est jamais assez bien écrite.

Comment éviter ça ? Benoît essaye d’arrêter d’écrire de la doc. A la place, il fait en sorte que les outils soient simples à utiliser. Et pour ça, si il faut supprimer des fonctionnalités …​ il les supprime. Par ailleurs, donnez immédiatement l’information utile, sans passer par des intermédiaires. (par exemple, pas de « allez voir dans les logs de machin », mais un lien direct vers « les logs de machin »). Il met aussi en place des interfaces dédiées aux différentes catégories d’utilisateurs.

Enfin, supprimer les exceptions ! C’est-à-dire faire en sorte qu’il n’y ait pas de cas exceptionnels.

Autrement dit, la documentation utile, mais elle a un coût d’entrée et de maintenance. Si il faut expliquer un outil c’est qu’il faut le simplifier.

Mon avis

C’est bien de montrer que la doc révèle souvent un manque dans la conception de l’interface d’un logiciel. Mais il y a en revanche des cas où elle reste utile. Et dans ces cas-là, on fait quoi ?

Devoxxfr – Clean architecture

Partons d’une application qui récupère des exemples sur Internet. En Android, on va faire une sale activité, et même une seule classe. Pour refactorer l’application, on commence par appliquer les principes SOLID. Et également par la rendre testable.

Au bout d’un moment, on se retrouve avec du MVC ou MVVM (selon qu’on soit sous Android ou iOS)

Keskecé

Le concept de clean architecture, c’est d’isoler la logique métier en appliquant les patterns classiques (architecture hexagonale, DDD, …​).

Principes

  • Indépendant des frameworks
  • Définir un bon découpage métier (en particulier, définir des packages selon les fonctionnalités métier, plutôt que selon les fonctionnalités techniques)
  • Testable

Avantages

D’abord, grâce à l’utilisation d’interfaces, le code change plus facilement. On implémente les fonctionnalités plus vite …​ Une fois qu’on a construit la structure initiale. Le code est également plus réutilisable, y compris les fragments de fonctionnalités métier. D’ailleurs, comme les règles métier sont isolées, il est plus facile d’en parler avec le métier. Pour le développement d’applications mobiles, ça aide également à concevoir un modèle identique pour Android et iOS, ce qui aide évidement beaucoup les développeurs. Et ça, c’est valable même si les features ne sont pas développées à la même vitesse.

Risques

Evidement, l’overengineering peut apparaître, comme toujours. Toute l’équipe doit par ailleurs être embarquée dans la démarche. Ce que les revues de code garantissent en aval du code.

Six mois plus tard …​

Le code métier aurait pu être écrit une seule fois pour les deux plateformes mobiles (par exemple avec Kotlin native). Réfléchir à la stratégie de test dès le début aurait évité des tests fastidieux à écrire. Se passer de la clean architecture leur semble maintenant difficile. Le pattern reactive a beaucoup aidé à mettre en place ce type d’architecture. Il y a globalement moins de bug, surtout sur les couches hors domaine.

Mon avis

Manifestement, Clean architecture est plus un guide de bonnes pratiques pour architectes en herbe plutôt qu’un style architectural. Ce sont des bonnes pratiques, et comme à chaque fois, les bonnes pratiques semblent naïves et simplistes dans une conférence comme Devoxx, mais c’est à mon avis autre chose sur une application réellement utilisée. Et c’est tout l’intérêt de la chose.

Devoxxfr – Ordinateur quantique

Un ordinateur classique, c’est simple : un circuit imprimé fait d’un bon gros paquet de transistors. Avec ça on fait des portes logiques qui, à un plus haut niveau, nous amène aux langages de haut niveau comme java ou C#. Grâce à la loi de Moore, la puissance des ordinateurs a bien augmenté. Actuellement, les transistors font 14 nanomètres. Et ça pose un problème de taille : on s’approche des bords de la physique quantique et des effets tunnels. On ne pourra donc plus gagner en puissance en améliorant les transistors.

Un peu de mécanique quantique

La physique quantique vite fait c’est

  • La superposition des états quantiques
  • Le principe d’incertitude
  • La réduction d’état quantique qui arrive quand on cherche l’état d’une particule
  • La dualité onde/particule
  • L’intrication quantique qui lie l’état de deux particules

QBit

Contrairement à un bit classique, un qbit stocke à la fois 0 et 1. Donc avec plusieurs qbits, on stocke l’ensemble des valeurs possibles pour ces qbits. Du coup, pour simuler un qbit, il faut beaucoup plus de bits (2^nombre de qbits).

Les opérateurs sont par conséquent sacrément différents. Les différents types de portes quantiques vont permettre de changer les possibilités d’apparition d’un résultat. Et donc de donner les probabilités d’apparition des différents résultats.

Par ailleurs, à cause des réductions d’état, un programme quantique pourra donner plusieurs résultats différents.

Exemples d’application

Tous les problèmes de répartition et d’optimisation (choisir les gens à une table par exemple). En chimie, trouver l’organisation d’une molécule marche bien mieux avec ce type de programmes. L’algorithme de Shore permet de trouver les facteurs premiers d’un nombre en une centaine de secondes.

Où exécuter du code quantique

Actuellement, les ordinateurs quantiques sont …​ expérimentaux (isolés magnétiquement et thermiquement). Chez Microsoft, ils travaillent sur une forme de machine quantique un peu différente, pour qu’elle soit plus stable. IBM, Google et Microsoft fournissent tous des plateformes permettant d’écrire du code quantique, mais c’est assez difficile à tester.

Mon avis

J’avais déjà lu quelques articles sur le sujet, et effectivement c’est très intéressant, mais aussi plus qu’à moitié incompréhensible. Sans doute qu’il va falloir attendre un bon moment avant que ça ne soit réellement utilisable.

Devoxxfr – Software heritage foundation

Pourquoi cette fondation ?

Autour de nous, le logiciel est partout. Et il contient une partie significative de notre connaissance et de notre héritage culturel.

Roberto nous rappelle ensuite cette fameuse citation sur l’importance de la lisibilité du code : « source code is made to be read by other human beings, and only incidentally by computers ».

Par exemple, la fonction de racine carrée écrite par John Carmak dans Doom est un code source qui est précieux et doit rester accessible. Et ça nous ouvre une fenêtre sur l’esprit du développeur.

Par ailleurs, en 50 ans, on est passé d’un code de pilotage d’Apollo 11 en 60.000 lignes au code du kernel Linux qui dépasse déja le million de lignes ! Et si le logiciel est partout, le code source lui, est hébergé chez de multiples fournisseurs (Google Code, Sourceforge, Gitorious, …​). Ce qui rend sa conservation assez complexe (surtout quand les plateformes de stockage de code source ferme). Enfin, si le logiciel est partout, il n’existe pas de plateforme de recherche pour analyser globalement le code source.

Pour combatttre ça, la software heritage fundation a été créée avec comme objectif de collecter, préserver tout le code source accessible. Actuellement, il y a déja 4 milliards de fichiers sources stockés pour 83 millions de projets.

Comment ça marche ?

Pour chaque plateforme, la SHF a créé un adaptateur permettant de collecter les codes sources utilisés. Ensuite, il faut récupérer le code source proprement dit. Actuellement, le code de GitHub et de Debian est stocké. le code de Google Code et Gitorious a été sauvé (avec l’aide de l’internet archive).

Construire pour le long terme

LA SHF a le support de l’Inria, et de l’Unesco. Cette vision est partagée avec un paquet d’organisations. Et un certain nombre d’entreprises sponsorisent l’initiative.

Comment aider ?

La SHF est du code, et peut donc avoir besoin de l’aide de développeurs (forge.softwareheritage.org). Elle a évidement besoin d’argent et de communication.

Conclusion

Il faut imaginer la SHF comme une bibliothèque d’Alexandrie du code (pour tout avoir) et un CERN du code.

Mon avis

C’est sacrément chouette ! Bravo !

Devoxxfr – Architecture hexagonale

Pourquoi ? Parce qu’à priori, les présentations sur DDD et l’architecture hexagonale ne parlent pas de framework, alors que les développeurs utilisent pas mal les frameworks.

Chez Saagie, le code s’exécute sur les bonnes machines, grâce à un container manager. Et celui-ci se trompe parfois. Ce container manager est développé avec un ensemble de couches classique. Et le code qui permettait au container manager de choisir où exécuter du code était éclaté dans plusieurs ensembles de service/DAO. Youen a donc refactoré ça dans une méthode à trois ifs.

Comment éviter ça ?

Théoriquement, l’architecture hexagonale permet d’éviter ça.

Domaine

Dans le domaine, il ne faut pas de framework. Des librairies simples peuvent en revanche être utiles.

Le domaine ne doit jamais contenir de code d’infrastructure.

Ports

Les ports sont les moyens d’appeler le domaine. Les ports primaires sont des méthodes du domaine appelables depuis l’extérieur. Et les ports secondaires sont des interfaces définies dans le domaine lui permettant d’appeler des éléments extérieurs.

Adapteurs

Les adapteurs permettent au monde extérieur d’appeler les ports.

Mise en oeuvre

Ensuite, Youen se lance dans une session de live-refactoring pour mettre en place ce type d’archiecture avec une application Spring Boot. Je vous ferai le diagramme de classe plus tard, mais globalement, en deux astuces, il arrive à écrire une application dont les règles métier sont totalement indépendantes des outils techniques utilisés pour communiquer avec le monde extérieur.

Conclusion

Avec ça, Spring est dans son cas nominal, tout comme le domaine. L’architecture hexagonale est donc parfaitement respectée, en utilisant les techniques classiques du monde Java. Le domaine est donc propre, les tests faciles et le code s’adapte beaucoup plus facilement aux échelles. En revanche, les DTO sont un peu lourds, les développeurs doivent être formés et il n’y a pas forcément de starters pour les frameworks.

Mon avis

En fait, l’architecture hexagonale, ça n’a rien de nouveau ni rien de vraiment sexy. Ca consiste surtout à séparer le code réseau du code métier et du code de stockage « d’une façon ou d’une autre ». Et si la méthode choisie par Youen est présentée comme astucieuse, elle est en fait uniquement un bon découpage en classes. Autrement dit ça n’est pas bien compliqué, c’est facilement adaptable et ça me parle puissamment.