logo_mixitNous vous avons déjà parlé de la conférence Mix-it qui aura lieu le 5 avril à Lyon! Un délicieux mélange de Java et d’agilité, le tout avec un peu de NoSQL, d’HTML5, bref de quoi passer une excellente journée … Si vous hésitiez encore à venir, voici de quoi vous faire bondir sur les dernières places disponibles. Rencontre avec Laurent Petit et Christophe Grand, les speakers Clojure de Mix-it. Accrochez-vous! C’est parti pour un échange passionnant … Vous franchissez la frontière du monde merveilleux de Clojure …

Christophe Grand est consultant indépendant. Il est membre de la communauté Clojure de longue date, et un des contributeurs du langage. Il est également l’auteur de 2 librairies Clojure réputées, “Enlive” et “Moustache”. Il tient un blog, Clojure and me, contenant des informations “pointues” sur Clojure. Christophe est intervenu en tant que speaker à la première conférence Clojure en octobre 2010, et travaille actuellement sur un livre Clojure chez O’Reilly.

Laurent Petit est le développeur/sponsor principal du projet “Counterclockwise”, une extension de l’IDE Eclipse pour écrire des applications avec Clojure. Il a été séduit très tôt par Clojure et s’investit depuis dans sa communauté. Il est intervenu en tant que speaker à la première conférence Clojure en octobre 2010. Il a travaillé 8 ans en société de service, avant de rejoindre en 2008 la société Yseop, éditeur spécialisé dans l’industrialisation des activités de conseil pour la Relation Client.

Follow Christophe on Twitter Follow Laurent on Twitter

@cgrand@petitlaurent

Agnès : Vous êtes tous les deux développeurs java expérimentés, et un jour… vous êtes tombés dans la potion magique Clojure. Qu’est-ce qui vous y a poussé ? Quels super pouvoirs avez-vous depuis ? La potion est-elle vraiment magique ?

Christophe : en 1BC (Before Clojure) je travaillais sur un éditeur de texte collaboratif scripté avec Rhino (Javascript) et les limitations de cette solution (que j’avais déjà mise en œuvre par ailleurs) se sont faites encore plus cruelles dans un environnement aussi concurrent. Après ce projet je me suis mis en quête de mon sanglier à 5 pattes : un langage dynamique, pour la JVM, fonctionnel, concurrent et métaprogrammable (marre du code répétitif non refactorable).
J’étais prêt à sacrifier une patte de mon sanglier (ce qui m’offrait deux choix : Scala et Erlang) quand je suis tombé sur Clojure !
Tous les attributs souhaités et une communauté vibrante et accueillante emmenée par un project leader avec une vision claire, que demander de plus ?

Laurent : “Un seul langage vous manque, et tout est repeuplé !” A un moment où j’étais à un poste moins “technique” au travail, je suis parti à la découverte de tous ces autres langages, anciens ou récents, que l’hégémonie Java/C++/VB/PHP avait cachés à ma vue jusqu’alors. J’ai découvert les fondements de l’orienté objet avec Smalltalk et Eiffel, la programmation fonctionnelle avec Haskell, goûté aux langages multi-paradigmes avec Common Lisp, Scheme, Oz, Scala … Quelles merveilles ! Mais j’ai vraiment reçu mon coup de bouclier sur la tête lorsque j’ai découvert Clojure. J’ai eu le sentiment d’avoir trouvé une très bonne synthèse de tout ce qui m’avait plu dans les autres langages. Et ce sentiment ne m’a pas quitté depuis.
De même que la potion magique nécessite une sélection rigoureuse des feuilles de gui (exclusivement ramassées à la serpe), chaque caractéristique de Clojure a été soigneusement conçue dans un souci d’efficacité et d’orthogonalité avec le reste du langage.

Agnès : Clojure encourage un modèle de programmation fonctionnel. Qu’est-ce qui distingue ce modèle des autres, en particulier des langages impératifs, et notamment sur les questions du changement d’état et de la mutabilité des données ? Dans la programmation traditionnelle orientée objet, beaucoup de développeurs privilégient une approche impérative/procédurale. Quels sont les arguments pour les intéresser au développement fonctionnel, en quoi devront-ils modifier leur approche du développement ?

LaurentLa “brique de base”, c’est la fonction. Et par défaut, Clojure encourage à écrire des fonctions prenant en entrée et donnant en sortie des objets “immuables”, sans effet de bord sur d’autres aspects du système.
Il en résulte qu’il est plus facile de raisonner sur ces fonctions car elles ne dépendent pas, ni n’ont d’effet de bord sur d’autres parties du système. Plus il y aura de parties du code écrites ainsi, plus grande sera la base de code “résistante” à l’effet “spaghetti” où changer une partie du système a des effets (voulus ou non) sur d’autres parties.
Bien sûr, ce n’est qu’un paradigme, applicable dans tout langage. Clojure a juste la particularité d’encourager au maximum son utilisation.

Christophe : L’important est d’apprendre à penser en pipelines, un peu comme en Shell : le chaînage d’opérations élémentaires (les briques de base dont parle Laurent) amènent à des traitements complexes.
Ce qui est intéressant, c’est que ces opérations élémentaires sont autonomes et sont donc généralement très réutilisables et de fait très testées.
Par-dessus cela s’ajoutent les vertus de la composition, c’est à dire la capacité à construire des éléments de pipeline à partir d’autres éléments plus simples mais toujours aussi fiables.
Enfin, l’on trouve les “fonctions de haut niveau” qui ne sont rien d’autres que des éléments de pipeline paramétrés par d’autres fonctions, ce qui n’est rien d’autre qu’une variation très commune du pattern “stratégie”.
Bref l’on dispose de tout un arsenal pour exprimer nos pipelines de traitement d’une manière fiable, ce qui permet de se concentrer sur les points d’articulations entre les pipelines (c’est à dire là où l’on a des effets de bords : entrées/sorties diverses, accès aux bases de données, au réseau etc.),

Laurent : Tout à fait Thierry. Le classique livre sur les design patterns du GoF (Gang of Four) décrit le pattern “stratégie” comme un des plus puissants/souples des modèles de conception comportementaux. Mais indique que son implémentation est plus complexe que les autres, et qu’il faut donc réfléchir à 2 fois avant de l’employer.
C’est bien dommage, car à mes yeux c’est celui qui permet d’écrire du code le plus découplé et générique.
En Clojure, le pattern “stratégie” n’a pas le même “coût” qu’en Java. Il est trivial, il est idiomatique de l’utiliser. C’est une déclinaison de ce que les anglais appellent les “higher order functions”.

Christophe : Je dirais même plus : “fonctions de haut niveau” (je sens qu’à la fin de cette interview nous seront considérés comme les Dupont et Dupond de Clojure). Ce que vient de dire Laurent est très important : Clojure change les coûts relatifs de certaines décisions et aligne ainsi code facilement écrit et code bien conçu. Par exemple, en Clojure il faut faire des pieds et des mains pour écrire du code adhérent à un type concret, par défaut il est naturel de coder contre une abstraction, une interface.

Laurent : Ca me rappelle la partie du livre Agile Software Development – Principles, Patterns and Practices” de Robert C. Martin (aka “Uncle Bob”) où il parle des “Design smells”, et notamment celui de “viscosité”: “Viscosity, when it is hard to do the right thing”. Je trouve le langage Clojure beaucoup moins visqueux que le langage Java. En java, il est beaucoup plus facile, et au final beaucoup plus tentant, de choisir pour son algorithme une solution sous-optimale, car elle sera beaucoup plus facile à mettre en oeuvre.

Je ne vais pas chercher ici à faire dans l’original, et voici donc en exemple un cas d’école, la bonne gestion de la fermeture des ressources, en Java et en Clojure.

Java1: répéter dans le code le même pattern, encore et encore :

[[code]]czoxNzA4OlwiPHNwYW4gc3R5bGU9XFxcImNvbG9yOiMzYjZhYzhcXFwiPnB1YmxpYyBjbGFzczwvc3Bhbj4gRW5kTGVzc1BhdHRlcm5SZXBle1smKiZdfXRpdGlvbgo8c3BhbiBzdHlsZT1cXFwiY29sb3I6IzMyMzIzMlxcXCI+ezwvc3Bhbj4KICAgIDxzcGFuIHN0eWxlPVxcXCJjb2xvcjojM2I2YWN7WyYqJl19OFxcXCI+cHVibGljPC9zcGFuPiBTdHJpbmcgPHNwYW4gc3R5bGU9XFxcImNvbG9yOiNjNzNhNjlcXFwiPnJlYWRGaWxlPC9zcGFuPjxzcGFuIHtbJiomXX1zdHlsZT1cXFwiY29sb3I6IzMyMzIzMlxcXCI+KDwvc3Bhbj5GaWxlIGZpbGU8c3BhbiBzdHlsZT1cXFwiY29sb3I6IzMyMzIzMlxcXCI+KTwvc3B7WyYqJl19YW4+IDxzcGFuIHN0eWxlPVxcXCJjb2xvcjojM2I2YWM4XFxcIj50aHJvd3M8L3NwYW4+IElPRXhjZXB0aW9uCiAgICA8c3BhbiBzdHlsZT17WyYqJl19XFxcImNvbG9yOiMzMjMyMzJcXFwiPns8L3NwYW4+CiAgICAgICAgSW5wdXRTdHJlYW0gZmlzIDxzcGFuIHN0eWxlPVxcXCJjb2xvcjojMzIzMntbJiomXX0zMlxcXCI+PTwvc3Bhbj4gbnVsbDxzcGFuIHN0eWxlPVxcXCJjb2xvcjojMzIzMjMyXFxcIj47PC9zcGFuPgogICAgICAgIDxzcGFuIHN0eWxle1smKiZdfT1cXFwiY29sb3I6IzNiNmFjOFxcXCI+dHJ5PC9zcGFuPiA8c3BhbiBzdHlsZT1cXFwiY29sb3I6IzMyMzIzMlxcXCI+ezwvc3Bhbj4KICAgICAgIHtbJiomXX0gICAgIGZpcyA8c3BhbiBzdHlsZT1cXFwiY29sb3I6IzMyMzIzMlxcXCI+PTwvc3Bhbj4gPHNwYW4gc3R5bGU9XFxcImNvbG9yOiMzYjZhYzhcXHtbJiomXX1cIj5uZXc8L3NwYW4+IDxzcGFuIHN0eWxlPVxcXCJjb2xvcjojYzczYTY5XFxcIj5GaWxlSW5wdXRTdHJlYW08L3NwYW4+PHNwYW4gc3R5bGV7WyYqJl19PVxcXCJjb2xvcjojMzIzMjMyXFxcIj4oPC9zcGFuPmZpbGU8c3BhbiBzdHlsZT1cXFwiY29sb3I6IzMyMzIzMlxcXCI+KTs8L3NwYW4+CiAgICAge1smKiZdfSAgICAgICA8c3BhbiBzdHlsZT1cXFwiY29sb3I6IzMyMzIzMlxcXCI+Li4uPC9zcGFuPiBDb3JwcyBkZSBsYSBtw6l0aG9kZSA8c3BhbiBze1smKiZdfXR5bGU9XFxcImNvbG9yOiMzMjMyMzJcXFwiPi4uLjwvc3Bhbj4KICAgICAgICA8c3BhbiBzdHlsZT1cXFwiY29sb3I6IzMyMzIzMlxcXCI+fTwvc3tbJiomXX1wYW4+IDxzcGFuIHN0eWxlPVxcXCJjb2xvcjojM2I2YWM4XFxcIj5maW5hbGx5PC9zcGFuPiA8c3BhbiBzdHlsZT1cXFwiY29sb3I6IzMyMzIze1smKiZdfTJcXFwiPns8L3NwYW4+CiAgICAgICAgICAgIDxzcGFuIHN0eWxlPVxcXCJjb2xvcjojM2I2YWM4XFxcIj5pZjwvc3Bhbj4gPHNwYW4gc3R5bGV7WyYqJl19PVxcXCJjb2xvcjojMzIzMjMyXFxcIj4oPC9zcGFuPmZpcyA8c3BhbiBzdHlsZT1cXFwiY29sb3I6IzMyMzIzMlxcXCI+IT08L3NwYW4+IG51bGw8e1smKiZdfXNwYW4gc3R5bGU9XFxcImNvbG9yOiMzMjMyMzJcXFwiPik8L3NwYW4+CiAgICAgICAgICAgIDxzcGFuIHN0eWxlPVxcXCJjb2xvcjojMzIzMjN7WyYqJl19MlxcXCI+ezwvc3Bhbj4KICAgICAgICAgICAgICAgIGZpczxzcGFuIHN0eWxlPVxcXCJjb2xvcjojMzIzMjMyXFxcIj4uPC9zcGFuPjxzcGFuIHtbJiomXX1zdHlsZT1cXFwiY29sb3I6I2M3M2E2OVxcXCI+Y2xvc2U8L3NwYW4+PHNwYW4gc3R5bGU9XFxcImNvbG9yOiMzMjMyMzJcXFwiPigpOzwvc3Bhbj57WyYqJl19CiAgICAgICAgICAgIDxzcGFuIHN0eWxlPVxcXCJjb2xvcjojMzIzMjMyXFxcIj59PC9zcGFuPgogICAgICAgIDxzcGFuIHN0eWxlPVxcXCJjb3tbJiomXX1sb3I6IzMyMzIzMlxcXCI+fTwvc3Bhbj4KICAgIDxzcGFuIHN0eWxlPVxcXCJjb2xvcjojMzIzMjMyXFxcIj59PC9zcGFuPiA8c3BhbiBzdHlse1smKiZdfWU9XFxcImNvbG9yOiM5Njk2OTZcXFwiPi8vIGV0IGVuY29yZSBqXFxcJ2FpIHNpbXBsaWZpw6ksIG9uIHBvdXJyYWl0IGTDqWNpZGVyIGRcXFwnYXtbJiomXX1qb3V0ZXIgdW4gdHJ5L2NhdGNoIGF1dG91ciBkdSBjbG9zZSgpPC9zcGFuPlwiO3tbJiomXX0=[[/code]]

Si on doit écrire plusieurs méthodes du genre de readFile(), on va être tenté de chercher à encapsuler la mécanique de gestion de la fermeture :

Java2: en utilisant un “InputStreamManager” qu’il resterait à écrire

[[code]]czoxODU1OlwiPHNwYW4gc3R5bGU9XFxcImNvbG9yOiMzYjZhYzhcXFwiPnB1YmxpYyBjbGFzczwvc3Bhbj4gVXNpbmdBbklucHV0U3RyZWFte1smKiZdfU1hbmFnZXIKPHNwYW4gc3R5bGU9XFxcImNvbG9yOiMzMjMyMzJcXFwiPns8L3NwYW4+CiAgICA8c3BhbiBzdHlsZT1cXFwiY29sb3I6IzNiNmF7WyYqJl19YzhcXFwiPnB1YmxpYzwvc3Bhbj4gU3RyaW5nIDxzcGFuIHN0eWxlPVxcXCJjb2xvcjojYzczYTY5XFxcIj5yZWFkRmlsZTwvc3Bhbj48c3BhbntbJiomXX0gc3R5bGU9XFxcImNvbG9yOiMzMjMyMzJcXFwiPig8L3NwYW4+PHNwYW4gc3R5bGU9XFxcImNvbG9yOiMzYjZhYzhcXFwiPmZpbmFsPC9zcGFuPiB7WyYqJl19RmlsZSBmaWxlPHNwYW4gc3R5bGU9XFxcImNvbG9yOiMzMjMyMzJcXFwiPik8L3NwYW4+IDxzcGFuIHN0eWxlPVxcXCJjb2xvcjojM2I2YWM4XFx7WyYqJl19XCI+dGhyb3dzPC9zcGFuPiBJT0V4Y2VwdGlvbgogICAgPHNwYW4gc3R5bGU9XFxcImNvbG9yOiMzMjMyMzJcXFwiPns8L3NwYW4+CiAgICAge1smKiZdfSAgIElucHV0U3RyZWFtTWFuYWdlciBpc20gPHNwYW4gc3R5bGU9XFxcImNvbG9yOiMzMjMyMzJcXFwiPj08L3NwYW4+IDxzcGFuIHN0eWxle1smKiZdfT1cXFwiY29sb3I6IzNiNmFjOFxcXCI+bmV3PC9zcGFuPiA8c3BhbiBzdHlsZT1cXFwiY29sb3I6I2M3M2E2OVxcXCI+SW5wdXRTdHJlYW1NYW5hZ3tbJiomXX1lcjwvc3Bhbj48c3BhbiBzdHlsZT1cXFwiY29sb3I6IzMyMzIzMlxcXCI+KDwvc3Bhbj48c3BhbiBzdHlsZT1cXFwiY29sb3I6IzNiNmFjOFxcXCJ7WyYqJl19Pm5ldzwvc3Bhbj4gPHNwYW4gc3R5bGU9XFxcImNvbG9yOiNjNzNhNjlcXFwiPkZpbGVJbnB1dFN0cmVhbTwvc3Bhbj48c3BhbiBzdHlsZT17WyYqJl19XFxcImNvbG9yOiMzMjMyMzJcXFwiPig8L3NwYW4+ZmlsZTxzcGFuIHN0eWxlPVxcXCJjb2xvcjojMzIzMjMyXFxcIj4pKTs8L3NwYW4+CiAgICAge1smKiZdfSAgIDxzcGFuIHN0eWxlPVxcXCJjb2xvcjojM2I2YWM4XFxcIj5yZXR1cm48L3NwYW4+IGlzbTxzcGFuIHN0eWxlPVxcXCJjb2xvcjojMzIzMjN7WyYqJl19MlxcXCI+Ljwvc3Bhbj48c3BhbiBzdHlsZT1cXFwiY29sb3I6I2M3M2E2OVxcXCI+ZXhlY3V0ZTwvc3Bhbj48c3BhbiBzdHlsZT1cXFwiY29sb3I6e1smKiZdfSMzMjMyMzJcXFwiPig8L3NwYW4+PHNwYW4gc3R5bGU9XFxcImNvbG9yOiMzYjZhYzhcXFwiPm5ldzwvc3Bhbj4gSW5wdXRTdHJlYW1NYW5hZ2V7WyYqJl19cjxzcGFuIHN0eWxlPVxcXCJjb2xvcjojMzIzMjMyXFxcIj4uPC9zcGFuPjxzcGFuIHN0eWxlPVxcXCJjb2xvcjojYzczYTY5XFxcIj5DYWxsYmFje1smKiZdfWs8L3NwYW4+PHNwYW4gc3R5bGU9XFxcImNvbG9yOiMzMjMyMzJcXFwiPigpPC9zcGFuPgogICAgICAgIDxzcGFuIHN0eWxlPVxcXCJjb2xvcjp7WyYqJl19IzMyMzIzMlxcXCI+ezwvc3Bhbj4KICAgICAgICAgICAgPHNwYW4gc3R5bGU9XFxcImNvbG9yOiMzMjMyMzJcXFwiPiZhbXA7bHQ7Lzwvc3BhbntbJiomXX0+Y29kZTxzcGFuIHN0eWxlPVxcXCJjb2xvcjojMzIzMjMyXFxcIj4mYW1wO2d0Ozwvc3Bhbj4KCiAgICAgICAgICAgIDxzcGFuIHN0eWxlPXtbJiomXX1cXFwiY29sb3I6IzNiNmFjOFxcXCI+cHVibGljPC9zcGFuPiBTdHJpbmcgPHNwYW4gc3R5bGU9XFxcImNvbG9yOiNjNzNhNjlcXFwiPmRvV2l0aEl7WyYqJl19bnB1dFN0cmVhbTwvc3Bhbj48c3BhbiBzdHlsZT1cXFwiY29sb3I6IzMyMzIzMlxcXCI+KDwvc3Bhbj5JbnB1dFN0cmVhbSBpczxzcGFuIHN7WyYqJl19dHlsZT1cXFwiY29sb3I6IzMyMzIzMlxcXCI+KTwvc3Bhbj4KICAgICAgICAgICAgPHNwYW4gc3R5bGU9XFxcImNvbG9yOiMzMjMyMzJcXFwiPns8e1smKiZdfS9zcGFuPgogICAgICAgICAgICAgICAgPHNwYW4gc3R5bGU9XFxcImNvbG9yOiMzMjMyMzJcXFwiPi4uLjwvc3Bhbj4gQ29ycHMgZGUgbGEge1smKiZdfW3DqXRob2RlIDxzcGFuIHN0eWxlPVxcXCJjb2xvcjojMzIzMjMyXFxcIj4uLi48L3NwYW4+CiAgICAgICAgICAgIDxzcGFuIHN0eWxlPVxcXCJ7WyYqJl19Y29sb3I6IzMyMzIzMlxcXCI+fTwvc3Bhbj4KICAgICAgICA8c3BhbiBzdHlsZT1cXFwiY29sb3I6IzMyMzIzMlxcXCI+fTs8L3NwYW4+CiAgIHtbJiomXX0gPHNwYW4gc3R5bGU9XFxcImNvbG9yOiMzMjMyMzJcXFwiPn08L3NwYW4+XCI7e1smKiZdfQ==[[/code]]

Vous aurez peut-être reconnu quelque chose d’équivalent à ce que SpringFramework propose en terme de support JDBC pour encapsuler la gestion des DataSources, et de la démarcation transactionnelle (JdbcTemplate + ConnectionCallback)

Le problème avec le code de J2, c’est que bien qu’il permette de ne pas dupliquer une logique technique de code dans toutes les classes, il est plus long à écrire que le code qu’il encapsule, et il est tentant de faire du “copier/coller” dans ces cas-là (la preuve, j’ai regardé dans Apache Commons IO, un tel mécanisme de callback n’est même pas proposé).

Avec un langage fonctionnel comme Clojure (mais il y en a d’autres !), le “bon” code est beaucoup moins visqueux :

a) En utilisant une librairie basée sur les “closures”, ça donnerait ( (fn [param1] …corps de la methode …) est la manière d’écrire une closure en clojure) :

[[code]]czo2MzM6XCI8c3BhbiBzdHlsZT1cXFwiY29sb3I6IzMyMzIzMlxcXCI+KDwvc3Bhbj48c3BhbiBzdHlsZT1cXFwiY29sb3I6IzNiNmFjOFxcXCI+ZHtbJiomXX1lZm48L3NwYW4+IHJlYWQtZmlsZSA8c3BhbiBzdHlsZT1cXFwiY29sb3I6IzMyMzIzMlxcXCI+Wzwvc3Bhbj5maWxlPHNwYW4gc3R5bGU9XFx7WyYqJl19XCJjb2xvcjojMzIzMjMyXFxcIj5dPC9zcGFuPgogICAgPHNwYW4gc3R5bGU9XFxcImNvbG9yOiMzMjMyMzJcXFwiPig8L3NwYW4+PHNwYW4gc3R7WyYqJl19eWxlPVxcXCJjb2xvcjojM2I2YWM4XFxcIj53aXRoLWlucHV0LXN0cmVhbTwvc3Bhbj4gPHNwYW4gc3R5bGU9XFxcImNvbG9yOiMzMjMyMzJcXFwie1smKiZdfT4oPC9zcGFuPjxzcGFuIHN0eWxlPVxcXCJjb2xvcjojM2I2YWM4XFxcIj5uZXc8L3NwYW4+IEZpbGVJbnB1dFN0cmVhbSBmaWxlPHNwYW4ge1smKiZdfXN0eWxlPVxcXCJjb2xvcjojMzIzMjMyXFxcIj4pPC9zcGFuPgogICAgICAgIDxzcGFuIHN0eWxlPVxcXCJjb2xvcjojMzIzMjMyXFxcIj4oPC9zcHtbJiomXX1hbj48c3BhbiBzdHlsZT1cXFwiY29sb3I6IzNiNmFjOFxcXCI+Zm48L3NwYW4+IDxzcGFuIHN0eWxlPVxcXCJjb2xvcjojMzIzMjMyXFxcIj5bPC97WyYqJl19c3Bhbj5pczxzcGFuIHN0eWxlPVxcXCJjb2xvcjojMzIzMjMyXFxcIj5dPC9zcGFuPi4uLiBjb3JwcyBkZSBsYSBtZXRob2RlPHNwYW4gc3R7WyYqJl19eWxlPVxcXCJjb2xvcjojMzIzMjMyXFxcIj4pKSk8L3NwYW4+XCI7e1smKiZdfQ==[[/code]]

b) Voire on peut se passer d’avoir à écrire explicitement la closure en utilisant les services d’une macro clojure pré-existante :

[[code]]czo1MTE6XCI8c3BhbiBzdHlsZT1cXFwiY29sb3I6IzMyMzIzMlxcXCI+KDwvc3Bhbj48c3BhbiBzdHlsZT1cXFwiY29sb3I6IzNiNmFjOFxcXCI+ZHtbJiomXX1lZm48L3NwYW4+IHJlYWQtZmlsZSA8c3BhbiBzdHlsZT1cXFwiY29sb3I6IzMyMzIzMlxcXCI+Wzwvc3Bhbj5maWxlPHNwYW4gc3R5bGU9XFx7WyYqJl19XCJjb2xvcjojMzIzMjMyXFxcIj5dPC9zcGFuPgogICAgPHNwYW4gc3R5bGU9XFxcImNvbG9yOiMzMjMyMzJcXFwiPig8L3NwYW4+PHNwYW4gc3R7WyYqJl19eWxlPVxcXCJjb2xvcjojM2I2YWM4XFxcIj53aXRoLW9wZW48L3NwYW4+IDxzcGFuIHN0eWxlPVxcXCJjb2xvcjojMzIzMjMyXFxcIj5bPC9zcGFue1smKiZdfT5pcyA8c3BhbiBzdHlsZT1cXFwiY29sb3I6IzMyMzIzMlxcXCI+KDwvc3Bhbj48c3BhbiBzdHlsZT1cXFwiY29sb3I6IzNiNmFjOFxcXCI+bmV3PHtbJiomXX0vc3Bhbj4gRmlsZUlucHV0U3RyZWFtIGZpbGU8c3BhbiBzdHlsZT1cXFwiY29sb3I6IzMyMzIzMlxcXCI+KV08L3NwYW4+CiAgICAgICAgLntbJiomXX0uLiBjb3JwcyBkZSBsYSBtZXRob2RlIDxzcGFuIHN0eWxlPVxcXCJjb2xvcjojMzIzMjMyXFxcIj4pKTwvc3Bhbj5cIjt7WyYqJl19[[/code]]

Christophe : Et ceci est réalisable au niveau utilisateur/librairie : il n’y a pas besoin d’attendre la prochaine version du langage pour bénéficier de with-open (s’il n’existait pas).
Par ailleurs, pour ceux que le mot closure effraie, l’instanciation d’une classe anonyme en Java est une closure ; un objet, certes, et non une fonction mais une closure quand même.

The venerable master Qc Na was walking with his student, Anton. Hoping to prompt the master into a discussion, Anton said “Master, I have heard that objects are a very good thing – is this true?” Qc Na looked pityingly at his student and replied, “Foolish pupil – objects are merely a poor man’s closures.”

Chastised, Anton took his leave from his master and returned to his cell, intent on studying closures. He carefully read the entire “Lambda: The Ultimate…” series of papers and its cousins, and implemented a small Scheme interpreter with a closure-based object system. He learned much, and looked forward to informing his master of his progress.

On his next walk with Qc Na, Anton attempted to impress his master by saying “Master, I have diligently studied the matter, and now understand that objects are truly a poor man’s closures.” Qc Na responded by hitting Anton with his stick, saying “When will you learn? Closures are a poor man’s object.” At that moment, Anton became enlightened.

http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/msg03277.html

Agnès : Clojure présente certains avantages vis-à-vis de la programmation concurrente, en quoi ce langage peut-il intéresser les développeurs d’applications qui veulent exploiter la puissance des CPUs mutli-cores? Si les structures de données de base sont immutables, il est néanmoins souvent nécessaire d’implémenter des changements d’état dans une application : comment Clojure donne t-il les moyens aux développeurs d’assurer proprement ces changements d’états (isolation de threads vs STM)?

Christophe : Comme je l’ai déjà évoqué plus haut, Clojure encourage à écrire fonctionnellement de gros pans de code. La gestion des états est alors réduite, circonscrite aux endroits où les modules fonctionnels s’articulent entre eux. J’aime assez utiliser cette analogie mécanique : Clojure tend à réduire les parties mobiles. (Bien sûr si vous êtes un horloger Suisse vous pouvez faire des miracles avec une myriade de parties mobiles …)
Moins de “parties mobiles” signifie moins de configurations (au sens de combinaisons d’états) différentes pour votre système, donc une plus grande facilité à raisonner sur celui-ci. Avoir une suite de tests qui passe c’est bien, avoir une suite de tests qui passe ET être raisonnablement sûr du comportement sain d’un système c’est mieux.
Enfin, Clojure capture différentes typologies “d’articulations” entre les modules, pour lesquelles il fournit des outils pour les gérer de manière fiable. Les garbage collectors ont automatisé le memory management, Clojure automatise le state management.

Laurent : Et je dirai même plus, Grichka. Agnès, tu faisais bien d’utiliser le verbe “encourager” dans la question précédente, quand tu parlais de la programmation fonctionnelle. Car Clojure se veut avant tout “pragmatique”. Et en cela, il ne se contente pas d’imposer au monde un dogme qui serait “le fonctionnel, c’est bien ; éloignez-vous du chemin, et vous serez damné !”. NON ! Bien au contraire !
Clojure est pragmatique, et reconnait complètement l’utilité de faire changer l’état d’un programme ! A tel point que même pour les parties du programme qui ne sont pas (ne *peuvent pas être* !) écrites avec des fonctions “pures”, le développeur a le support du langage à la rescousse !
Christophe a raison, sans entrer dans les détails de ce support, on peut faire un parallèle direct avec la gestion de mémoire via le ramasse-miettes : Clojure apporte à Java avec le support de la gestion d’état ce que Java a apporté à C++ avec le support de la gestion mémoire.

Christophe : Clojure ne vous demande pas de comprendre ce que sont les monades ou les arrows pour pouvoir lire un fichier. Ces choses là ne font pas partie du monde Clojure.

Agnès : La plateforme Java a connu et connait toujours un vrai succès, mais on ne peut plus dire que Java est LE langage universel pour cette plate-forme. Java 6 a introduit le support pour les langages de scripts (JSR 223) et Java 7 le support des langages dynamiques compilés au niveau de la JVM (JSR 292). Il existe ainsi aujourd’hui toute une variété de langages, comme Clojure, qui tournent sur la JVM. Outre Clojure, avez-vous des retours d’expériences sur d’autres langages (notamment par exemple sur Scala/Akka que je rapprocherais peut-être le plus de Clojure)?

Christophe : La JSR 292 ne présente pas une perspective de gain énorme pour Clojure car la grande majorité des appels de méthodes ne sont ni réflexifs ni ne présentent des mécanismes de dispatch polymorphique complexes. Hotspot est plutôt dynamique (via la filiation à Self) et Clojure sait en tirer partie car Rich Hickey a disposé et dispose des conseils avisés de plusieurs architectes de la JVM. La JSR292 est surtout un travail d’exposer en bytecode des capacités fondamentales de Hotspot, faire craquer le vernis statique pour révéler la nature dynamique…
Quant à Akka, on peut lire sur leur site :

Akka’s STM implements the concept in Clojure’s STM view on state in general. Please take the time to read this excellent document and view this presentation by Rich Hickey (the genius behind Clojure), since it forms the basis of Akka’s view on STM and state in general.

Laurent : En ce qui me concerne, pas de retour d’expérience “projet”. J’ai étudié il y a quelques années Groovy, et notamment le framework Grails, qui s’inspir(ait) de Ruby on Rails. Pour ma part, en toute honnêteté, je n’avais pas été convaincu par certains points, notamment l’aspect performance (très forte utilisation de la réflexivité), et de l’aspect “magique” de son côté très “dynamique” (appeler des méthodes en respectant une certaine convention et le framework fournit automatiquement une implémentation). Je trouvais également qu’il ne m’apportait rien de fondamentalement “novateur/intéressant” au-delà de son aspect dynamique et “sucre syntaxique au-dessus de java”. Ce langage semble néanmoins avoir de bons jours devant lui avec la place que lui fait par exemple SpringFramework.

Agnès : Vous vous êtes tous deux investis dans le développement du plugin Eclipse “Counterclockwise” et, Christophe, tu es l’auteur de deux librairies Clojure “Enlive” et “Moustache”. Pouvez-vous présenter succinctement chacun de ces projets? Christophe peux-tu nous parler également de ton livre sur Clojure pour les éditions O’Reilly? Vous allez être speakers lors de la conférence lyonnaise mix-it, mais auparavant vous êtes intervenus en tant que speakers à ClojureConj aux USA octobre 2010. Quel retour pouvez-vous faire sur cette première conférence Clojure?

Laurent : Counterclockwise est un moyen pour moi d’être présent dans la communauté Clojure en fournissant un plugin Eclipse pour le langage. C’est un plugin Eclipse qui a pour objectif d’apporter au développement Clojure le niveau de support attendu (coloration, outline, complétion, smart indentation, lancement d’un runtime de test, console de développement interactif – avec les mêmes fonctionnalités que dans l’éditeur pour la zone de saisie -, etc.). Lorsque j’ai démarré, je faisais également du développement Eclipse chez mon employeur, le support d’Eclipse pour Clojure était balbutiant, ce fut donc un choix “win-win” !
Il est à noter que, si au début pour “aller à l’essentiel” une majorité de Counterclockwise était écrite en Java, il s’est vite imposé à nous que ce n’était ni satisfaisant, ni productif, et aujourd’hui nous écrivons le plus possible de code en Clojure. “Eat your own dog food, as they say …”

Christophe : Moustache est une petite librairie HTTP qui permet de déclarativement décrire les routes, de les valider, d’appliquer des middlewares (wrappers) le cas échéant, de dispatcher selon la méthode utilisée etc.
Enlive est un peu plus ambitieux, il s’agit d’une librairie qui permet d’extraire, transformer et générer de l’HTML ou de l’XML. Enlive est souvent utilisé en moteur de template car ses templates sont 100% HTML, aucune balise, attribut ou classe spéciale, du bon HTML cru, directement au pis du webdesigner — ce qui facilite énormément les roundtrips avec le design ou le changement de thème d’une webapp. Le webscraping est aussi un domaine de prédilection pour Enlive.
La Conj était très énergisante, beaucoup de rubyistes de la première heure étaient présents et ont retrouvé la même énergie (et qualité) que lors de la première Ruby Conf.
Tant que l’on est sur les confs, en plus de Mix-IT, je serai présent à GOTO Cph pour donner deux présentations et une journée de formation (j’ai déjà donné deux sessions de trois jours l’an passé, à Bruxelles et Francfort) — le tout sur Clojure bien évidemment !
Enfin, je travaille, avec Chas Emerick et Brian Carper, sur un livre Clojure chez O’Reilly qui devrait être disponible en Rough Cuts (accès au livre à l’état brouillon) d’ici quelques jours et partir sous presse cet été. Il adopte un angle différent des livres déjà publiés : pour moitié c’est une introduction au langage et pour moitié il couvre des sujets pratiques (les bases de données, le Web, Maven/Ant et Clojure, etc.), il s’adresse à la fois au monde Java et au monde Ruby — qui sont les deux communautés d’origines de beaucoup de Clojuristes.

Merci Laurent et Christophe! Vous les retrouverez donc à Mix-IT, non seulement pour une session sur Clojure, mais également pour un atelier pratique où vous allez pouvoir tremper vos mains dans Clojure

Les inscriptions à Mix-IT sont ouvertes!

**Allez découvrir le programme sur le site pour vous inscrire!
Et d’ici là suivez @mixIT_lyon sur twitter pour avoir plus d’informations!
**