S’il y a un élément que je dois mettre en avant comme étant l’élément clé de l’adoption de Groovy dans l’entreprise, c’est bien celui de la syntaxe. Groovy offre, par rapport à d’autres langages sur la JVM comme Scala ou Clojure, des avantages immenses :
-
syntaxe à 95% compatible Java : n’importe quel développeur Java peut écrire du Groovy, sans avoir besoin de comprendre les particularités de ce langage : celà permet d’avoir un temps d’apprentissage extrêmement réduit. Lorsque dans une équipe, on n’a pas beaucoup de temps à consacrer à la formation, c’est un plus indéniable
-
des ajouts précieux : l’ajout de nombreuses méthodes ``utilitaires'' simplifiant l’utilisation des API standard rend le code plus compact
-
l’utilisation des closures, qui permettent de se concentrer sur l’algorithmique avant la syntaxe
-
un typage dynamique, qui permet aux non initiés d’éviter d’avoir à se poser la question des types
Revenons sur ce dernier point. A plusieurs reprises, j’ai fait référence à la possibilité d’utiliser Groovy pour faire travailler des ``non informaticiens''. Si le terme est un peu abusif, il n’en résume pas moins ce que je considère avec le recul comme une grande réussite. Le pari était osé, mais il a fonctionné : chez Lingway, nous avons trois types de profils dans l’équipe de développement. Il y a d’abord les développeurs, comme moi, issus de formations en ingénierie informatique. Ensuite, nous trouvons les consultants, qui s’ils sont formés à l’informatique et au développement, ont un niveau de technicité moins élevé : leur expertise repose sur la compréhension du besoin client et au paramétrage de nos produits. En particulier, ce sont eux qui écrivent les fameux workflows d’acquisition. Enfin, la dernière catégorie correspond aux linguistes. S’ils sont formés à l’informatique, c’est avant tout en tant qu’outil : la plupart d’entre eux ne connaissent rien des langages de programmation. Pourtant, grâce à Groovy, ces trois profils peuvent cohabiter sur une même plateforme, un même langage. La capacité qu’on a, avec Groovy, de simplifier à l’extrême la syntaxe, et à écrire des langages de domaine est extraordinaire.
Prenons un exemple concret, dans le cadre des workflows d’acquisition de données. L’ingénieur Java, sans Groovy, aurait écrit ceci (et il aurait bien fait son travail) :
Map inputMap = new HashMap()
inputMap.put(com.lingway.lkm.db.corpus.bean.fields.DublinExtendedKind.Title, "Hello, World !");
inputMap.put(com.lingway.lkm.db.corpus.bean.fields.DublinExtendedKind.Body,"Groovy is cool !");
inputMap.put(com.lingway.lkm.db.corpus.bean.fields.DublinExtendedKind.Language,com.lingway.lkm.db.corpus.bean.languages.LanguageKind.ENGLISH);
L’utilisation de Groovy dans nos workflows permet de simplifier l’écriture ainsi :
inputMap = [
title: "Hello, World !"
body: "Groovy is cool !"
language: "en"
]
Cette façon de faire permet de rendre le code du workflow beaucoup plus lisible, et de se concentrer sur ce que doit faire le workflow, non sur la syntaxe. C’est extrêmement important, et ça permet de gagner énormément de temps : la lecture est facilitée, la maintenance aussi. Par ailleurs, il n’y a pas besoin d’une expertise énorme pour comprendre ce que celà fait. Pas besoin de comprendre de qu’est une hashmap. Pas besoin de savoir, même, qu’il faut en créer une… Un autre exemple, concernant la lecture d’un fichier ligne par ligne sur lequel on souhaiterait faire la somme des entiers qu’il contient: notre développeur Java aurait écrit ceci :
File file = new File("/tmp/data.txt");
int total = 0;
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "utf-8"));
String line;
while ((line=reader.readLine())!=null) {
if (line.length()>0) total += Integer.valueOf(line);
}
reader.close();
} catch (IOException e) {
// this must never happen, and if it does, I don't know what to do
}
System.out.println("total = " + total);
En groovy, on se contentera d’écrire ceci :
def total = 0
new File("/tmp/data.txt").eachLine("utf-8") { line ->
if (line) total += line as int
}
println "Total : $total"
De 13 lignes, on passe à 4. Ces 4 lignes se concentrent sur la seule chose qui importe : le traitement. Au pire, vous devrez expliquer à votre interlocuteur novice en Groovy ce que fait eachLine ou as int, et tout est compris… De la même façon, Groovy est un excellent outil pour simplifier l’utilisation des API Java. Un des exemples qui me plaît le plus est celui de l’utilisation de l’API Java mail (tiré de la documentation de Gaelyk, un framework web léger basé sur Groovy) :
mail.send sender: "app-admin-email-AT-gmail-DOT-com",
to: "recipient-AT-somecompany-DOT-com",
subject: "Hello",
textBody: "Hello, how are you doing? -- MrG",
attachment: [data: "Chapter 1, Chapter 2".bytes, fileName: "outline.txt"]
Il s’agit ici d’un mini DSL, dédié à l’envoi de mails. Comment imaginer plus simple ? Lorsqu’on connait la verbosité de l’API Javamail, il n’y a pas photo…
Ainsi, grâce à la flexibilité de Groovy, nous avons pu :
-
rendre lisible nos workflows
-
écrire un langage domaine dédié à l’écriture de règles linguistiques. Ce langage est au coeur de notre outil interne d’extraction d’informations, et est utilisé par des linguistes.
A ce propos, la force de l’utilisation de Groovy dans un tel outil est multiple :
-
il permet à des non informaticiens d’écrire des règles qui sont compilées en bytecode exécuté par la JVM
-
lorsque le DSL est insuffisant, les linguistes peuvent faire appel aux développeurs, qui écrivent des ``bouts de code Groovy'' qui réalisent les opérations complexes
Ainsi, le possible ne se limite plus à l’expressivité du DSL. C’est un point particulièrement important à comprendre : si on avait choisi d’écrire un DSL classique, un moteur à base de règles disposant de sa propre syntaxe, nous aurions certes sans doute atteint un niveau de lisibilité supérieur à ce qu’il est possible de faire en Groovy, mais nous aurions du :
-
soit écrire un interpréteur, version simple, soit un compilateur, version complexe, de règles
-
développer de nouvelles versions du langage au fur et à mesure que les besoins apparaissent
Avec Groovy, on s’affranchit de ces deux étapes, et on dispose d’un bonus non négligeable : il s’agit de code. Même si les linguistes écrivent des règles, il n’en reste pas moins qu’au milieu de ces règles, on peut faire appel à tout le langage, et donc faire toutes les opérations possibles et imaginables…
Chose amusante, nous nous rendons compte qu’avec le temps, nos linguistes montrent une curiosité grandissante envers la partie ``code'', et tendent naturellement à générifier leurs règles : le langage devient structurant, et appele à une meilleur qualité !