Docker, Kubernetes et Istio

Docker, K8s (j’abrège, hein, parce que bon) sont souvent présentés pour les microservices, mais ça marche aussi avec les applications un peu plus grosses. C’est ce que David va montrer avec le petstore version A. Goncalvez.

Dockeriser

Pou ça, David construit son image Docker avec un multi-stage build (toujours impressionant pour le dockeriste débutant comme moi). Et paf, l’application est conteneurisée.

Lancer dans un cluster K8s

Vous connaissez Kubernetes ? ? non ? bon, David a une surprise pour vous

Avec K8s, on peut prendre un cluster de machines et travailler dessus sans trop s’en soucier. Pour lancer notre application, on crée deux descripteurs yaml (ouch, j’aime aussi peu que David).
  1. Un déploiement (qui décrit l’application à déployer)
  2. Un service (qui route le port 80 vers notre application – à la traefik/https://nginx.org/[nginx]/https://getkong.org/[kong]/https://www.sozu.io/[sozu]/…​.)

Et paf, on déploie. L’explication sur le mode de fonctionnement de K8s est un peu louche (à base de boucles de contrôle qui réconcilient des états souhaités/actuels).

Organisation

La CLI de K8s permet d’avoir des informations sur l’état du cluster, et nous montre par exemple que l’application tourne dans un pod. Si ce pod est détruit, K8s en relance un nouveau, et y redéploie l’application. C’est très très cool. On peut aussi facilement déployer l’application dans plusieurs pods, pour faire de la redondance dans ce que ça a de plus vrai : arrêter ou perdre un pod n’a aucun impact sur l’autre.

Améliorer l’appllication de l’extérieur

David ajoute maintenant un proxy nginx pour gzipper le flux, ajouter une page 404 et réécrire les urls. Pour ça, il suffit d’ajouter le proxy dans le pod de l’application. Ca veut dire un déploiement et un service décrivant nginx, un dockerfile et enfin fichier de configuration pour nginx. La particularité, c’est que nginx reroute vers localhost (ce qui n’est pas le cas quand on joue classiquement avec des conteneurs). Parce que nginx et petstore seront forcément déployées sur la même machine. Enfin, en ajoutant un ingress, il est possible de créer un nom de domaine spécifique devant le nginx. C’est vachement pratique, parce que pendant ce temps-là, petstore n’a pas changé.

Istio

Istio reprend précisément ce principe en ajoutant des facades envoy (un proxy C++) devant toutes les applications. Le proxy est configurable.

Premier apport : Istio transforme tous les flux en HTTPS. C’est dingue. C’est à la fois génial et affreux : comment débugger le traffic ?

Grâce à envoy, Istio fournit de monitoring de tous les services avec les temps de réponse,

David passe à une démo où les deux versions de l’application sont déployées côte à côte avec des urls différentes. Et grâce au smart routing d’Istio, on peut faire du blue-green deployment. Alors qu’avec K8s, c’est impossible. Bon, apparement, il y a d’autres solutions (de mémoire, OpenShift le fait aussi comme l’avait montré Clément Escoffier précédement). Pour vérifier qu’on a bien du blue-green, David affiche un dashboard grafana (installé par Istio) en ouvrant un tunnel de sa machine vers le composant Grafana (assez spectaculaire). Et ça marche ! On a bien 20% d’utilisateurs en v2 et 80% en v1.

Routage

Et maintenant, il est temps de tout réécrire. David va donc séparer l’application en plusieurs services, qui utiliseront toujours les routes de l’application initiale. Pour ça, le smart routing d’Istio est pratique …​ mis à part le fait qu’il y a de plus en plus de contenu YAML. Donc on a deux composants, qui se parlent à travers le réseau. Et forcément, avec le réseau, les problèmes arrivent. Heureusement, Istio va nous aider pour survivre à ça. D’abord grâce à un graphe des services (auquel on se connecte comme Grafana grâce à un tunnel temporaire). Et là, trop bien …​ mais trop moche …​ le graphe est généré par Grafviz (mais la version plus récente utilise D3.js).

Gestion du réseau

Encore une fois, grâce au proxy envoy, on peut configurer finement chaque composant pour, par exemple, simuler des timeouts. Ou de mirrorer le trafic de prod vers une application non utilisée en prod, mais qui en recevra la charge. Ou encore d’industrialiser les circuit breakers en les plaçant au niveau d’envoy. Ou encore de gérer la sécurité sans passer par les notions classiques et pénibles de zones de sécurité réseau, mais en utilisant une gestion de la sécurité par rôle. C’est vraiment chouette parce que ça permet d’optimiser le nombre de serveurs. Ca permet également, grâce à la télémétrie, de voir quel composant appelle quel autre service. Pour ceux qui connaissent, ça ressemble vachement à Dynatrace dans l’idée.

Rate limiting

En particulier, il est possible de limiter les appels à un service pour qu’il ne soit pas noyé sous la charge. Malheureusement, encore une fois, il faut des paquets de YAML.

Conclusion

J’ai loupé la séance de questions, parce que je devais aller chercher les bières, mais c’est pas grave, lançons-nous. Docker est un outil un peu chiant, mais très pratique pour les petits ops. Docker est aussi issu d’idées (conteneurs et c-groups) sur lesquels Google bosse depuis …​. des années. Donc forcément, leur outil de gestion de flotte intègre un niveau de complexité supérieur (l’abstraction des pods semble par exemple pratique, mais délicate à aborder). Et évidement, c’est difficile à comprendre pour un non averti comme moi. En revanche, cette complexité permet le déploiement d’outils comme istio, qnui est la killer feature de K8s. Rien que pour donner un exemple, il semble possible pour une entreprise de se débarasser de Dynatrace (dont les licences tournent autour de 100000€/serveur/an). Sans compter toutes les possibilités de debug qui sont, dans le monde des conteneurs, aussi indispensables qu’introuvables. Autrement dit, K8s me tente peu, mais Istio le rend supportable.

Publicités

T’as vu ? Un chtijug !

Le monde change, et le chtijug s’adapte donc. Et ce soir, l’adaptation, c’est un framework Javascript assez connu : VueJS. J’en ai déja parlé un peu, voyons voir si les speakers vont m’aider à revoir mon opinion …​

Mais avant, deux mots. D’abord, Sarah Habchi veut interviewer des développeurs Android qui ont utilisé le Linter. Pour s’inscrire, c’est http://bit.ly/Android-Lint. Allez-y, c’est pour l’INRIA.

(attention, cette fois-ci, c’est moi qui parle directement, et pas le chtijug) Ensuite, regardez ces photos de la soirée

Comptez approximativement le nombre de présents … Et comparez avec le nombre d’inscrits sur Meetup … Où il y avait 78 personnes sur liste d’attente. Si vous vous êtes inscrits, mais que vous n’êtes pas venu, vous avez pris la place de quelqu’un. C’est assez moche. Donc la prochaine fois, ne soyez pas moche, annulez plutôt.

Revenons-en à notre sujet …

Vous pouvez trouvez les slides de la présentation à cette adresse : https://slides.com/posva/vue-simple-yet-scalable/live et si vraiment vous voulez revoir la présentation dans les conditions du direct, le chtijug a ce qu’il faut :

 

Vuejs vite fait

Donc, Vuejs ! Ou plutôt l’écosystème de Vuejs. Notre speaker posva n’est pas un amateur, parce qu’il fait partie de la core team vue, et s’occupe d’un certain nombre de librairies vue.

Ecosystème ? oui, parce qu’effectivement, vue-router, vuex, vue-devtools et autres vue-test-utils sont des outils assez pratiques pour travailler autour de Vuejs. Il faut noter que ces composants additionnels sont développés par l’équipe Vuejs, ce qui facilite la communication entre les développeurs, et fournit aussi une sacrée visibilité à ces « extensions ».

Créer une application Vuejs simple, c’est facile. Regardez cet exemple de Hello World :

Et ça permet tout de suite de montrer le lien entre le template et le modèle de données : le contenu de {{message}} sera automatiquement remplacé par sa valeur.

Ca rend Vuejs assez abordable, puisqu’on peut commencer par un simple composant et l’étendre assez rapidement (contrairement à React et Angular, il semble).

Un autre intérêt de Vuejs, c’est le format .vue, où les différents éléments d’un composant sont déclarés dans le même fichier. C’est très dérangeant pour quelqu’un qui a fait du MVC avec un modèle, une vue et un contrôleur séparé. Mais ça plaît à certains. Et je dois bien reconnaître qu’il est assez confortable d’avoir les aspects d’un composant réunis au même endroit, même si j’aurais préféré avoir trois fichiers séparés dans le même dossier (par exemple).

Parce qu’évidement, Vuejs fait du MVC. Ce MVC relie donc d’un côté le DOM et de l’autre le modèle Javascript à travers des event listeners et un virtual DOM.

Dans le document HTML, enfin dans le fragment HTML contenu dans un composant Vuejs, on utilise des directives comme v-if qui commencent toutes par v-. Vuejs supporte aussi les templates JSX. Mais franchement, utiliser des du JSX, c’est un peu comme faire une JSP à l’ancienne : c’est à peu près la garantie de perdre la séparation entre la vue et le modèle, et donc de rendre le code bien pourri.

Le meilleur morceau de Vuejs, c’est évidement le binding : quand on change une donnée, elle est immédiatement mise à jour dans toutes les vues qui l’affichent.

Et c’est tout pour le « comment ça marche ».

L’écosystème

Voyons maintenant pourquoi Vuejs est aussi adaptable à l’échelle de l’application, en partant d’un simple rendu déclaratif, puis en intégrant les composants, le routage, la gestion d’état, le système de build. Évidement, tous ces éléments sont optionnels.

Démarrer un projet

Donc, pour commencer, la CLI, ou POI, c’est bien, parce que ça permet de démarrer facilement un projet sans s’embêter avec la configuration Webpack (et ça, c’est bien).

Le routeur

Ensuite, quand vous avez une barre de navigation qui change le contenu de la page, vous êtes tenté de mettre une batterie de if. Et c’est là que le routeur prend son intérêt, puisqu’il suffira de déclarer les différents composants, et donner à ces composants le nom d’une variable qui sera alimentée par un binding. Et là, pouf, ça marchera. Et en bonus, on peut changer l’url (pour peu qu’on accepte de ne pas supporter IE 9). La méthode présentée semble un peu …​ astucieuse, mais c’est assez cool de pouvoir avoir une URL qui suit l’état de la page web.

Ca devient un peu moins drôle quand on aborde les modifieurs, comme .prevent. Comme on peut les ajouter derrière un événement, ça change son sens d’une façon …​ qui me satisfait assez peu intellectuellement.

Gérer l’état

Comme les composants n’ont que des relations hiérarchiques, pour communiquer des informations entre composants, ça n’est pas toujours trivial : le parent peut modifier l’état d’un enfant, mais l’enfant doit envoyer des événements auxquels le parent doit s’abonner. Et comme Vuex est assez verbeux (une fonction par mutation d’état), on peut essayer d’éviter ça de deux façons

$root

C’est le composant racine, instancié à partir du moment où on a fait new Vue(....) C’est clairement l’utilisation d’une variable globale pour stocker l’état. C’est sale. Avec une ou deux astuces, on peut simplifier ça, mais franchement, je trouve ça sale …​ Et franchement inmaintenable.

Par contre, ça peut rendre service pour les fonctions « globales », justement, comme par exemple l’authentification : en définissant une fonction login globale, on peut facilement authentifier l’utilisateur depuis n’importe quelle hiérarchie de composant (mais en y réfléchissant, c’est assez peu utile).

Partager un état

Là, ça parlera au javaiste en moi : si je crée un objet, que je passe à la construction d’un conteneur (et que le conteneur mémorise comme data), il sera partagé entre tous les conteneurs qui utilisent cet objet. Et ça fera un chouette état partagé.

Vuex

C’est quoi Vuex ? ou plutôt qu’est-ce que ça offre ? Avant tout, comme Vuex enregistre tous les changements de l’état global, ça permet de voyager dans le temps …​ et par exemple de rejouer les bugs de l’utilisateur (classe !). Du copu, quand changer ? Par exemple, quand on a déja 5 morceaux du modèle codant l’état, et qu’on en ajoute encore.

Migrer à Vuex

D’abord, il faut créer le Store. Ensuite il faut créer les mutations. Et les actions. Et il faudra injecter le store dans l’instance root. Avant de tout refactorer pour remplacer le $root par $store.Ca a l’air bien compliqué, en fait.

Commencer Vuejs

Le plus simple, c’est évidement de lire le guide (qui est effectivement bien fichu). Ensuite, utilisez vue-devtools, et les fichiers .vue. Si vous utilisez VSCode, vetur est bien pratique (anecdote marrante, le présentateur nous parle d’emacs, de vi, d’Atom, …​ et c’est tout !).

Conclusion

J’ai trouvé ce tour d’horizon du monde Vue assez rapide. Pour tout dire, j’aurais vraiment apprécié de voir quelques exemples en live-coding (le cas le plus typique étant Vuex, dont je ne comprend pas l’intérêt).

Et même si je l’ai déja dit, je vais me répéter.

Cette présentation n’a malheureusement pas changé l’opinion que j’ai de Vuejs. C’est chouette, et évidement bien mieux que les saloperies que sont React ou Angular. Malheureusement, ça n’est pas au niveau de Ractivejs, que je continue à croire être le meilleur framework JS existant. Pour tout dire, et c’est quand même une interrogation majeure, je ne comprend pas pourquoi Vuejs a percé et pas Ractivejs, puisqu’ils offrent globalement les mêmes fonctionnalités, avec à mon sens une plus grand expressivité de Ractivejs.

Kotlin au chtijug

Première soirée chez Axa, pour découvrir un petit langage qui monte, qui monte.

En introdution

D’abord, si vous voulez comprendre Kotlin, le site du langage est très bien fichu. Et pour aller plus loin, les kotlin koanssont très bien (et c’est vrai, je les ai presque tous fait, et on apprend vite et agréablement les concepts du langage).

Pourquoi Kotlin ?

Plutôt que de nous parler des ses avantages par rapport à Java, Salomon préfère nous indiquer qu’il y a de plus en plus de Kotlin, du coup ça vaut le coup …​ Un argument d’autorité que je rapproche toujours de « 10 millions de mouches à merde en mangent, et toi ? » (la tournure est certes provoquante, mais vous voyez l’idée).

Les avantages de Kotlin sont d’abord qu’il s’agit d’un langage développé par l’industrie, et donc construit selon les besoins de l’industrie. Par exemple, il n’y a pas d’implicites en Kotlin (par opposition au Scala) parce que ça n’est pas vraiment lisible. En revanche, il y a des fonctions d’extension, qui ne valent à mon sens pas beaucoup mieux. Un autre avantage important, c’est l’interopérabilité. Kotlin vise le 100% …​ Comme le Groovy, en fait, mais pas pareil, puisque Kotlin est compilé. Enfin, Kotlin vise la facilité de lecture.

Types

En Kotlin (comme en Pascal) les types sont postfixés. Personnellement, je ne suis pas fan, mais je comprend pourquoi : en Kotlin, les déclarations de type peuvent être inférrées, typiquement dans les instanciations, comme val uri = URI(str). C’est un avantage, tant que votre IDE ne sait pas générer les déclarations de type (ce que fait Eclipse depuis …​ cinq ans, il me semble). En revanche, il n’y a pas de new. Mais du coup, la définition des constructeurs est un peu différente.

Un autre point intéressant est la nécessité de déclarer les types nullables. Par exemple, String ne peut pas être null, mais String? peut l’être. Du coup, l’elvis operator est résolu dès la compilation, ce qui est très chouette. Et le fameux coup de la million dollar mistake du null n’existe plus. A peu près …​

Interopérabilité

L’une des magies de Kotlin est que tous les objets Kotlin, y compris les collections, sont utilisables en Java. L’un décore l’autre. Salomon nous indique d’ailleurs qu’il y a un peu de magie de compilation là-dedans.

Interopérabilité & nullabilité

Comment ça marche quand on crée un type Kotlin non-null (donc sans ?) et qu’on l’utilise depuis du Java, où null est permis dans tous les types. Eh bien tout simplement, la méthode Kotlin est décorée par un code qui vérifie que l’argument n’est pas null, et renverra une KotlinNullException (à peu près) sans qu’on ait à l’écrire dans le code. Du coup, ce qu’il faut retenir, c’est que la nullabilité ne peut être vérifiée qu’en Kotlin. A l’inverse, du code Java appelé depuis Kotlin pourra retourner null. A l’origine, Kotlin utilisait toujours les types nullables, mais ça polluait le code avec des ? partout. Du coup, les concepteurs du langage ont crée le platform type (comme String!) qui ne peuvent pas être créés à la main, et qui peuvent être null. Personnellement, je trouve ça très fâcheux, mais bon, c’est un choix.

A noter qu’il existe un raccourci IntelliJ IDEA permettant de retrouver le type d’une variable …​ Parce qu’on ne l’écrit pas (ce qui en fait démontre que ces types inférrés sont peut-être une idée pas si fameuse que ça …​).

Attention, là, c’est moi qui infère. Pour en revenir à cette histoire de nullabilité avec du Java, il y a quand même un truc louche. Salomon nous explique que Kotlin fait tout pour éviter les NullPointerExcecption, et c’est très cool …​ tant qu’on reste dans le monde Kotlin. Mais manifestement, le monde Java a curieusement bénéficié d’une exception à la null-safety qui vient polluer le monde Kotlin via ces fameux platform types. Et la million dollar error est revenue par là : dès que vous appelez du code Java, vous vous retrouvez, via ces platform types, sensibles à des NullPointerException. Et utiliser du Java depuis du Kotlin, ben ça risque fort de vous arriver …​

Propriétés

Comme dans tous les langages modernes de la JVM, il y a des data class pour écrire plus simplement les Java beans. Même si en Java, on peut aussi écrire un bean sans getter ni setter, parce qu’en fait, si ils ne font rien, autant ne pas les écrire. En tout cas, en Kotlin, si on écrit une variable de classe avec un var, c’est une propriété dont les getter et setter sont générés …​. comme avec Lombok. J’aime beaucoup la justification de Salomon : JetBrains a analysé beaucoup de code Java pour constater que la plupart des attributs sont en fait publics (privés avec getters et setters qui sont, eux, publics). Du coup, le qualificateur par défaut sera public. Donc les getters et les setters sont tous générés, ce qui en fait une forme de taxe …​ A un avantage près : il est toujours possible de surcharger les getters et les setters, avec une syntaxe très proche des properties C#.

Il est également possible de définir les propriétés directement dans la déclaration de classe, ce qui fait de la déclaration de classe un one-liner pour les beans (du moment qu’ils n’ont pas trop de propriétés).

Enfin, il est possible de générer les méthodes hashCode() et toString() en ajoutant le qualifieur data devant le nom de la classe.

Propriétés déléguées

Bon, alors là, c’est un peu tordu. La ligne de code est pourtant simple :

val cm by instance(CredentialsManager::class)

En fait, dans ce cas, les getters/setters implicites de la propriété sont transférés au délégué, qui en fait …​ ce qu’il veut. La doc Kotlin est assez claire, avec quelques exemples communs : lazy, observable, …​

Fonctions

Il est possible d’ajouter une fonction à une classe (ce sont les fonctions d’extension dont je parlais plus haut). Comme par exemple String.toCamelCase(…​.) qui serait une nouvelle méthode de la classe String. En fait, dans ce cas, une méthode statique est générée dans la classe String avec en premier paramètre la chaîne de caractère à transformer. C’est en fait du simple sucre syntaxique.

Ca devient très intéressant quand on utilise ces fonctions avec des types génériques. Très intéressant, ou diabolique. Cela dit, le bon exemple est fun Map.prefixed(prefix: String): List qui retourne les clés d’une map préfixées avec le préfixe fourni en paramètre.

A noter que la fonction doit être importée à part de la classe qu’elle étend …​ si l’IDE la décrit bien.

Lambdas

Kotlin est aussi fonctionnel que Java 9. Bon, ben tout est dit, hein, on a rajouté du fonctionnel sur un langage objet. Comme en Groovy, dans une lambda à un paramètre, on peut ne pas écrire le paramètre et le remplacer par it. Et comme en Groovy également, lorsque la lambda est le dernier paramètre, on ne met pas de parenthèse autour.

DSL

En Kotlin, on ne peut pas déclarer de variables statiques …​ Mais on peut définir des objets spécifiques. Avec ça et les fonctions d’extensions, il est très facile de définir des DSL internes. Si on déclare une fonction infix, elle ne doit avoir qu’un seul argument, mais ça permet de retirer les parenthèses. Encore une fois, Groovy a les mêmes mécanismes.

Surcharge d’opérateur

Comme en Groovy (décidément), si une méthode utilise la signature d’une méthode d’opérateur, on peut utiliser la syntaxe de l’opérateur. Et avec les fonctions d’extension, d’un coup, on peut ajouter des opérateurs à des types (comme par exemple operator fun Date.plus(other: Date): Date {…​}). Ce qui est très chouette (allié à la limitation du nombre d’opérateurs utilisables).

Inline

J’avais dû survoler ça dans la doc : si une fonction a le mot clé inline, son code sera forcément copié dans toutes les fonctions qui l’appellent …​ sauf quand c’est impossible. Par exemple, comme le souligne Logan, une fonction récursive ne devrait pas être inlinable (mais il va vérifier !).

Non-local return

Ca permet par exemple de faire du non-local return …​ Là, honnêtement, j’ai du mal à conceptualiser le truc.

En fait, en Kotlin, les lambdas et les fonctions ne sont pas strictement équivalentes, apparement, et return sort de la fonction englobante. Et il est parfois utile de sortir de la lambda sans sortir de la fonction (même si la dernière instruction d’une lambda est sa valeur de retour).

Types réifiés

En Java, les types génériques ne sont pas réifiés. C’est-à-dire qu’ils sont utilisés lors de la compilation, mais pas lors de l’exécution (Rémi Forax vous expliquerait ça bien mieux que moi). Bon, donc Kotlin permet de déclarer des types réifiés. Par exemple, inline fun typeName() = T::class.simpleName devient typeName() String:::class.simpleName(). Et pour que ça marche, il faut apparement passer par des fonctions inline, sans doute pour que ces fonctions soient appliquées lors de la complation, ce qui semble nous amener dans le domaine de bugs du compilateur C# (je me souviens avoir lu un article qui expliquait qu’à cause de la réification des génériques en C#, il était possible de provoquer des OutOfMemory sur le compilateur C#, mais je ne retrouve pas le lien).

ReactiveX

Si vous connaissez RxJava, c’est plus cool.

Un des trucs marrants, c’est que ReactiveX fournit une gestion du null à travers Maybe

, et non Article?. Alors bon, d’accord, ` null` est une erreur à un million, mais si il y a un million de corrections mutuellement exclusives, je ne suis pas complètement certain que la victoire vaille le combat mené …​

TODO()

En Kotlin, on peut déclarer une fonction sans l’implémenter en écrivant fun my() = TODO(). C’est vraiment très cool !

Retour à ReactiveX

Bon, ben là, c’est de la programmation asynchrone, donc compliquée. Mais simplifiée par les coroutines …​ qui sont simplement des appels à await() après l’appel de fonctions asynchrones.

L’important, c’est que les coroutines transforment du code séquentiel en callbacks …​ grâce au compilateur, qui doit faire quand même pas mal de boulot. Du coup, écrire une librairie qui utilise ces coroutines ne doit pas être simple, mais JetBrains l’a déja fait dans un certain nombre de cas (y compris passer du thread d’affichage Swing à un thread de traitement, ou évidement vert.x).

Plateformes

Kotlin tourne sur

  • La JVM, bien sûr
  • Javascript – on peut même compiler pour du Node, mais franchement, n’en faites pas.
  • WebASM
  • Raspberry, Linux, Mac, Windows, iOS, STM32

L’intérêt de Kotlin dans ce cas est que la cross-compilation est supportée par les concepteurs du langage, ce qui change pas mal des API qui permettent de compiler du code Java pour Javascript, par exemple. C’est un gros argument marketting, clairement. Et c’est aussi assez pratique, même si ça implique quelques changements dans la chaîne de compilation, et du coup, sans doute des adaptations au niveau du code.

La philosophie de Kotlin est de faire le code buisness dans les modules multiplateforme, et de laisser le code système dans les modules plateforme. C’est pas con du tout. Sauf que, par exemple, Date n’est pas multiplateforme, ce qui est vite gênant.

A priori, du code Kotlin natif est vingt fois plus performant que du code compilé pour la JVM …​ Mais ça, je demande à voir (parce que j’ai des convictions assez arrêtées sur les performances de la JVM).

Librairies

Il y en a évidement des tonnes. Salomon choisit de nous parler de Kodein, Kotson, KTOR et autres K* …​ et Spring, hélas. On peut aussi utiliser Spek pour les tests ou Mokito pour mocker (fou, non).

A noter qu’il existe un transpileur Java vers Kotlin dans IntelliJ IDEA …​ mais évidement c’est du code généré.

Conclusion

La présentation était assez riche, mais manquait parfois d’exemples les mains dans le cambouis. Mais surtout, surtout, elle m’a compris de comprendre un truc que je vais essayer d’exprimer clairement (et là, je donne complètement mon opinion sur Kotlin).

Quelles sont les motivations pour créer un langage ?

Pour Martin Odersky et ses amis, clairement, c’était tenter d’injecter dans le monde de la JVM des concepts fonctionnels, et de les marrier proprement avec le monde objet de la JVM.

Pour Groovy, c’était de créer un lanage de scripting pour la JVM qui soit dynamique, extensible, efficace dans l’écriture.

Pour Kotlin, même si j’ai du mal à le reconnaître, l’objectif est avant tout de permettre à JetBrains d’avoir une influence visible sur l’écosystème Java et les écosystèmes natifs. Pour moi, ça apparaît clairement à travers plusieurs éléments : le côté bien trop pragmatique de certaines décisions (typiquement, l’interopérabilité maximale avec la JVM est une bêtise qui fera beaucoup de mal à ce langage). Le pari me semble audacieux, aussi bien pour JetBrains que pour les gens qui miseront sur ce langage : que se passera-t-il quand JetBrains se fera racheter par …​ disons …​ Oracle ?

Les aspects de Kotlin qui sont séduisants peuvent tous être traçés à des langages antérieurs, et en tant que tel kotlin apparaît comme une synthèse. Mais tant qu’à faire dans la synthèse, je pense qu’il vaut mieux miser sur Ceylon, qui est à peu près équivalent conceptuellement, mais qui est, lui, open-source. Alors écidement, Kotlin est soutenu par une entreprise, qui vend un certain nombre de prestations permettant à d’autres entreprises de se sentir en confiance (et franchement, pour Google, le pari sur Kotlin fait figure d’OPA amicale), mais tout ça me met un peu mal à l’aise, e qui paraît évidement curieux pour un vieux développeur Java …​ donc en quelque sorte baigné de force dans le monde Oracle.

Vavr, tu vas voir !

Merci à Norsys, qui offre le food truck ce soir (!). (par contre, le chauffage semble être mort dans la soirée).

Guillaume nous vient de chez Saagie (où je connais quelqu’un …​ depuis pas mal de temps) dans l’équipe d’outillage. Et quand il parle, j’ai presque l’impression d’entendre parler un collègue tout aussi barbu, mais plus rancheros …​

La programmation fonctionnelle

C’est de la programmation sans effet de bords, et c’est cool. Et pour faciliter ça, les fonctions sont des éléments essentiels du langage, les variables sont immutables (ça n’a pas de rapport avec la programmation fonctionnelle, en vrai, mais ça fait maintenant partie du canon fonctionnel).

Enfin, ce qui est important pour Guillaume, c’est aussi la transparence référentielle (ou referential transparency) qui garantit que deux appels à la même fonction retourneront le même résultat.

Par exemple, Math.random() ne respecte pas cet aspect, mais Math.max(1, 2) oui.

Java 8 est déja fonctionnel ?

Ben oui, avec les lambda, les streams, les Optional<?>, c’est un début. Mais pour Guillaume il manque des trucs.

Vavr …​ anciennement Javaslang

La librairie a été créée par un développeur Scala frustré par Java. Et le nouveau logo retourne joliment Java …​

Les collections Java, c’est pas pratique

Il y en a en java …​ mais c’est loin d’être pratique. Parce qu’à la base les collections sont conçues pour être mutables (et pas parce qu’ils n’ont pas compris l’immutabilité). Autrement dit, elles ne sont pas joliment immuables, ce qui fâche les puristes. Donc vavr redéfinit ses collections (y compris un Vector).

Typiquement, les méthodes Collection.stream() et Stream.collect() n’existent pas en vavr, parce que les collections sont conçues autour de concepts fonctionnels.

Guillaume mentionne ensuite un point intéressant : en programmation fonctionnelle, on n’aime pas trop les exceptions parce qu’elles ne respectent pas trop le flux d’opérations.

Streams inconsistents

Parfois, les streams Java démarrent leurs opérations un peu en avance. Du coup, deux appels successifs à Stream.map`(…​.)` peuvent balancer des exceptions, ce qui est insupportable pour Guillaume …​ Peut-être pas autant pour moi.

Streams de Map

En Java, utiliser un stream sur une map, c’est l’enfer (il faut faire le stream sur l’ entrySet() et reconstruire la Map au moment du collect). Par contre, en vavr, c’est super facile parce que vavr va mapper les couples clé/valeur vers des Tuple.

Value types

Ils arriveront en Java 10, peut-être (il faudrait demander à Rémi Forax). En revanche, il y en a un paquet dans vavr, inspirés de Scala, évidement.

Option

Hey, mais l’ Option de vavr est sérialisable ! C’est très cool !

Try

Qui permet d’encapsuler du code susceptible de lancer une exception. L’exception sera gentiment catchée et conservée. C’est pas bête du tout.

Either

Là, on est en plein dans la scalaterie. Ca permet de retourner deux types différents en disant que le retour est soit l’un soit l’autre. Bon, jusque là, c’ets un tuple. La particularité d’ Either, c’est qu’on prend comme convention que le bon cas est celui de droite …​ autrement dit le deuxième …​ Je trouve ça pénible et un authentique retour en arrière.

Validation

Qui ressemble furieusement à Bean Validation dans l’objectif …​ mais pas du tout dans l’implémentation, puisque c’est encore un Tuple, voire même un Either particulier.

Des fonctions

vavr ajoute aux Function et BiFunction des interfaces permettant d’utiliser jusqu’à 8 paramètres. Ca n’est pas très pur fonctionnellement, mais c’est bien pratique.

Composition

Mais bien sûr qu’on peut composer des fonctions avec vavr !

Lifting

Chez les fonctionnalistes, c’est la transformation d’une fonction impure en fonction pure. Et je dois bien dire que c’est assez propre.

Application partielle de fonctions

Là aussi, ça fait rêver tous les haskelliens, et c’est assez simplement réalisé. Mais mon voisin pose une excellente question : si j’applique ma fonction partielle à 5 paramètres, lequel reste à utiliser ? Le premier ou le dernier ?

Curryfication

A priori, c’est très semblable à l’application partielle, tout en étant subtilement différent.

Mémoisation

Un peu comme un cache, en fait …​ mais sans avoir besoin de réécrire à chaque fois.

Et maintenant, le pattern matching

Alors là ça va être un peu fou …​ Toujours est-il que, vous le savez maintenant, le pattern matching, c’est un switch sous stéroïdes (mais alors beaucoup de stéroïdes). Par contre, comme vavr reste du Java, c’est la syntaxe habituelle qui est utilisée. Et du coup, c’est moins surprenant puisque l’instruction langage est remplacée par des appels de méthode dans tous les sens. Ca n’est pas forcément très lisible à mon sens, mais bon. En revanche, ce qui est vraiment moche, c’est que le cas d’usage typique, c’est pour faire des instanceOf plus propres de la manière suivante :

Number plusOne = Match(obj).of(
    Case($(instanceOf(Integer.class)), i -> i + 1),
    Case($(instanceOf(Double.class)), d -> d + 1),
    Case($(), o -> { throw new NumberFormatException(); })
);

Bon, ben là, franchement, je suis désolé, mais il n’y a aucune espèce de gain par rapport au simple instanceofdans un if (qui est un foutu antipattern).

Par contre, pour filtrer une liste d’adresses entre valides et invalides, c’est pas mal du tout (merci Either).

Property Checking

On parle ici de la génération automatique de cas de tests. Et il y a pour les différents types de variables simples, des générateurs aléatoires inclus. Ca n’est pas inintéressant …​ mais le test est salement pollué par tout le code supplémentaire nécessaire pour gérer ce contenu aléatoire. Il me semble qu’il y a d’autres outils qui fournissent le même genre de services

Conclusion

La présentation était intéressante et Guillaume sacrément motivé pour nous convaincre (et ça, c’est très cool). Néanmoins, je ne peux pas m’ôter de la tête l’idée que vavr est avant tout un exercice de style, une espèce de figure imposée éventuellement utilisable sur un projet, mais dont ça n’est pas le but premier. Pour moi, le but de ce genre de librairie (comme ça a pu l’être quand j’ai écrit gaedo), c’est avant tout de tester la faisabilité d’un concept. Après, pour l’utiliser, il faut quand même avoir des besoins qui sont à mon sens particulier (surtout si quelqu’un veut sortir de Java 8 pour utiliser vavr). L’idée est néanmoins intéressante, et certains aspects m’ont paru particulièrement séduisants.

Keycloak au chtijug

 

 

Thibaut commence par nous présenter KaliCustomer …​ le nouveau nom d’Onyme. Qui fait donc du suivi de la satisfaction client à travers des questionnaires envoyés. Un truc amusant, c’est qu’Onyme est devenu un éditeur de logiciel en 2010, après avoir été longtemps une ESN.

Revenons donc à Keycloak …​

Ca envoie du rêve !

Et commençons donc par une démo. Une démo assez simple, puisque nos speakers vont coder une application Spring Boot …​ depuis start.spring.io (qui fournit un chouette générateur de pom). Donc, après un peu de code, le contrôleur est implémenté avec une vue thymeleaf. Il y a deux ou trois trucs que je trouve un peu moche avec Spring Boot, mais bon …​ pour l’instant ça marche.

On installe ensuite Keycloak, qui est en fait l’outil de sécurité de JBoss Wildfly, et packagé également pour servir des applications externes (heureusement). Du coup, paf, on crée un realm, hop, un utilisateur, boum, on connecte l’application côté Keycloak.

Et ensuite, il faut configurer l’application elle-même. Ce qui est un tout petit peu fastidieux (du moins quand on le présente en conférence). Par contre, d’une façon un peu dommage, la demande d’authentification sur un contrôleur n’est pas dans le contrôleur (sur une annotation, typiquement), mais dans une configuration séparée.

Après un peu de configuration complémentaire, Keycloak intercepte bien les requêtes pour accéder aux pages demandant une authentification.

Du coup, la suite logique, c’est d’avoir un service externe qui fournit une liste de bières à un autre service qui affiche ces bières, les deux utilisant une identité qui est propagée par keycloak.

Et bon, là, on intègre Keycloak dans du nodejs, et c’est à peu près pareil …​ mais plus sale.

Et surtout, ça marche.

Et on passe maintenant au client, en HTML+Javascript (mais sans framework infame). Et pour ça, Keycloak fournit un connecteur Javascript pour les clients directement depuis le serveur, ce qui est assez cool. Et qui permet de garantir que le client utilise la bonne version de l’API de sécurité. Et ça marche …​ simplement (pour du Javascript).

Plus sérieusement

Keycloak est un produit sérieux, avec des connecteurs pour toutes les bases de données, LDAP, Kerberos, …​ Par ailleurs, il supporte OpenID, OpenID Connect, OAuth, et SAML (mais on ne parle pas de SAML). Thomas enchaîne ensuite par une présentation de ces protocoles, que je ne vais pas vous relater ici (parce qu’il y a quand même tout un paquet de sites de qualité sur le sujet). Par contre, je ne connaissais pas JSON Web Keys

Et sous le capot de Keycloak ?

Donc l’interface de saisie est facilement configurable (via des thèmes) et on peut aussi changer la langue de l’interface simplement en activant l’internationalisation. Comme Keycloak est un service d’identité, il est évidement possible de permettre aux utilisateurs de s’enregistrer eux-même (le scénario typique dans un site grand public). Et évidement, la page de création d’utilisateur est fournie par Keycloak …​ Il est évidement possible d’envoyer des mails pour les mots de passe oubliés ou pour vérifier les emails des utilisateurs, mais ça implique d’avoir configuré un serveur SMTP (comme par exemple Fake SMTP Server – bon en fait il y en a plusieurs : en Java (http://nilhcem.com/FakeSMTP/), en .Net (https://fakesmtp.codeplex.com/), très pratique pour le développement). En bonus, lorsque l’utilisateur clique sur le lien de vérification d’email, il est authentifié et connecté à l’application, ce qui fournit une meilleure expérience utilisateur. A part les utilisateurs simples, Keycloak peut aussi utiliser les logins sociaux (GitHub, Google, StackOverflow, …​). Et si votre site préféré n’est pas présent, il est possible de créer une extension Keycloak …​ ou encore d’utiliser les protocoles standard (OAuth, OpenID).

Pour revenir aux cas simples, Keycloak fournit évidement des outils de gestion de qualité de mot de passe. Mais aussi, et surtout, Keycloak met à jour régulièrement sa politique de hashage des mots de passe, et lorsque cette politique change et qu’un utilisateur se logge avec un mot de passe hashé avec un vieil algorithme, il re-hashe le mot de passe avec le nouvel algorithme. Très cool. Un autre truc vraiment très cool, c’est de pouvoir prendre l’identité d’un utilisateur (pour peu qu’on dispose des privilèges suffisants). Et ça, pour les développeurs, c’est quand même super chouette. Et si vous voulez vous compliquer la vie, l’authentification deux facteurs est supportée via FreeOTP ou Google Authenticator.

Conclusion

Certains éléments des démos ont été particulièrement bluffants. Et je l’utiliserai bien …​ si j’avais à développer une solution de gestion de l’identité. Mais ça n’est pas vraiment le genre de projet qui se fait toutes les cinq minutes …​ Sauf dans les petites boîtes.

Scala, c’est l’histoire d’un type

Hier soir, c’était … chtijug !

Et comme je me suis occupé d’aller chercher toutes les bières (et de les servir), je n’ai pas suivi très attentivement la présentation de Valentin Kasas. Pas de panique, j’ai un collègue qui a produit un article de qualité.

Heureusement, elle est là

Et en la lisant, je ne peux m’empêcher d’avoir … certaines opinions.

Et comme je suis généreux, je vais vous les partager, parce que comme le dit l’inspecteur Harry

(je peux pas m’en empêcher)

A travers les différents éléments présentés (pattern matching, destructuring, méthode apply, case class, implicites), on voit bien que les concepteurs du langage ont cherché à mettre en place dans la JVM un langage aux fondations théoriques solides. Mais je crois profondément que l’intérêt d’un langage n’est pas dans ses fondations théoriques. Sinon, ni Python, ni Ruby, ni Java n’auraient percé, et on ferait tous gentiment du LISP, de l’Ada ou du PROLOG. Or ça n’est pas le cas.

Parce que ces langages, théoriquement puissants, manquent d’ergonomie. Et en l’occurrence, le coeur de mon idée, c’est que l’ergonomie de Scala est clairement défaillante. Défaillante, parce qu’il y a des tonnes de choses qui me semblent implicites, et d’autres qui sont vraiment à la limite de l’overengineering. Sans compter tous ces moments douteux où on sent bien la volonté de faire de « l’avant-garde ».

Bref, Scala, ça n’est pas trop ma came. Heureusement, je crois qu’on aura une présentation de Kotlin bientôt, qui m’a nettement plus intéressé pour l’instant.

Java 9, tu modules ?

Rémi ?

Vous connaissez Rémi ? Il est maître de conférences à Marne la Vallée, développeur d’ASM (j’ignorais ça), d’OpenJDK, expert pour le JCP (et clairement spécialiste des évolutions du langage, pas la partie JavaEE) où il a ajouté invokedynamic, et a travaillé sur les lambda, Jigsaw.

Java 9

Java 9 est la dernière grosse release, parce que c’est pénible. Ca va être remplacé par une release tous les six mois …​ c’est un peu plus rapide. Et donc, dans six mois, on verra var apparaître dans le langage Java.

Les modules

Historiquement, ça devait arriver en Java 6 ou 7 …​ Ca a pris un peu de retard.

Qui veut modulariser le JDK ?

Il y a d’une part des développeurs du JDK qui veulent le faire évoluer, mais ne peuvent pas à cause de toutes les APIs qui utilisent des classes « cachées » du JDK. Et d’autre part …​ des experts de sécurité qui considèrent les failles de la plateforme.

D’autres problèmes

L’enfer du CLASSPATH

Sans outil pour gérer automatiquement le CLASSPATH (genre maven, gradle et autres), c’est l’enfer. Par ailleurs, quand le ClassLoader charge une classe, il scanne linéairement tous les jars et charge la première classe qu’il trouve. Du coup, c’est long. Mais aussi super merdique quand on a deux versions du même artefact. Du coup, on aimerait bien que ce soit géré par la JVM. De la même manière, éviter que les NoClassDefFoundError ne sortent qu’à l’exécution serait une bonne idée pour les développeurs.

Alléger Java

Ce serait sympa de pouvoir faire tourner le code Java sur des plateformes plus légères (typiquement pour l’IoT). Personellement, ça meparaît vaguement possible avec des outils comme ProGuard de limiter la taille des dépendances, mais ce serait mieux d’avoir ça directement dans le JDK. Par exemple, rt.jar contient encore des parseurs XML (qui n’ont pas à être des classes privilégiées) ou CORBA (qui s’en sert encore ?).

Comment modulariser ?

standards
Aucun rapport avec Java, bien sûr

Il y a déja des standards de modules en Java

  • maven
  • gradle
  • JBoss
  • OSGi
  • JavaEE

Du coup, Jigsaw doit fournir un système de modules compatible avec tous ces systèmes prééexistants. Ce qui implique tristement qu’il ne peuvent pas contenir de numéros de version. Et ça, c’est moche.

Modularisons donc !

C’est quoi un module ?

Dans un module, il y a

  • des dépendances
  • et des classes qu’on veut garder invisibles aux autres packages

Par exemple, java se est constitué d’un paquet de modules …​ dont java.compiler. Ce qui signifie qu’il n’y a plus de distinctions JRE/JDK.

Tout ça est décrit dans un module-info.java qui va être compilé comme le reste du code. Ca empêche les modifications ultérieures, ce qui est bien.
A la compilation, il ne peut donc plus y avoir de « split-packages » (des packages déclarés dans deux JARS), ou de dépendances cycliques.

Qu’est-ce qu’on perd ?
  • les « split-package »
  • setAccessible(true) sur une classe d’un module fermé

Au passage, ça permettra enfin à Rémi d’optimiser les champs final (un truc dont j’étais sûr qu’il existait déja pourtant)

Enfin, sauf si on active le flag --illegal-access=permit (qui est parfaitement clair). Notez qu’il y a d’autres valeurs possibles (warn, debug). Bon, un jour, il disparaîtra.

En bonus, les classes JavaEE cachés dans JavaSE (java.xml.bind, java.xml.ws et autres) ne seront plus dans le JDK. Notez que ces classes sont toujours accessibles via des dépendances Maven.
Les classes sun. et com.sun. qui ne sont pas utilisées sont également supprimées.

A noter : L’annotation @ForRemovall (je ne suis pas sûr de l’orthographe) indique les classes qui seront supprimées dans la prochaine version du JDK. C’est une version étendue du classique @Deprecated.

Comment trouver les dépendances

Avec jdeps, par exemple, on peut facilement trouver toutes les dépendances d’un module. Notez que cet outil existe déja dans Java8.

Oui, mais comment je transforme mon application pour Java9 ?

Pour ça, Rémi a développé son application de test : ModuleTools qui lui permet de lire et d’écrire un fichier module-info.java ou module-info.class.Et dans son application, il déclare quelques modules, qui dépendent tous de java.base (comme les classes Java dépendent de java.lang.Object).

Contrairement à maven, un require de module n’est pas transitif (contrairement à maven). Du coup, il y a un require transitif, mais qui est limité à un niveau.

En terme d’organisation de fichiers, il est possible d’avoir plusieurs organisations, dont par exemple plusieurs modules dans le même dossier (ce qui n’est supporté ni par maven, ni par gradle, ni par les IDE).

Il est possible de stocker la version du JAR dans le module-info, et de la réutiliser depuis le code, mais le système de modules n’utilise pas la version.

Comment utiliser un JAR non modulaire ?

Typiquement, une dépendance de Maven Central.On ne peut évidement pas ajouter simplement le JAR dans le CLASSPATH. Il suffit en fait de mettre le jar dans le module-path, et Java va générer automatiquement un module-info, qui permet en plus à ce module automatique de dépendre de JARs du CLASSPATH.Et comment s’appelle ce module ? Soit le nom fourni dans le MANIFEST.MF comme Automatic-Module-Name, soit le nom du JAR sans le numéro de version. Du coup, en ce moment, sur GitHub, c’est la fête à l’Automatic-Module-Name. Au passage, il est possible d’utiliser les JARs modulaires comme des JARs classiques, en les mettant dans le CLASSPATH !

Comment limiter la visibilité ?

Si on veut faire un module interne, il est possible de limiter sa visibilité à certains modules spécifiques, et pas au monde entier. C’est très chouette pour mieux gérer la sécurité. C’est ce qu’ont fait les développeurs du JDK pour la tristement célèbre sun.misc.Unsafe dont une partie a été déplacée dans jdk.unsupported, et une autre partie dans un jdk.internal.misc. Du coup, la réflexion n’est plus possible sur les champs privés (dommage pour gaedo). C’aurait été pénible pour JPA …​ mais les fournisseurs d’implémentation JPA utilisent des agents qui changent le code avant son exécution. Cela dit, la réflexion reste possible grâce à open sur un package ou sur le module.Par ailleurs, le très moche ServiceLoader a été étendu pour fonctionner avec les modules …​ La différence, c’est que la description est un peu propre et intégrée au module-info. Et la description à la fois des fournisseurs d’implémentation et de l’utilisation de ces implémentations doit être fournie. C’est super cool, parce que ça permet de tester les injections de dépendances.

Packager ?

Avec jlink, on peut créer une image à la volée de l’application et de ses dépendances. Pratique pour l’embarqué, évidement, mais aussi pour Docker. Hélas, il ne peut pas y avoir de modules automatiques, parce qu’avec ces modules automatiques, il faut embarquer tout le JDK, et ça limite en plus énormément les possibilités d’optimisation de jlink. C’est un peu la carotte de Jigsaw. Ca permet aussi d’utiliser une JVM minimale de 3 Mo !. Bon, sans JIT, mais sur un Raspberry, c’est pas vraiment utile. Ca permet aussi de garantir la durée d’exécution …​ avec jaotc, qui génère du code natif (qui pourra même se passer de JIT). Le but à terme de cette expérience est (accrochez-vous) de réécrire la JVM en Java (pour se débarasser du code C++).

Evidement jlink (et l’ahead-of-time-compiling) est chouette pour les performances. Et pour l’espace disque.

Conclusion

Modulariser, ça n’est pas si facile, à la fois pour les implémenteurs et les utilisateurs. A ce sujet, la conclusion de Rémi est parfaitement claire : si vous avez une application non-modulaire, n’essayez pas de la modulariser. C’est à la fois long, complexe, et sans valeur ajoutée. En revanche, si vous vous lancez dans une nouvelle application, la modulariser dès le départ peut être utile.

Et merci à nos amis du chtijug pour une soirée sans faille, dans une super salle, et avec une vue vraiment chouette !

Chtijug et barbecue

Gravitee

Bon, je connais les speakers depuis …​ 10 ans facile. Et ça fait plaisir de les voir sur scène !

Gravitee, un API Manager

Donc l’API management (voir la session chez Kiabi – et la page Wikipedia de définition), ça permet de créer et de publier des API, de les maintenir en état de marche, et enfin de collecter des statistiques d’usage.

D’un point de vue architecture, il y a principalement deux composants

  1. Un portail d’API, permettant l’enregistrement d’utilisateurs, la découverte des API.
  2. Une gateway, qui va exécuter les appels en les dispatchant auprès des services backend.

Pour les clients, ça peut être

  • Une façon d’exposer une API
  • Un reverse proxy
  • Un ESB pour les API REST (mais ça c’est faux : il y a tout un tas de différences entre l’API manager et l’ESB)

Gravitee, le produit

Existe depuis 2015, et nos speakers ont créé la société GraviteeSource pour fournir le conseil, la formation autour du produit.

Démonstration de création d’API

A partir d’un serveur exposant l’API, on peut facilement créer les éléments dans Gravitee grâce …​ à un wizard ! Il faut noter que, dans le wizard simple, la notion de plan de consomation (pour pouvoir facturer facilement, évidement). Par ailleurs, on peut importer facilement de la doc RAML/SWAGGER/Markdown. Et c’est fini, l’API est déployable

Consomation d’API

Une fois l’API créée, il faut créer une souscription pour pouvoir l’utiliser.

Et là, les petits gars, vous avez déja de quoi remplir quelques rapports de bugs pour améliorer vos présentations 😉

Cela dit, les écrans d’administration sont sacrément bien fichus, avec une vision complète des temps de réponse et de la qualité des réponses.

Réécriture de la réponse

L’un des éléments intéressants d’un API manager, c’est la possibilité de modifier les requêtes pendant leur exécution grâce à des politiques de transformation préconçues (des transformations simples) ou …​ du Groovy (j’aime beaucoup), ou aussi de créer un cache au niveau de la gateway.

Développement de policy

Comme gravitee est développé en Java avec des mécanismes de plugins typiques, ajouter une policy, c’est assez facile, et c’est parti …​ avec un archétype Maven ! Et je dois dire que le code produit par la génération d’archétype est, un peu comme pour Wisdom, assez complet.

Web multi-écrans

J’ai déja vu la présentation sur Youtube, mais en live, ça n’est évidement pas pareil …​

Un truc marrant dès le début de la présentation : Hubert nous parle de 2008 et de ses deux écrans. De mémoire, avec mon voisin de derrière, en 2009, on bossait dans une boîte où chaque poste avait 3 écrans sur deux machines avec Synergy …​ Et encore, ça n’était pas ma première fois avec plusieurs écrans.

Donc, plusieurs écrans, et des interfaces avec plusieurs écrans. Dans le web.

Un truc très intéressant dans sa présentation, c’est qu’il intègre un avis contraire, celui de quelqu’un qui affirme ne travailler qu’avec un seul écran.

Et Hubert enchaîne ensuite avec les différentes techniques permettant la communication : window.open, et autres hacks. J’ai malheureusement un trou dans mes notes. Dans mes souvenirs, il y a un ou deux hacks, et une technologie parfaite pour les applis du futur, mais pas forcément disponible partout.

Cela dit, il y a une faille dans cette présentation (formellement impressionante) : le cas d’usage est quand même super limité : faire du web, sur plusieurs écrans, sans serveur …​ mis à part TiddliWiki, je connais peu de projets sur ce créneau. D’ailleurs, même les applications comme Atom, Brackets, Code ont un serveur web (oui, dans le même process, mais conceptuellement, il y a quand même un client, et un serveur). Personnellement, quand j’ai le genre de besoin dont Hubert parle (avoir des clients qui communiquent entre eux), je reste simple et je mets du websocket sur mon serveur.

Conclusion

Les sujets étaient assez spécifiques, mais les speakers étaient très chouettes, et la soirée s’est finie tranquillement sur les pelouses de Norsys

Un chtijug dans le textile

Et paf, un chtijug pas à petit prix chez kiabi ! Le site est plutôt sympa, avec un côté plateforme pour théatre d’improvisation (par contre, les spots du fond qui clignotent, ça va pas être pratique pour les épileptiques). Julien (du chtijug) est bien content qu’on sorte des éternels ISEN/IUT B …​ et moi aussi : aller faire ces conférences dans des entreprises, pour des développeurs professionnels, c’est effectivement mieux.

OpenAPI chez Kiabi

Il y a deux ans, Kiabi a lancé une API web. Je ne vais pas vous reprendre tout l’argumentaire développé par le speaker sur les API, parce que personnellement, je connais déja (oui, je ne suis pas vraiment pédagogue). Cela dit, il explique bien les différents aspects positifs de la définition d’une API (quand les slides seront disponibles, ce sera plus clair). L’un des plus grands bénéfices étant évidement l’accélération des développements : en découplant le développement back-end et le développement front-end, on peut accélerer ce dernier.

OpenAPI, c’est le troisième niveau du développement d’API dans l’échelle suivante :

  1. API interne
  2. API publique, mais uniquement exposée aux partenaires (avec évidement de l’OAuth, et peut-être de l’API management)
  3. API publique, exposée et source de revenus.

Définition

Pour développer l’API, Kiabi a d’abord défini des concepts généraux :

  • API Kiss
    • incluant une API affordance, c’est-à-dire intuitive dans son usage, et suggérant même ses bons usages
    • avec une sémantique claire
    • et en ne fournissant qu’une seule façon de faire une chose
  • Réutiliser des standards et des types d’API existant

Par contre, il faut éviter d’utiliser le jargon fonctionnel interne (ce qui est un point à mon sens super intéressant). Laissez-moi détailler ce point un instant. Dans votre entreprise, vos fonctionnels sont là pour définir le vocabulaire métier. Vous comptez sur leur sérieux. Mais quand vous développez une API publique, vous n’utilisez pas ce vocabulaire … C’est de la schizophrénie ? Non, à mon avis, c’est plutôt que le vocabulaire interne dérive, se jargonifie, et perd son adhérence avec le réel. Du coup, c’est DDD ou pas ? A mon avis, et contrairement à certain homonyme, oui.

A partir de ces concepts, Kiabi a défini une refcard qui reprend l’ensemble des concepts et des règles de fonctionnement définies. Chose curieuse, cette refacrd inclut la liste des codes HTTP retournés par les applications Kiabi. Ca me paraît curieux : le W3C a défini ces codes pour des raisons qui peuvent arriver, non ? Alors pourquoi ne pas tous les utiliser ?

Implémentation

Et donc, les implémenteurs implémentent leur API à partir de ces règles, et elle est définie en comité (argh) avec une platrée d’architectes transverses (re-argh). Evidement, ça qualifie le projet comme non-agile, mais en un sens, je comprend le besoin de cohérence du bazar. Et de la même manière, l’implémentation se fait sur une plateforme standard : Tomcat, CXF, JSON, …​

Management

Pour gérer tout ça, Kiabi a mis en place un API Manager (Software AG Webmethods API machintruc) qui ne semble pas fournir tous les services, puisqu’il y a quand même un Apache en frontal (apparemment pour faire de l’URI rewriting). Ils ont également un portail d’API pour développeur, évidement indispensable pour permettre aux développeurs d’utiliser les différentes API proposées. D’une façon amusante, le speaker insiste lourdement sur le fait que ce portail d’API permet aux développeurs d’utiliser facilement les différentes API. Ca trahit à mon sens plus le choc culturel qu’est cette ouverture que le challenge technique de ce portail (ne serait-ce que parce que StackOverflow, Goodreads, le fournissent déja depuis …​ quoi …​ 5 ans ?).

Démo

Pub

Kiabi organise au mois de juin un hackathon. Bon, personnellement, je ne suis pas fan de ce genre d’événements. Mais si ça vous branche …​

traefik

Pourquoi faire un autre reverse proxy (par rapport à, par exemple, nginx ou HAProxy) ? A cause des miccroservices.

Avec les microservices, on gagne un tas de nouveaux outils :

  • Des conteneurs (Docker, rkt)
  • Des orchestrateurs (Docker Swarm, Kubernetes, Mesos, Rancher)
  • Des outils de service discovery (etcd, Consul, Zookeeper)
  • Et des reverse proxy

A quoi ça sert ? A connecter le réseau privé au web en respectant l’état des microservices. Souvenez-vous, Christophe Furmaniak en avait déja parlé lors d’une session sur Rancher.

Les reverse-proxyes open-source (HAProxy et nginx) ont une configuration statique. Du coup, quand les microservices sont déployés, il faut

  1. Arrêter le proxy
  2. Changer la configuration
  3. Redémarrer le proxy

Pas très pratique.

traefik, lui, lit sa configuration depuis l’orchestrateur. Du coup, pas besoin de redémarrage. Plutôt cool …​ Et pour être rapide, c’est du go. Et d’un coup, je comprend pourquoi le go progresse : avec le build statique, une image Docker d’un programme go ne contient pas de dépendances, et c’est chouette ! (pour ceux qui aiment ça). Attention, je ne dis pas que c’est bien. Je dis juste que Go est plutôt bien adapté au monde Docker.

Démo

Et d’un coup, je comprend l’affection de Quentin Adam pour les gestionnaires d’abréviation : lancer des conteneurs docker en ligne de commande pendant une démo, ça peut merder facilement …​ Parce qu’Emile a eu quelques soucis liés à la connexion internet … sensible et aux commandes docker un peu longues.

Jenkins, sers-moi donc un Chtijug !

Nicolas Géraud était venu nous parler des pipelines il y déja deux ans.Est-ce que cette présentation allait être mieux ? En tout cas, elle est bien différente.

Petit point sponsoring de l’IUT sur la taxe d’apprentissage : les entreprises peuvent déclarer des organismes de formation bénéficiaires de leur taxe d’apprentissage. Ca peut avoir une influence sur le budget de ces organismes.

Et c’est parti !

Avec d’abord un petit sondage :

  • qui connait Jenkins ? A main levée, tout le monde dans la salle.
  • qui a déja migré vers Jenkins 2 ? Encore à main levée, pas grand monde.

Jenkins 2

Donc Jenkins 2 … est totalement compatible avec Jenkins 1. Et c’est bien, parce que la montée de version va être simple. Dans l’ensemble, les plugins sont compatibles.

Avec Jenkins 2, il y a aussi de nouveaux sites

  • http://jenkins.io qui est bien plus grand public
  • le project Voltron sert de plugin store avec une chouette présentation. Limite comme le google play store, en fait.

Il y a maintenant au premier démarrage un mot de passe à aller chercher dans les logs de la machine. Ca va permettre de sécuriser le serveur Jenkins avec un admin par défaut. Evidement, on peut toujours avoir un Jenkins non sécurisé, mais il faut le vouloir. Ce qui change pas mal de Jenkins 1 qui, par défaut, n’était pas sécurisé. En bonus, une liste de plugins par défaut est disponible, pour faire une première personnalisation de Jenkins.

Et ensuite, on arrive aux fameux pipeline-as-code.

Pipeline as code

Un job est défini par un Jenkinsfile, écrit dans un DSL Groovy, qu’on peut stocker dans son SCM. L’avantage, c’est aussi de permettre d’utiliser les structures de contrôle de Groovy pour personnaliser le job.

Et ensuite

Il y a tout un tas de nouveaux trucs qui ne vont pas tarder à arriver

BlueOcean (déja disponible en pas beta, mais pas release non plus)

La fameuse nouvelle interface graphique pour Jenkins. Les captures sont très chouettes !

Franchement, l’affichage des pipelines est très chouette. Si j’avais eu ça chez Perigee, j’aurais pu montrer un vraiment très beau pipeline. Le plus incroyable, c’est quand même de pouvoir faire « pousser » un pipeline graphiquement. Il faut voir l’écran pour le croire, je trouve.

Pipeline déclaratif

En bonus, ça permet à des non-développeurs de modifier le build, ce qui n’est pas une si mauvaise idée, puisque le code exécuté est toujours en SCM. En fait, le pipeline généré n’est pas exactement identique à celui qu’un développeur écrirait : c’est un pipeline déclaratif.

D’une façon amusante, le speaker décrit la syntaxe d’un DSL Groovy comme « à mi-chemin entre YAML et Groovy ». Guillaume Laforge et tous ses amis pleurent des larmes de sang en entendant ça. Parce que quand on regarde un DSL Groovy, comme par exemple le MarkupBuilder, on est exactement dans la syntaxe visible à l’écran. Bon, je ne vais pas en vouloir au speaker : il connaît sans doute mieux Jenkins que je connais Groovy.

Back-end storage

Manifestement, l’objectif est de découpler le fonctionnement de Jenkins et le stockage des configurations d’exécution et des résultats. C’est une chouette idée, mais pas vraiment assistée par les capacités des plugins à écrire eux-mêmes des fichiers.

Donc Jenkins 2, c’est ?

Jenkins 2, c’est mieux, et orienté sur le continuous delivery. Et pas le continuous deployment. Autrement dit, l’équipe de cloudbees ne vise pas trop à utiliser Jenkins pour le déploiement en prod.

Quelques questions

Si les pipelines sont déclaratifs, comme maven ou gradle, pourquoi ne pas réutiliser leur outillage ?

Jenkins est utilisé pour faire le delivery, ce que ne font pas ces outils. En un sens, je comprend cette réponse : le scope fonctionnel est différent, et ce serait assez curieux de dire « on peut faire du gradle pour le déploiement ». Et puis, Cloudbees et Gradle inc ne vont pas fusionner demain.

Mais quand même, en transformant les jobs en bouts de code, je trouve que Cloudbees fait rentrer Jenkins dans une espace de continuum de build qui va de mon poste jusqu’aux artefacts déployables en prod.

Comment se compare l’API de pipeline-as-code et de job-dsl ?

L’inspiration initiale de pipeline-as-code était buildflow, mais ça a vite divergé.

Et la démo

  • Premier truc cool : les plugins installés sont toujours installés à la dernière version.
  • Deuxième truc cool : BlueOcean est déjà disponible comme plugin, et donc installable.
  • Troisième truc cool : le travail d’administrateur Jenkins s’arrête, pour les jobs, à créer les jobs et les connecter à des SCM. Tout le reste vient du Jenkinsfile.

Et donc, on passe à la création du Jenkinsfile. Et là, la structure des DSL Groovy réapparaît vraiment, et c’est bien.

  • Quatrième truc cool : les commandes checkout de SCM utilisent la révision du Jenkinsfilecomme référence. Par conséquent, l’enchaînement d’étapes se passera beaucoup mieux que dans Jenkins 1, puisqu’il n’y aura pas de révision à passer. Par contre, curieusement, le DSL ne semble pas contenir de commande maven, puisque notre speaker exécute les commandes maven via un sh "mvn clean package". Arf … apparement, le plugin exécutant maven est « mauvais ».
  • Cinquième truc cool : l’interface de Jenkins inclut un générateurs de snippets façon vieux wizards qui permet d’apprendre très rapidement le DSL des pipelines.
  • Sixième truc cool : l’affichage des pipelines en cours est vraiment très sympa, avec des logs par noeud du pipeline affichés en temps réel.
  • Septième truc cool : le DSL inclut une notion de stashes, valable uniquement pour la durée du pipeline, qui permet donc de ne pas déployer dans Nexus les artefacts temporaires.
  • Premier truc pas cool : le pipeline est toujours exécuté sur le master. Du coup, la montée en charge pourrait mal se passer.
  • Huitième truc cool : pour les pipelines déclaratifs, il est possible de demander à Jenkins d’analyser la syntaxe.
  • Deuxième truc pas cool : on peut relancer un pipeline à partir d’une étape uniquement dans la version commerciale de Jenkins. C’est moins bien … mais je comprend tout à fait.
  • Neuvième truc cool : il est possible de créer des morceaux de code partagés entre pipelines.
  • Dixième truc cool : les milestones permettent d’éviter de lancer plusieurs builds concurrents sur une ressource critique.

Et si vous voulez voir le Jenkinsfile utilisé pour ce live-coding, il est disponible sur github.

D’autres questions

Comment tester un pipeline ?

Eh bien, on ne peut pas : il faut le lancer dans une instance de Jenkins. Autrement dit, c’est le genre de truc où il faut une instance de test de Jenkins. Et mon collègue me souffle à l’oreille qu’on peut très bien utiliser l’annotation @StaticCompile de Groovy pour vérifier la syntaxe autant que possible (parce que @StaticCompile, sur un DSL, il doit bien s’amuser, tiens).

Conclusion

J’ai quand même hâte de voir les projets passer au moins aux pipelines as code, histoire d’avoir dans mon SCM, à côté de mon pom.xml, le Jenkinsfile qui va bien. Et histoire aussi d’ajouter un peu de Groovy dans tout ça !