Java 8 : Design Pattern pour Lambda
Presque 2 ans après la sortie de Java 8, l’engouement pour les lambdas n’est pas retombé, comme j’ai pu le constater lors de la conférence Devoxx Belgique en Novembre dernier. Par contre, au vu des présentations, le focus a changé. On est passé du « Comment ça marche ? » au « Quand les utiliser ? ».
Si vous venez comme moi d’un background orienté objet, vos débuts avec les lambdas seront sûrement timides. Vous commencerez par vous attaquer aux interfaces ActionListener, et autres Runnable. Lentement, un pattern va s’imposer : le corps de la méthode se retrouvera dans la classe container, et les lambdas seront remplacés par des références de méthodes :
Quand la syntaxe des lambdas est maitrisée, on s’attaquera à l’API Stream. Commence alors une chasse dont les boucles sont les victimes :
Devient :
Arrive enfin le point critique où l’on se dit: “Et maintenant quoi?”. Lorsque je découvrais les joies de la programmation orienté objet (ça date un peu, mais j’en ai encore quelques souvenirs), ma progression a suivi plus ou moins les étapes suivantes :
- Identité : les objets sont comme des structures avec des méthodes à l’intérieur.
- Encapsulation : on cache les détails d’implémentation et le format des données du monde extérieur.
- Héritage : on construit de hiérarchies de classe pour éviter de récrire du code.
- Polymorphisme : on exploite enfin toute la puissance des objets.
- Design Patterns : on apprend les différents motifs d’organisation des objets.
- La Sagesse : on apprend quand ne pas utiliser les Design Patterns.
J’émets donc l’hypothèse que l’apprentissage des lambdas suivra une progression similaire :
- Interface Fonctionnelle : on remplace des classes anonymes par des lambdas.
- Référence de méthodes : on remplace certains lambdas par des références de méthodes.
- Stream : on remplace des boucles par des streams.
- Design Patterns : on organise des lambdas entres eux, comme pour les objets à l’époque.
- La Sagesse
Jusque-là, j’avais franchi les trois premières étapes de ma petite liste. Seulement voilà, comment franchir l’étape suivante ? C’est dans cet état d’esprit que j’arrive à Devoxx Belgique, pour me rendre compte que je suis loin d’être la seule personne atteinte de blocus fonctionnellitus.
Et justement, trois présentations traitent de ce sujet : « Design Patterns Reloaded » de Rémi Forax, « Design Patterns in the Light of Lambda Expressions » de Venkat Subramaniam, et « From object oriented to functional domain modelling » de Mario Fusco (toutes trois disponibles gratuitement sur YouTube). Ces trois présentations partent du bon vieux bouquin « Design Patterns, Elements of Reusable Object-Oriented Software » de Gamma et Helm(1994). L’idée est de reprendre ces Patterns que nous connaissons tous, et de voir comment les implémenter avec des lambdas.
Certains Patterns coulent de source. Par exemple, le Pattern Command est le cas de base des lambdas :
De même, le Pattern Iterator est très simple avec les nouvelles méthodes de Java 8 :
Le Pattern Factory est tout aussi évident quand on se rend compte qu’un constructeur est une implémentation d’un Supplier :
Certains autres Patterns proviennent directement des langages de programmation fonctionnelle. Par exemple, le Pattern Decorator peut facilement être implémenté grâce à la composition de fonctions :
La curryfication, ou application partielle de paramètre, n’est rien d’autre que le Pattern Adapter déguisé :
Enfin, plus loin que les Design Patterns objets, on peut apprendre au long de ces présentations, que les lambdas offrent certaines possibilités intéressantes. Entre autres, les lambdas permettent de déférer l’exécution de code. Cela nous permet de résoudre le vieux problème de l’œuf et de la poule. Comment créer un Œuf qui prend une Poule en paramètre de son constructeur, qui elle-même nécessite la présence de l’œuf dans le sien ?
Une autre possibilité intéressante est la faculté des références de méthodes à transformer une interface fonctionnelle en une autre, à condition qu’elles aient la même signature :
Maintenant que la porte du niveau Design Pattern est grande ouverte, il nous faut acquérir l’expérience pour atteindre le niveau de la Sagesse. Pour cela, il nous faut expérimenter, s’essayer à différentes applications des lambdas, en bref s’amuser avec, pour pouvoir dire dans quels cas ils nous apportent quelque chose de positif, et dans quels cas, au contraire, compliquent-ils le code inutilement. A vous de jouer.