Par une journée du début du mois d’octobre 2012, les xebians (ainsi que quelques invités) se sont une nouvelle fois réunis dans le cadre d’un de leur fameux XKE dont eux seuls ont le secret. Cette édition d’automne fut marquée par une session-débat autour de Java 8 et plus précisément sur le « Project lambda ». Le titre de la session était volontairement provocateur : « Les lambda de java 8 vont-ils changer la face du monde ? »
Contexte et objectif
Java 8 devrait sortir d’ici moins d’un an. Cette version verra notamment l’arrivée de la programmation fonctionnelle dans le langage. C’est le Project Lambda (JSR335) dirigé par Brian Goetz qui se charge de cette intégration. Les changements qu’apporte ce projet sont particulièrement impactants à la fois pour le JDK et la syntaxe du langage.
Sur ce blog, nous avons déjà plusieurs fois parlé du Project Lambda. Si vous souhaitez rafraîchir votre mémoire par rapport au Project Lambda, nous vous proposons les liens suivants :
- « Les lambda expressions dans Java 8″. 20 septembre 2011. http://blog.xebia.fr/2011/09/20/les-lambda-expressions-dans-java-8/
- « Les méthodes virtuelles d’extension dans Java 8″. 5 octobre 2011. http://blog.xebia.fr/2011/10/05/les-methodes-virtuelles-dextension-dans-java-8/
- « Quizz Java 8″. 12 juillet 2012. http://blog.xebia.fr/2012/07/12/quizz-java-8/
- « Solution du Quizz Java 8″. 17 juillet 2012. http://blog.xebia.fr/2012/07/17/solution-du-quizz-java-8/
L’objectif de la session de XKE était de tenter de répondre à une question : « Quelle sera l’impact du Project Lambda sur le monde de Java ? » Comprenez par là que Project Lambda est en train de créer un nouveau Java assez différent de ce que nous avons connu jusque là. Les modifications seront encore plus impressionnantes que ce que nous avons vécu lors de l’arrivée des inner classes, des generics ou du for each. Par conséquent, la question est : est-ce que les modifications apportées par Project Lambda finiront par être adoptées par le monde Java — ce qui inclut la communauté et les projets en entreprise —, finiront-elles par être rejetées par celui-ci ou bien assisterons-nous à un certain degré d’adoption/rejet ?
Forces en présence
Lors de cette session autour du projet lambda de Java 8, 16 personnes étaient présentes, dont l’un de nos deux directeurs techniques et moi-même. Globalement, l’auditoire était composé de javaïstes avec une expérience variant entre 2 ans jusqu’à 10 ans et bien plus. Plusieurs parmi eux ont même des connaissances dans des langages intégrant d’autres paradigmes de programmation.
L’auditoire de la session en pleine revue de la rétrospective (photo et montage par @morlhon)
Détail de la session
La session avait la particularité singulière (#pleonasme) de s’articuler autour d’une présentation suivie de quelques séquences de code in vivo et débats, puis pour finir d’une rétrospective dans la plus pure tradition agile. Dès le départ de la session, l’auditoire était prévenu que l’objectif de la session était de décorer avec des post-it, façon sapin de Noël, le speed car servant de support à la rétrospective, en trois heures seulement. Et ils étaient prévenus que ce qui ressortirai de cette rétrospective irait directement alimenter l’article que vous lisez actuellement, ainsi que la mailing du projet lambda de Java 8.
Présentation
La présentation de la session sur le Project Lambda était composée :
- D’une introduction
- D’une section présentant le contexte dans lequel s’inscrit Project Lambda (exploitation des architectures multi-core et amélioration de la productivité du développeur) et les motivations
- D’une section présentant les lambda expressions dans Java 8, les méthodes virtuelles d’extension, ainsi que les références à des méthodes, l’extension de l’API collection et la facilité avec laquelle il sera possible de paralléliser ses traitements
- D’une section présentant les membres de Project Lambda, les différents sites Web / mailing list et leur utilité, les quelques passionnés qui participent à la promotion de produit de Project Lambda et enfin mon appréciation sur la relation entre Project Lambda et la communauté (transparence, possibilité de tester des pré-versions et voir le code, réaction rapide des membres de Project Lambda sur la mailing list le tout dans un bon esprit, etc.)
Séance de code in vivo et débat
La séance de code en live était composée d’un ensemble d’exercices basé sur des tests unitaires. Les trois premiers exercices montraient la différence entre Java impératif, Guava et l’utilisation des lambda expressions dans Java 8 pour exploiter des collections. Par la suite, nous avons vu que les lambda expressions permettent d’exprimer les notions de call by value et call by name dans les appels de méthodes.
Un kata reprenait un exercice proposé par Martin Odersky (le créateur de Scala) au ScalaDays’2011. Sachant que chaque touche d’un téléphone est associé à des mnémoniques (pour la touche 2 vous avez les mnémoniques A, B et C), le kata a pour objectif de reproduire le comportement de l’auto-complétion lorsque vous écrivez vos SMS : en associant à chaque combinaison de touches un ensemble de mots possibles. Vous trouverez sur github la solution qui a été développée.
Nous avons vu par la suite un ensemble d’exercices autour des méthodes d’extension virtuelles, leur utilité et la façon de résoudre le problème du diamant. Était présenté aussi, l’optimisation faite pour les lambda expressions indépendantes de l’état du reste de l’application. Et nous avons terminé en faisant un test de rapidité sur le traitement de grandes collections en utilisant d’un côté les opérations séquentielles et de l’autre les opérations parallèles. Nous avons constaté que sur un architecture quad-core, le gain en performance va du simple au double.
Cette partie de la session a celle qui a le plus amené l’auditoire à réagir. Et les réactions étaient assez riches en questions, en réflexions, en challenges et… en trolls. La partie code et débat est parmi les autres parties celle qui a certainement le plus amené l’auditoire à se faire une idée de ce que sera le futur Java 8 et à partager les points de vue.
À titre d’information, la code produit lors de la session est disponible sur github.
Rétrospective
La rétrospective était basée sur un Speed Car. Le speed car raconte l’histoire d’un pilote qui s’est trouvé une voiture aussi puissante que possible. L’objectif du pilote est de traverser un pont très rapidement sans que celui-ci s’écroule. S’il arrive au bout du pont c’est la réussite de son projet.
Le Speed Car utilisé pendant la session
Il s’agit bien sûr ici d’une métaphore. L’ensemble voiture-parachute représente le Lambda Project au présent, avec sa syntaxe, sa nouvelle API et la façon dont est géré le projet. Plus exactement, la voiture correspond à ce qui est moteur dans le projet et le parachute à ce qui freine. De l’autre côté du schéma, l’ensemble pont-ravin représente l’avenir du Lambda Project. Autrement dit, le pont représente le soutien de la communauté et l’adoption dans les projets par rapport à ce qu’apporte le projet. Au contraire, le ravin représente un rejet partiel voir total des nouveautés de Java 8.
Résultat de la rétrospective en photo
Résultat au niveau du Speed Car et du parachute
Résultat au niveau du pont
Résultat au niveau du ravin
Résultat de la rétrospective et de l’ensemble de la session
En conclusion de la session, voici les points qui sont principalement ressortis.
Établir un guide des bonnes pratiques
Java 8 vient avec de nouvelles évolutions. Ces évolutions aideront le développeur à être productif. Mais il y a fort à parier que de mauvaises pratiques se répandront, surtout parce que les développeurs ne sauront pas exactement comment bien utiliser les évolutions de Java 8. Dans l’idéal, il faudrait pouvoir guider les développeurs en diffusant des best practices.
Appréciation de la syntaxe simplifiée mais pas pour tout le monde ni pour tout
La simplification de la syntaxe est globalement appréciée par l’auditoire. Mais il ressortait que plus de simplification pour les expressions chaînées serait appréciable. Typiquement, devoir faire appel à la méthode map
pour effectuer une transformation préalable avant de pouvoir appeler reduce
est perçu comme une lourdeur. De même pour l’appel intermédiaire à stream
: pourquoi ne pas mettre les opérations directement dans les collections ?
Plutôt que d’avoir :
Streams.stream(myCollection) .map(product -> product.getUnitPrice() * product.getQuantity()) .reduce(0.0, (subTotal, price) -> subTotal + price)
Certains auraient préféré :
myCollection.reduce(0.0, (subTotal, price) -> subTotal + product.getUnitPrice() * product.getQuantity())
Il y a eu des remarques sur l’absence de paramètres implicites comme it
en Groovy ou _ en Scala.
Enfin, certains trouvent le code peu lisible, en particulier dans le cas de la succession de map
et reduce
.
Les méthodes virtuelles d’extension
Les virtual extension methods représentent un moyen d’étendre les API existantes du JDK sans obliger les frameworks et applications réimplémentant ces API de devoir aussi réimplémenter les extensions. Par exemple, l’API collection de Java se voit dotée de nouvelles méthodes pour pouvoir effectuer des opérations sur des lots de données et pour pouvoir le faire en traitements parallélisés. Avec les méthodes virtuelles d’extension, Hibernate ne sera pas obligé de réimplémenter toutes ces nouvelles fonctionnalités pour ses PersistentCollection.
Néanmoins, est-ce que les méthodes virtuelles d’extension ne vont pas introduire de nouvelles confusions ? Par exemple, il est possible de fournir une implémentation par défaut à une méthode m
d’une interface et ne pas obliger les sous-classes de cette interface à implémenter m
. Par héritage, on peut retirer cette implémentation par défaut dans une sous-interface et forcer les sous-classes à fournir une implémentation de m
. Dans un arbre d’héritage, il est possible d’alterner entre implémentation par défaut ou pas.
Un autre point sur lequel le Project Lambda est attendu, c’est le fonctionnement de la Javadoc avec les méthodes virtuelles d’extension. Puisque les méthodes virtuelles d’extension introduisent du comportement dans les interfaces, la javadoc devient d’autant plus importante au niveau des interfaces. La javadoc a-t-elle bien suivie le mouvement ?
Troll
L’un des membres de l’auditoire a fait remarquer qu’il y aura immanquablement un maximum de trolls de la part des programmeurs spécialisés dans la programmation fonctionnelle. Ce à quoi un autre membre a indirectement répondu en précisant que le troll ferait de la publicité à Java 8 et favoriserait son adoption en attisant la curiosité.
Autres points
- Certains pensent que les lambda dans Java 8 arrivent trop tard, d’autres solutions concurrentes existent déjà : Scala, Groovy et même Guava pour la partie Collection API.
- Les lambda sont d’une certaine manière des anonymous inner class et n’ont pas de type dédié. On ressent trop le passif de Java.
- Le debug semble difficile sur les chaînages d’appel de méthodes (par exemple, comment déboguer
filter(x -> ...).map(y -> ...).reduce((u, v) -> ...)
). - Il serait intéressant d’obtenir les résultats d’un benchmark sur les différences entre les stream séquentielles et les stream parallèles.
- Java 8 introduit de nouvelles syntaxes. Est-ce que cela augmente la durée de la compilation ?
Conclusion
Une session de XKE qui s’est particulièrement bien passée. Même si quelques trolls ont fusé, l’ensemble des remarques étaient intéressantes et promptes à être rapportées. Les conclusions de cette session devraient faire l’objet d’un mail sur la mailing list du Project Lambda dans les jours à venir (http://mail.openjdk.java.net/mailman/listinfo/lambda-dev). Nous reviendrons vers vous dès que nous aurons reçu les réponses.
Annexe : Concernant le format de session choisi
Mes conclusions sur la session sont que le format de session que j’ai choisi est un format qui permet d’obtenir de riches réactions de la part des auditeurs, même si le temps imparti pour la session (trois heures) ne leur permet pas de maîtriser les tenants et aboutissants du sujet présenté. Ces réactions interviennent en particulier au moment de la partie live code. Pour le live coding, il est bon de diviser cette séquence en petits exercices basés sur des tests unitaires pour avoir des réactions sur des points précis de ce que vous voulez présenter. Si vous partez sur un exercice plus long, l’auditoire réagira surtout sur les derniers instants de l’exercice et moins sur les instants précédents. Autre point, il vaut mieux que les réactions soient d’abord orales avant d’être écrites. Les réactions orales vont souvent engendrer d’autres réactions amenant petit à petit à un débat. S’il est suffisamment bien encadré, le débat offre du coup un moyen de parfaire les argumentations et de diffuser les idées au sein d’un groupe. Là dessus, les réactions écrites restent nécessaires. Elles permettent d’avoir des réactions plus abouties, car l’écrit engage beaucoup plus la responsabilité, même si l’anonymat est respecté à terme. L’écrit permet aussi de « faire parler » les membres de l’auditoire les plus silencieux. Donc avec un format de session comprenant code en live avec de petits exercices et une rétrospective, on a un moyen de maximiser les réactions de l’auditoire.
Si je devais réitérer l’exercice, je diminuerais encore plus la partie présentation pour laisser plus de place au live coding, aux débats et à la rétrospective. Toutefois, je ne supprimerais pas complètement la présentation, car c’est une partie qui permet de donner le contexte dans lequel s’inscrit la session et de décrire ce qui motive la session. Enfin, tout ne peut pas être dit lors du live coding. C’est le cas, par exemple, lorsqu’il faut décrire la gestion d’un projet.
Bref, je vous pousse à reproduire l’expérience si vous vous posez des questions auxquelles vous ne pouvez pas répondre seul.