Hier, je me suis dit que ça vaudrait la peine d’essayer d’utiliser le langage de programmation Groovy pour un projet chez Nuance. J’estime que cela va me permettre de générer et manipuler du XML plus facilement et m’éviter de répétitives constructions. Plutôt qu’écrire du code pour effectuer la même opération sur chaque item d’une liste, classifier des items selon certains critères afin de pouvoir appliquer un traitement spécifique à chaque classe d’items, ouvrir des fichiers, etc., je pourrai me concentrer davantage sur la logique du programme et éviter de perdre plein de temps à écrire de la poutine répétitive et déboguer. Eh bien pour le moment, c’est exactement tout le contraire! Voici pourquoi.
- Cette journée a mal commencé avec un problème de connexion de mon écran. Mon laptop de Nuance est relié chez moi à mon écran par un adaptateur mini-HDMI vers HDMI, un fil HDMI qui va dans un commutateur HDMI, puis un fil HDMI vers DVI qui va dans l’écran. Eh bien je n’avais plus d’image. Pourtant, mon ordinateur personnel, lui aussi raccordé au commutateur et allumé pour des raisons qui importent peu ici, affichait le bureau d’Ubuntu. C’est arrivé à quelques reprises et j’ai dû débrancher et rebrancher le câble mini-HDMI. Eh bien en vain cette fois. Cela a fini par fonctionner en essayant avec un autre adaptateur mini-HDMI! Je ne sais pas encore si c’est vraiment l’adaptateur, car mon Raspberry Pi a aussi, hier soir, refusé d’afficher en HDMI. C’est donc peut-être le foutu commutateur si bien qu’il faudrait idéalement que je remplace mon écran par un doté de plusieurs entrées HDMI. Mais les écrans d’ordinateur ont pour la plupart une seule entrée DVI ou HDMI.
- L’installation de mon environnement Groovy a posé des difficultés. Je n’ai eu aucun mal à installer Groovy lui-même, à mettre en place le plugin Groovy pour Eclipse, mais après, les problèmes ont commencé. Je me suis vite rendu compte qu’il valait mieux créer un nouveau projet distinct dans Eclipse pour cette nouvelle tâche, pas seulement pour éviter d’introduire des difficultés dans les builds à cause de Groovy mais aussi par souci de séparation correcte du code. Sans cela, Eclipse indiquait que le compilateur Groovy du projet, dicté par le fichier POM de Maven, ne correspondait pas au compilateur utilisé par défaut dans Eclipse. Il fallait alors modifier les propriétés du build, dans Eclipse, et il n’y avait pas de synchronisation avec le fichier POM de Maven, donc modifier le fichier POM risquait de nécessiter de refaire le paramétrage du build, et toute personne désireuse de consulter mon code dans Eclipse aurait elle aussi à paramétrer le build.
- Trouver comment configurer mon fichier POM pour que Maven puisse gérer mon satané projet Groovy n’a pas été une mince affaire. Le plugin GMaven qui semblait devoir faire ce travail est discontinué, sans aucune alternative convainquante pour le remplacer! Le seul candidat est un plugin Groovy-Eclipse-Compiler qui me semble un joli hack utilisant le compilateur d’Eclipse en arrière-plan pour compiler du Groovy! Mais bon, c’est tout ce qu’on a alors on essaie. Eh bien il me fallut copier/coller plusieurs blocs de code dans mon fichier POM et ça ne fonctionnait même pas pour les raisons suivantes!
- Eclipse s’est d’abord plaint qu’il y avait deux installations de Groovy dans le classpath. J’ai dû exclure celle en provenance d’un projet dépendant; c’était la 1.8 et je voulais partir avec la 2.0. Après, eh bien encore cette erreur de correspondance du compilateur: mon projet voulait Groovy 2.1, Eclipse avait la 2.0! Il m’a fallu utiliser une version antérieure de Groovy-Eclipse-Compiler, et trouver le bon numéro de version a demandé des recherches à plus finir.
- Après tous ces efforts, eh bien Eclipse est devenu affreusement lent et gelait à tout bout de champ. Cela a fini par des erreurs à propos de mémoire insuffisante puis un plantage. Par chance, le comportement était plus normal après le redémarrage d’Eclipse.
- Ensuite, le développement a véritablement commencé. D’abord, le plugin Groovy d’Eclipse souffre de problèmes lorsque vient le temps de proposer des noms de classes, méthodes et propriétés. Parfois, il trouve un nom, parfois pas, et c’est très arbitraire. Par exemple, j’avais une variable de type String (chaîne de caractères), et Groovy avait l’information à propos du type (à noter que ce n’est pas toujours le cas vu la nature dynamique de Groovy). Eh bien Eclipse localisait la méthode toLowerCase() mais pas toUpperCase()! La complétion de noms de classes fonctionnait parfois, mais elle n’ajoutait pas toujours l’importation nécessaire si bien qu’après coup, j’avais des erreurs indiquant que la classe récemment référencée n’était pas trouvable, devais sélectionner sa référence et appuyer sur CTRL-SHIFT-M pour ajouter l’importation. Ça fonctionnait parfois, parfois pas, il fallait alors appuyer plusieurs fois!
- D’autres difficultés surgirent en raison de ma connaissance embryonnaire du langage Groovy. Par exemple, je me suis emmêlé les pinceux avec la notation pour construire un tableau associatif. Il ne faut pas utiliser [a:b, c:d]; ça ne va pas fonctionner, le compilateur va se plaindre de l’absence des variables b et d. Il faut plutôt utiliser [a: »b », c: »d »] ou encore [« a »: »b », « c »: »d »]. Mais pourtant, GroovySH va bêtement afficher [a:b, c:d] si on lui demande de montrer le tableau! Déclarer une variable de type List<?> ne fonctionnait pas: il fallait que j’utilise simplement List; en Java, cela déclenche un avertissement comme quoi c’est un type brut. Mais si je déclarais List[] ou List<?>[], eh bien j’avais un avertissement à propos du type brut! Il faut utiliser des listes au lieu des tableaux ou bien ne pas déclarer de type du tout. Mais je trouve ça plus clair de donner le type, surtout pour les arguments d’une fonction!
- J’ai été bien choqué quand j’ai voulu créer une classe avec des champs et y générer des accesseurs, car la fonction d’Eclipse pour le faire n’était pas disponible en Groovy. Je me suis alors rappelé qu’il existe des annotations pour indiquer à Groovy de générer ces accesseurs automatiquement. Eh bien je n’arrivais pas à retrouver ces annotations dans la documentation et des recherches sur Internet me donnèrent à des indices pour bâtir une transformation d’AST personnalisée permettant de le faire!!! Bon sang! Par chance, il suffisait de déclarer mes champs sans modificateur d’accès pour que Groovy ait l’intelligence de les traiter comme des propriétés et alors définir les accesseurs.
- Outre les problèmes syntaxiques, il y a aussi eu des difficultés d’API. Jusqu’à ce que je trouve la documentation du GDK, indiquant quelles méthodes Groovy ajoute à Java, je n’arrivais pas à savoir facilement comment appliquer une transformation sur tous les items d’une liste (collect peut le faire), s’il était possible d’ouvrir un fichier texte en UTF-8 avec un seul appel de méthode plutôt que construire le FileInputStream, puis le InputStreamReader, et enfin le BufferedReader, etc..
- J’ai aussi eu des difficultés avec le débogueur qui s’est remis à se plaindre chaque fois que je définissais un point d’arrêt conditionnel. J’avais beau vérifier et revérifier l’expression de la condition, tout était OK. Pourtant, j’avais cette maudite erreur. J’ai encore été obligé de modifier le code temporairement après quoi le point d’arrêt fonctionnait, mais Eclipse n’arrivait pas à trouver le code source de la classe, dans un projet importé par dépendance Maven qui était pourtant dans mon espace de travail Eclipse! Il m’a fallu indiquer l’emplacement explicitement puis j’ai enfin pu déboguer le code. C’est possible que ce soit ça qui ait brisé les points d’arrêt conditionnels.
- J’ai eu des erreurs d’exécution à la pelle! Le code compilait, semblait beau, mais à l’exécution, j’avais des problèmes à propos de méthodes ou de propriétés inexistantes. Cette fois-ci, ce n’était pas Groovy, ni Maven, ni Eclipse mais bien mon code; il fallait corriger les petites erreurs. Certaines erreurs ont été difficiles à corriger, surtout celles qui ont surgi quand je me suis mis à utiliser le MarkupBuilder de façon un peu exotique pour construire mon XML de façon dynamique. Oh là là! La documentation de Groovy n’explique pas très bien comment fonctionne le builder; c’est un fichier en progression. Mais pourquoi placer une page sur un site web pour simplement écrire, pendant deux ans, work in progress ou coming soon? Je ne me souviens plus exactement d’où j’ai eu les indices pour comprendre ce qui se passe, peut-être dans le chapitre sur les DSL de Groovy in Action. Le problème ici était que mon fichier XML n’était pas statique: je devais générer un élément <task> pour chaque tâche de mon application et y injecter des attributs au besoin, pas toujours tous les attributs! Par chance, la chose a été possible et peut être étendue pratiquement à l’infini.
En bref, quelle galère! On se demandera si tout ceci a valu le coup. Je me le demande moi aussi. Je pense que l’apprentissage de Groovy aura une utilité si bien que je prévois continuer cette exploration. Je ne saurais pour le moment mesurer la contribution exacte de Groovy, Eclipse et Maven dans cette expérience plutôt déplaisante.
Il faut garder à l’esprit que j’ai eu beaucoup de difficultés avec Eclipse, incluant des problèmes avec la complétion de noms de classes et de méthodes, les points d’arrêt conditionnels qui boguent parfois mais au moins pas de plantages, pas sous Windows en tout cas. Sous Linux, j’en ai déjà eu à plus finir. Pourtant, les alternatives à Eclipse sont plutôt limitées: NetBeans qui ne gère même pas bien le fichier POM de notre projet chez Nuance, IntelliJ dont la version gratuite est bridée (on ne sait JAMAIS quand on tombera sur un blocage demandant la version payante!!!) et puis les éditeurs de texte comme Notepad++, Emacs, Vi, etc. Ces éditeurs sont excellents, je ne peux que l’avouer, mais ils ne suffisent pas à la tâche pour gérer un gros projet Java ou Groovy avec plusieurs classes.