Il y a 3 années · 24 minutes · Events

Paris JUG : On a testé pour vous le Young Blood II

Format

parisjugDans un amphithéâtre de plusieurs dizaines de places, 6 speakers présélectionnés se sont succédés pour nous présenter un sujet de leur choix, disposant de 15 minutes chacun, suivies de 5 minutes de questions / réponses. Le tout animé par un chauffeur de salle survolté.

Le milieu de la soirée est marqué par un entracte, au cours duquel un buffet nous est offert par le sponsor de la soirée, Innovation Box. Pendant ce temps, un QCM décalé nous est posé concernant les présentations de la soirée, sûrement pour vérifier notre assiduité.

A l’issue des présentations, l’auditoire est invité à voter pour ses présentations préférées.

WebCrypto API

Ou comment chiffrer ses données via Javascript dans un navigateur web moderne… (par Jean-Christophe Sirot)

Jusqu’en 2012, et malgré la présence de librairies tierces, il n’existait pas d »API JavaScript performante pour effectuer du chiffrage / déchiffrage, et protéger ses données, hormis SSL. Cependant, SSL permet seulement de chiffrer une communication entre un client et un serveur. Il existait néanmoins des solutions basées sur des applets Java.

Avec l’apparition de nouvelles applications riches, de nouveaux besoins apparaissent, et notamment celui de chiffrer des données au sein même du navigateur (par exemple pour un coffre fort électronique).

Il existe plusieurs raisons pour lesquelles JavaScript ne proposait pas, jusqu’ici, de solution de chiffrage :

  • il est incapable de générer des nombres aléatoires de manière non prédictible,
  • le langage ne propose pas de tableaux performants, ni d’entiers 64 bits, ou big integer, indispensables si l’on souhaite implémenter des algorithmes de cryptographie,
  • impossibilité de réaliser des calculs long dans le navigateur (calculs de clés de chiffrage) car un seul thread exécute le JavaScript dans un navigateur.

Après de longs mois de gestation, le W3C a donné naissance à de nouvelles APIs(http://www.w3.org/TR/WebCryptoAPI/#examples-section), parmi lesquelles, un ensemble de primitives prêt à l’emploi au sein de l’objet window.crypto.

Par ailleurs, l »implémentation toute fraîche des promesses (processus asynchrones) s’avère salutaire lorsqu’il est nécessaire d’effectuer des calculs longs.

Exemple d’utilisation de window.crypto :

// plusieurs opération possibles : encrypt / decrypt / sign / verify / generateKey ou digest&amp;amp;amp;amp;lt;br /&amp;amp;amp;amp;gt;&amp;amp;amp;lt;br /&amp;amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;<br />
window.crypto.subtle.digest({ name: &amp;amp;amp;amp;amp;quot;SHA-256&amp;amp;amp;amp;amp;quot; }, data);&amp;amp;amp;amp;lt;br /&amp;amp;amp;amp;gt;&amp;amp;amp;lt;br /&amp;amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;<br />
// générateur de nombres aléatoires&amp;amp;amp;amp;lt;br /&amp;amp;amp;amp;gt;&amp;amp;amp;lt;br /&amp;amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;<br />
window.crypto.getRandomValues(new Uint32Array(10));&amp;amp;amp;amp;lt;br /&amp;amp;amp;amp;gt;&amp;amp;amp;lt;br /&amp;amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;<br />
// déchiffrage d’un message en précisant une clé et un algorithme&amp;amp;amp;amp;lt;br /&amp;amp;amp;amp;gt;&amp;amp;amp;lt;br /&amp;amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;<br />
var iv = window.crypto.getRandomValues(new Uint8Array(16))&amp;amp;amp;amp;lt;br /&amp;amp;amp;amp;gt;&amp;amp;amp;lt;br /&amp;amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;<br />
var algo {&amp;amp;amp;amp;lt;br /&amp;amp;amp;amp;gt;&amp;amp;amp;lt;br /&amp;amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;<br />
 name: &amp;amp;amp;amp;amp;quot;AES-GCM&amp;amp;amp;amp;amp;quot;,&amp;amp;amp;amp;lt;br /&amp;amp;amp;amp;gt;&amp;amp;amp;lt;br /&amp;amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;<br />
 iv: iv&amp;amp;amp;amp;lt;br /&amp;amp;amp;amp;gt;&amp;amp;amp;lt;br /&amp;amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;<br />
}&amp;amp;amp;amp;lt;br /&amp;amp;amp;amp;gt;&amp;amp;amp;lt;br /&amp;amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;<br />
return window.crypto.subtle.decrypt(algo, key, message);

Nonobstant les quelques limitations de cette jeune API, il est désormais possible de faire du chiffrage dans notre navigateur web, et la plupart des algorithmes communément utilisés sont proposés. De plus, l’API est gelée, et permet donc d’être utilisée sans être obligé de revoir son code après chaque montée de version du navigateur.

Concernant les limitations, cette recommandation du W3C :

  • ne nous dispense pas de devoir faire confiance à l’application web,
  • n’est pas encore disponible sur tous les navigateurs (Can I Use Cryptography ?),
  • n’est pas non plus utilisable avec les cartes à puces,
  • ne permet pas encore de chiffrer de gros objets (streaming),
  • ne propose pas tous les algorithmes de chiffrement
Le conseil avisé de notre speaker : plutôt que de faire de l’à-peu-près, si l"on doit utiliser WebCrypto sur un projet, mieux vaut demander conseil, ou effectuer un audit le cas échéant.

Circuit Breaker Pattern

Ou comment accroître la tolérance d’un système aux pannes (par Mouhcine Moulou)

Combien de fois a-t-on buté sur des problématiques de timeouts qui nous font perdre non seulement un temps précieux, mais qui - et c’est terrible - se terminent régulièrement en exception… Exceptions qui sont en général brutalement stoppées dans leur élan (pas l’animal) par de gros try-catchs poilus, vraiment.
A l’image d’un disjoncteur qui coupe le courant pour empêcher la propagation d’une panne à tout une installation électrique, le Pattern Circuit Breaker fait office de proxy qui n’appelle plus les services si ces derniers sont tombés sur le champ de bataille.

Exemple de code Java utilisant ce pattern :

// utilisation de l&amp;amp;amp;amp;quot;implémentation d&amp;amp;amp;amp;quot;Akka&amp;amp;amp;amp;lt;br /&amp;amp;amp;amp;gt;&amp;amp;amp;lt;br /&amp;amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;<br />
CircuitBreaker breaker = new CircuitBreaker(...);&amp;amp;amp;amp;lt;br /&amp;amp;amp;amp;gt;&amp;amp;amp;lt;br /&amp;amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;<br />
breaker.callWithCircuitBreaker( new Callable&amp;amp;amp;amp;amp;lt;Future&amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;gt;() { ... } );

 

Le breaker connaît l’état du service cible grâce à plusieurs règles paramétrables, telles que le “max-failures”. Si ce “max-failures” est atteint, le breaker s’ouvre et retourne immédiatement une exception à chaque appel. On nomme ce principe le “let-it-crash”. Provoquer nous même un échec nous permet d’effectuer un “handle-with-grace” de l’exception.

Après une durée appelée “reset-timeout” à l’état open, le Circuit Breaker se met dans un état dit “half-open” où il laisse passer un appel vers le service tiers, pour tâter le terrain.

Si le service est de nouveau disponible, le Breaker se referme et les appels ne sont plus interrompus prématurément. Au contraire, si l’appel échoue, le Breaker se rouvre, et ainsi de suite.

 

(source : http://doc.akka.io/docs/akka/snapshot/common/circuitbreaker.html)

 

Ce Pattern semble convenir plus particulièrement à des architectures type “micro-services”, au sein desquelles le système doit rester réactif malgré la multiplication des briques. En outre, il offre aussi la possibilité d’y connecter des outils de monitoring, selon l’API utilisée. On ne va pas se mentir, un tel pattern nous permet avant tout d’économiser des ressources (essentiellement mémoire) et de répondre plus rapidement au client en attendant la remise en route du servie sous-jacent.

Lors de la session de questions, on apprend que l’implémentation d’Akka ne nous permet pas de filtrer les exceptions levées par les services selon leur type (technique ou fonctionnel).

Ainsi, mettre un Circuit Breaker pour des appels à une base de données peut se révéler contre productif : si les Exceptions sont d’ordre technique (ConstraintException par exemple), le Breaker pourrait s’ouvrir alors que le service est totalement opérationnel.

Le speaker indique qu’un Circuit Breaker doit être utilisé pour “disjoncter” les appels d"un seul et unique service. Il ne doit absolument pas être mutualisé : pour deux services utilisant le même Breaker, si l’un tombe, l’autre en pâtit.

Le speaker précise également que ce pattern permet d’éviter le Cascading Failure, c’est à dire l’effet domino et la perte des services s’appelant consécutivement lorsque les erreurs sont mal gérées.

 

Faire tourner une JVM avec 4To de mémoire

Ou comment gérer la mémoire en Java sans native behaviors (par Gaëlle Guimezanes)

La speakerine commence sa présentation en nous introduisant directement dans le contexte : comment faire monter en mémoire vive une montagne de données (600 millions de tuples et 50 colonnes) relatives à des trades sur des marchés financiers ? Pour corser le tout, on se fixe comme contrainte de conserver Java comme unique langage de programmation.

C’est justement ce que nous explique Gaëlle, à travers une base de données “in-memory” qu’elle développe.

Sur une JVM traditionnelle, et en utilisant de la mémoire “on-heap” garbage collectée, dès les quelques premiers gigas de données chargées en RAM l"expérience touche rapidement à sa fin. En effet, le GC (Garbage Collector) se déclenche… La JVM explose sous le nombre de déplacements de références (Young vers Old Generation) et autres optimisations qui s’avèrent contre productives dans notre cas d’utilisation. En fait, le GC ne sait pas gérer de tels volumes de données. De plus, nous souhaitons stocker de gros objets, pour une longue durée (le propre d’une base de données), ce qui va à l’encontre de "l’hypothèse générationnelle faible", et ce n’est pas forcément ce que préfère le GC.

Nous sommes donc contraints de sortir de la zone de mémoire scrutée par le GC. Il est nécessaire de pénétrer dans un univers hostile, le “off-heap”.

Une utilisation naïve de l’API nous fait choisir en premier lieu un ByteBuffer(http://docs.oracle.com/javase/6/docs/api/java/nio/ByteBuffer.html), capable de retourner un pointeur sur une zone “off-heap”. Dès lors, une limitation de taille nous est imposée : il est impossible de stocker des objets (sérialisés ou non), on doit se contenter de caractères ou d’entiers primitifs. Un avantage tout de même à cette solution, la mémoire est allouée dans une zone située au plus proche du processeur.

Néanmoins, une fois encore, certaines optimisations de Java créent de l"overhead et nous mettent des bâtons dans les roues (la conversion en Little / Big Endian des octets en fonction du système hôte, par exemple).

Sitôt abandonnés les ByteBuffers, une nouvelle classe attire notre attention : Unsafe(http://www.docjar.com/docs/api/sun/misc/Unsafe.html). Pour allouer de la mémoire, à la manière de C, mais cela reste moins indigeste qu’en assembleur (décalage de bits, bonsoir !).

Comment récupérer une instance d’Unsafe de manière tout à fait unsafe ?

// récupération du singleton d&amp;amp;amp;amp;quot;Unsafe par reflexion&amp;amp;amp;amp;lt;br /&amp;amp;amp;amp;gt;&amp;amp;amp;lt;br /&amp;amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;<br />
Field f = Unsafe.class.getDeclaredField(&amp;amp;amp;amp;amp;quot;theUnsafe&amp;amp;amp;amp;amp;quot;);&amp;amp;amp;amp;lt;br /&amp;amp;amp;amp;gt;&amp;amp;amp;lt;br /&amp;amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;<br />
f.setAccessible(true);&amp;amp;amp;amp;lt;br /&amp;amp;amp;amp;gt;&amp;amp;amp;lt;br /&amp;amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;<br />
Unsafe unsafe = (Unsafe) f.get(null);

Gaëlle nous fait rêver !

Une fois récupérée ladite instance d’Unsafe, nous quittons l’univers Java bisounours où allouer une zone mémoire relève de la magie. On affecte désormais des valeurs directement via des adresses “physiques” en mémoire, avec tous les crashs que cela peut engendrer.

Maintenant que nous sommes en mesure de gérer la mémoire, il nous faut optimiser les calculs. En effet, un processeur pouvant servir plusieurs mémoires vives, d’énormes quantités de données s’engouffrent dans un entonnoir pour s’y coincer lamentablement.

Pour pallier ce problème, Gaëlle utilise un système NUMA (Non Uniform Memory Access) intégré dans un Bullion (http://www.bull.fr/bullion/), machine dopée aux EPO prêtée pour l’occasion par l’entreprise Bull. Lance Armstrong lui-même n’a jamais pris autant de substances dopantes. Sur cette architecture particulière, chaque processeur est servi par une mémoire distribuée. Le couple processeur / mémoire est géré par un Thread qui lui est propre.

En chiffres :

3 minutes : c’est la durée totale d’une requête en NUMA. Il faut compter 1,5 à 3 fois plus de temps pour exécuter cette même requête sur une architecture non NUMA.

10 heures : c’est le temps que prend le garbage collector si 2 To de données sont stockées On-Heap et 3 secondes Off-Heap.

1h20 : c’est le temps qu’il nous faut pour charger presque 4 To de données.

Le défi est relevé, la solution proposée permet d’obtenir des résultats bluffants malgré l’utilisation de Java, notoirement connu pour sa gourmandise en terme de mémoire.

Mais que se passe-t-il en cas de panne ? Il s’avère que chaque calcul est loggué, cette fois ci sur un disque bien dur, ce qui permet de remettre la machine en route et de recharger les données dans l’état ou elles étaient avant le plantage. Il est également possible de repartir de zéro depuis une base de données aggrégées du fournisseur. Dans ce cas on a le temps d’aller prendre un, voire plusieurs cafés, et d’envoyer quelques tweets.

Booster les dev’ avec SpringBoot

Ou comment éviter de trop se soucier de la configuration (par Julien Sadaoui)

Durant cette présentation, on survole rapidement Spring Boot (http://projects.spring.io/spring-boot/) et son principe fondateur : la convention c’est bien, la configuration c’est mal. Il était temps !

Le speaker démarre la présentation en nous montrant une configuration de dépendances Maven pour un projet Spring. Il demande si quelqu’un dans la salle a déjà eu à affronter ce plat de spaghettis. Évidemment, les mains se lèvent.

Pour pallier aux défauts inhérents à Spring, Spring Boot apporte de nombreuses nouveautés :

La première d’entre elles est l’apparition de dépendances starters qui vont remonter pour nous les dépendances tierces. L’avantage principal est que Spring nous certifie que ces versions de dépendances sont testées s’intègrent parfaitement avec la version de Spring utilisée.
Par exemple, le starter spring-data-jpa va remonter Hibernate avec une version sélectionnée aux petits oignons.

Ensuite, le framework va nous apporter tout un tas de configurations par défaut, qu’il nous suffit de surcharger à l’envie, ou d’activer via des annotations salvatrices.

Un autre de ses avantages est qu’il nous permet de tester facilement nos applications. Il propose un ensemble d’outils et de classes pour faciliter l’écriture et la mise en place de tests d’intégration de bout en bout.

Enfin, Spring Boot expose un certain nombre de services REST pour inspecter l’état d’une application en cours d"exécution, parmi lesquels : /beans /env /info /metrics /trace.

Pour les amateurs de Spring pour le web, Spring Boot embarque automatiquement un Tomcat ou un Jetty, sans qu’il ne soit nécessaire de l’installer soi-même. Un gros plus pour bootstrapper rapidement un projet “from scratch”.

Monitorer sa consommation d"électricité : avec un Raspberry Pi, ActiveMQ, MongoDB et Docker

Ou comment court-circuiter légalement les factures EDF annuelles (par Cédric Finance)

 

Première étape : la connexion au compteur

On peut brancher simplement le Raspberry Pi sur le compteur, c’est légal, et ça se fait via un port série. Muni d’un émetteur wi-fi, de quelques résistances et d’un fer à souder, notre bidouilleur en herbe peut désormais récupérer de jolies données sous la forme :

[none ]HCHP 001521211 "
PTEC HC.. S
IINST 001 I
IMAX 008 2
PMAX 06030 3
PAPP 01250
...[/none]

 

Seconde étape : le stockage / affichage des données

Dans un premier temps, on stocke les données sur Thingspeak (https://thingspeak.com/). L’outil à la gentillesse de nous apporter une interface de consultation agréable sous la forme de graphiques. Mais très vite Cédric veut pousser l’exercice un cran plus haut.

Ce qui ressemblait jusqu’alors à un passe temps nous fait désormais penser à un projet viable et quasi vendable. Il faudrait juste penser à remplacer la boîte à chaussures dans laquelle se trouve le Raspberry Pi.

A partir de ce moment là, Cédric a été capable de détecter une anomalie sur son installation électrique. Un abominable chauffe-eau se mettait inutilement en route pendant son absence. Ni une, ni deux, Cédric s’empare d’un câble, d’un marteau et d’une tronçonneuse pour entailler la bête et lui faire une opération à coeur ouvert.

 

Troisième étape : l’analyse des données

On abandonne Thingspeak. Les données sont envoyées vers ActiveMQ qui va stocker tout ça dans une base de donnée Mongo via un “subscriber”. L"ensemble de ce micro-système est encapsulé dans un conteneur Docker.

Il ne reste plus à Cédric que d"implémenter sa propre interface de monitoring, capable d’aller lire les informations reçues en temps réel.

On peut imaginer de nombreuses applications à ce petit dispositif ingénieux, et même simplifier ce dernier en remplaçant le Raspberry Pi par un Spark Photon.

On peut aussi imaginer de nombreuses améliorations possibles. Cédric nous en cite quelques-unes, qui sont dans la Roadmap… graphes en fonction des périodes ; interpolation des données manquantes ; calcul du coût relatif à la consommation réelle ; ajout de Docker Compose.

 

Applications du type Optional

Ou “Apprendre à coder en Java 8, pour les nuls” (par Fabrice Sznajderman)

 

Pour tous les briscards du code Java, un tel bout de code représente le mal, le vrai Malin, le suppôt de Satan du code :

if (contact == null) {&amp;amp;amp;amp;lt;br /&amp;amp;amp;amp;gt;&amp;amp;amp;lt;br /&amp;amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;<br />
 ...&amp;amp;amp;amp;lt;br /&amp;amp;amp;amp;gt;&amp;amp;amp;lt;br /&amp;amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;<br />
}

 

Les checks-null : la terreur des mappers ! Et ça, on n’en veut plus. On veut du code qui soit porteur de sens, et pas du code qui nous protège contre Satan en personne : les NullPointerExceptions.

Ce genre de code n’a aucune utilité métier et pollue souvent la lisibilité des méthodes.

Pour se débarrasser de tels bouts de code, il est possible d’utiliser le type Optional (http://docs.oracle.com/javase/8/docs/api/java/util/Optional.html). Il s’agit d’un type monadique : le speaker nous explique cette notion abstraite comme étant une espèce de capsule permettant d’appliquer des primitives sur son contenu, indifféremment du type de contenu (chaînes de caractères, entiers, ou même des fonctions).

Grâce à la magie des Optional, on peut se débarrasser des checks-null.

Pour sa session de live-coding, Fabrice a choisi un exemple de la vie courante en proposant un service de Contact exploitant un repository. La méthode findById(long id), avant le refactoring, renvoie un Contact.

Que se passe t-il si l’Id ne correspond à aucun contact ? La méthode retourne null !

En refactorant la méthode de cette manière :

public Optional&amp;amp;amp;amp;amp;lt;Contact&amp;amp;amp;amp;amp;gt; findById(long id) {&amp;amp;amp;amp;lt;br /&amp;amp;amp;amp;gt;&amp;amp;amp;lt;br /&amp;amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;<br />
 return Optional.ofNullable(contactRepository.findById(id));&amp;amp;amp;amp;lt;br /&amp;amp;amp;amp;gt;&amp;amp;amp;lt;br /&amp;amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;<br />
}

 

On s’assure ainsi que la méthode renverra uns structure de données représentant une valeur potentiellement absente.

Il nous reste plus qu’à utiliser l’Optional dans notre méthode appelante :

Optional&amp;amp;amp;amp;amp;lt;Contact&amp;amp;amp;amp;amp;gt; optional = contactService.findById(5);&amp;amp;amp;amp;lt;br /&amp;amp;amp;amp;gt;&amp;amp;amp;lt;br /&amp;amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;<br />
if (optional.isPresent()) {&amp;amp;amp;amp;lt;br /&amp;amp;amp;amp;gt;&amp;amp;amp;lt;br /&amp;amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;<br />
 System.out.println(“Le contact a ” optional.get().getAge() “ ans”);&amp;amp;amp;amp;lt;br /&amp;amp;amp;amp;gt;&amp;amp;amp;lt;br /&amp;amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;<br />
} else {&amp;amp;amp;amp;lt;br /&amp;amp;amp;amp;gt;&amp;amp;amp;lt;br /&amp;amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;<br />
 System.out.println(“Le contact n’a pas été trouvé”);&amp;amp;amp;amp;lt;br /&amp;amp;amp;amp;gt;&amp;amp;amp;lt;br /&amp;amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;<br />
}

 

Cependant, même si le pattern if-null a disparu, la structure conditionnelle est toujours présente et continue de polluer le code.

On peut donc pousser l’exercice un cran au dessus et frôler la perfection en appliquant un petit trait fonctionnel à un langage des plus impératifs :

Optional&amp;amp;amp;amp;amp;lt;String&amp;amp;amp;amp;amp;gt; message = optional.map(c -&amp;amp;amp;amp;amp;gt; “La contact a ” c.getAge() “ ans”).orElse(“Le contact n’a pas été trouvé”);&amp;amp;amp;amp;lt;br /&amp;amp;amp;amp;gt;&amp;amp;amp;lt;br /&amp;amp;amp;gt;&amp;amp;lt;br /&amp;amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;<br />
System.out.println(message.get());

 

Cette portion de code permet de transformer un Optional<Contact> en Optional<String>, en conditionnant la chaîne de caractère à la présence d’un contact ou non. Si le contact est présent, on affiche une chaîne contenant son âge, sinon on affiche un message arbitraire. On élimine ainsi toutes les fioritures techniques, et la fluent API permet de lire le code aussi simplement qu’une phrase !

Pour ceux qui voudraient bénéficier de cet objet magique sur leurs projets préhistoriques en Java 7, Guava (https://github.com/google/guava) propose une implémentation assez proche de celle présente dans Java 8, à l’instar de la relation entre JodaTime (http://www.joda.org/joda-time/) et la nouvelle API java.time.

Le type Optional permet donc de représenter une valeur potentiellement absente. Le speaker a également précisé que ce type permettait également de documenter automatiquement le code. En effet, plutôt que d’avoir un commentaire erroné du type “cette méthode ne renverra jamais null”, la sémantique même du type Optional permet de renseigner le développeur sur le fait que la méthode peut, potentiellement, ne pas renvoyer de valeur utile. Et le tout de manière typée !

 

Ce que nous retiendrons de cette soirée

Nous avons pu assister à une soirée somme tout agréable, avec des talks et des speakers de qualité. L’ensemble était très bien organisé et bien mené par les organisateurs, qui ont ponctué les présentations de petits interludes croustillants.

Portant sur des sujets très hétérogènes, il est difficile de classer toutes les présentations les unes par rapport aux autres. Il nous est tout de même possible d’élire notre TOP 2 : la JVM surboostée et le Raspberry-Pi survolté. C’est d’ailleurs ce dernier talk, présenté par Cédric Finance, qui a remporté le vote du public. Il aura l’opportunité de présenter son installation à Devoxx 2015 (http://www.devoxx.fr/).

Ce format, à l’instar des Human Talks, permet en peu de temps de parcourir un ensemble de sujets hétérogènes. Nous avons maintenant hâte de découvrir ce que nous réserve la prochaine édition !

Alexandre Hebert

Développeur Full Stack depuis 3 ans, Alexandre a une connaissance approfondie de nombreux langages et frameworks. Curieux de comprendre le "comment ça fonctionne" plutôt que de simplement "utiliser", c'est avec cet état d'esprit qu'il évolue depuis plusieurs mois au sein d'une équipe agile de Xebia.

Retrouvez-le sur http://a1exand.re, et sur son compte twitter @dijxdream.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *