Dans cet article, je vais vous montrer la puissance du produit sur lequel j'ai trébuché cette semaine: Project Lombok. Il vous permet de modifier le bytecode au code de compilation. Tout d'abord, je vais détailler les fonctionnalités que Lombok vous apporte. Dans la deuxième partie de cet article, je vais décrire comment l'étendre pour générer votre propre code.
L'objectif du projet Lombok est exactement le même que pour les initiatives précédentes, mais pour ce faire, il utilise un autre mécanisme.
Par exemple, lors de vos premiers pas sur la programmation OO, vous avez été forgé pour rendre vos champs privés et écrire des accesseurs publics pour accéder à ces champs:
Comme c'est lourd à écrire, certains IDE (si ce n'est tous) ont une fonctionnalité pour générer les accesseurs. Mais ça pose quelques inconvénients:
Puisque les getter / setter ne sont que des méta-données pour un champ, la position de Lombok est de les traiter comme tel en Java : les méta-données sont gérées avec des annotations. Regardez le code suivant:
En pensant, j'ai trouvé 3 arguments contre l'utilisation de Lombok:
Il y a un piège, cependant. Notez la dernière déclaration et l'accent mis sur javac. Puisque la plupart (sinon tous) les développeurs que vous et moi connaissons se concentrent un peu sur la productivité, il est probable que vous utilisiez un IDE. Je ne connais pas NetBeans et les autres, mais mon IDE Eclipse préféré n'utilise pas javac pour compiler mais son propre compilateur interne.
Nos amis de Lombok y ont réfléchi et Lombok est également capable de se connecter au processus de compilation Eclipse. Pour ce faire, lancez lombok.jar et suivez les instructions sur votre écran: il ajoutera juste 2 lignes à votre eclipse.ini.
Un conseil (depuis que j'ai fait l'erreur): si vous lancez Eclipse avec une commande qui prend des paramètres, comme un raccourci Windows, ces paramètres sont prioritaires et eclipse.ini est silencieusement ignorée. (Juste pour que vous sachiez…)
L'avantage de ceci est que Morbok utilise automatiquement le nom de classe complet comme nom de logger, donc plus d'erreur de copier-coller. L'inconvénient est que si vous n'utilisez pas Commons Logging comme framework de journalisation, vous devez configurer chaque annotation @Logger avec le framework que vous voulez utiliser, il n'y a pas de configuration globale: à mon avis, c'est quelque chose qui pourrait être couvert dans la prochaine version.
Il passe ensuite la structure ainsi formée à chacun de ses handlers référencés. Il y a un seul gestionnaire pour chaque annotation: HandleGetter pour @Getter, HandlerSetter pour @Setter et ainsi de suite. Les Handlers sont (devinez quoi) responsables du traitement des annotations.
De plus, coder deux handlers pour chaque annotation est une perte de temps. Et si on devait également prendre en charge NetBeans? Peut-être que l'utilisation du Service Provider est une erreur ...
Enfin, la dépendance envers l'API du compilateur interne de Sun a un risque trop important. Je pense que si Lombok pouvait fournir une façade à cette API, il pourrait être moins risqué pour les entreprises de prendre cette route et le pontage pourrait être fait par des personnes qui comprennent l'API (l'équipe Lombok) et non des développeurs de base (comme moi).
Dans l'ensemble, et malgré ces défauts, Lombok ressemble à un projet très prometteur qui pourrait bien imiter le succès de Spring. C'est ce que je souhaite de toute façon car c'est une vraie pensée du faite qu'il apporte beaucoup de valeur ajoutée.
Bonne chance pour l'avenir!
Introduction
Depuis l'aube de JEE, des plaintes ont été déposées concernant la complexité des composants de codage. Je considère qu'EJB v2 est un très bon exemple de cette complexité: pour un simple EJB, vous devez fournir la classe EJB elle-même et un home et une interface pour chaque type d'accès (local et remote). Cela le rend complexe, sujet aux erreurs et surtout vous donne moins de temps pour se concentrer sur le code métier où est la valeur réelle. Deux initiatives montrent la volonté de diminuer la quantité de code standard requis lors du codage:- La devise de Spring Framework est de réduire la complexité de JEE. Le code standard est écrit une fois dans le core de Spring et puis à utiliser par les projets.
- EJB v3 a pris en compte les leçons de Spring et vise à réduire le code standard, rendant inutile les interfaces locales et distantes. Finalement, la prochaine version de la spécification rendra les interfaces locale et distante aussi facultatives.
L'objectif du projet Lombok est exactement le même que pour les initiatives précédentes, mais pour ce faire, il utilise un autre mécanisme.
Traitement d'annotation
La version 5 du langage Java introduit le concept d'annotations. Ce sont des métadonnées de code qui pourraient être traitées au moment de la compilation et / ou de l'exécution. Malheureusement, dans JDK 5, le traitement des annotations à la compilation est un processus en deux étapes. D'abord, vous devez exécuter l'exécutable apt pour traiter les annotations, peut-être créer ou modifier des fichiers source, puis compiler vos sources avec javac. Ce n'était pas la meilleure approche, donc Java 6 supprime apt et rend javac capable de gérer les annotations, rationalisant le processus pour obtenir un traitement en une seule étape plus simple. C'est le chemin emprunté par Lombok.Projet Lombok
L'objectif de Lombok est de créer le code dont vous avez besoin à partir des annotations afin de réduire la quantité de code standard que vous devez écrire. Il vous fournit les annotations suivantes qui changeront votre code (si ce n'est votre vie) pour toujours:- @Getter et @Setter: créez des getters et setters pour vos champs
- @EqualsAndHashCode: implémente equals () et hashCode ()
- @ToString: implémente toString ()
- @Data: utilise les quatre fonctionnalités précédentes
- @Cleanup: ferme votre flux
- @Synchronized: synchroniser sur les objets
- @SneakyThrows: jette des exceptions
Par exemple, lors de vos premiers pas sur la programmation OO, vous avez été forgé pour rendre vos champs privés et écrire des accesseurs publics pour accéder à ces champs:
public class Person { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
Comme c'est lourd à écrire, certains IDE (si ce n'est tous) ont une fonctionnalité pour générer les accesseurs. Mais ça pose quelques inconvénients:
- Vous devez supprimer manuellement les accesseurs si vous supprimez le champ
- Il encombre votre code réel avec du boilerplate code
- Corollaire: il faut un réel effort pour vérifier si un accesseur existe déjà pour un champ dans une classe longue
Puisque les getter / setter ne sont que des méta-données pour un champ, la position de Lombok est de les traiter comme tel en Java : les méta-données sont gérées avec des annotations. Regardez le code suivant:
import org.lombok.Getter; import org.lombok.Setter; public class Person { @Getter @Setter private String name; }J'ai décompilé la classe générée (en utilisant JAD) et ça se trouve qu'il crée exactement le même bytecode, mais c'est plus concis et moins sujette aux erreurs. Fascinant non ?
En pensant, j'ai trouvé 3 arguments contre l'utilisation de Lombok:
- Le premier argument contre l'utilisation d'une telle stratégie est que vous ne pouvez pas créer un accesseur protégé comme ça. Vous avez tort, Lombok est configurable (Et c'est vrai pour toutes les annotations fournies!):
import lombok.AccessLevel; import org.lombok.Getter; import org.lombok.Setter; public class Person { @Getter @Setter(AccessLevel.PROTECTED) private String name; }
- Le deuxième argument contre l'utilisation de Lombok est que vous ne savez pas ce qu'il fait derrière la scène. C'est vrai, mais la même chose pourrait être dite pour l'AOP ou CGLIB ou quel que soit le framework que vous utilisez.
- Le dernier argument est à mon avis le seul valide, c'est qu'il rend le débogage plus complexe: mais il en est de même de l'utilisation des proxies dynamiques que Spring utilise tout au long de son code, et encore de nombreux projets les utilisent.
Utilisation et installation
L'utilisation de Lombok est un processus en trois étapes:- Mettez le JAR sur le chemin de classe (Ou laisser maven le faire )
- Ajoutez l'annotation que vous souhaitez utiliser
- Compiler avec javac
Il y a un piège, cependant. Notez la dernière déclaration et l'accent mis sur javac. Puisque la plupart (sinon tous) les développeurs que vous et moi connaissons se concentrent un peu sur la productivité, il est probable que vous utilisiez un IDE. Je ne connais pas NetBeans et les autres, mais mon IDE Eclipse préféré n'utilise pas javac pour compiler mais son propre compilateur interne.
Nos amis de Lombok y ont réfléchi et Lombok est également capable de se connecter au processus de compilation Eclipse. Pour ce faire, lancez lombok.jar et suivez les instructions sur votre écran: il ajoutera juste 2 lignes à votre eclipse.ini.
Un conseil (depuis que j'ai fait l'erreur): si vous lancez Eclipse avec une commande qui prend des paramètres, comme un raccourci Windows, ces paramètres sont prioritaires et eclipse.ini est silencieusement ignorée. (Juste pour que vous sachiez…)
Extensions de Lombok
À ma connaissance, il n'y a actuellement qu'une seule extension de Lombok appelée Morbok. Elle vous permet de créer votre logger classique final statique privé avec juste une annotation.L'avantage de ceci est que Morbok utilise automatiquement le nom de classe complet comme nom de logger, donc plus d'erreur de copier-coller. L'inconvénient est que si vous n'utilisez pas Commons Logging comme framework de journalisation, vous devez configurer chaque annotation @Logger avec le framework que vous voulez utiliser, il n'y a pas de configuration globale: à mon avis, c'est quelque chose qui pourrait être couvert dans la prochaine version.
Architecture
Tout d'abord, Lombok a besoin d'un JDK 6+ pour la compilation puisque le traitement des annotations se fait en Java 5 avec APT. Pour l'instant, Lombok se connecte au processus de compilation immédiatement après que l'environnement a construit l'AST pour la classe.Il passe ensuite la structure ainsi formée à chacun de ses handlers référencés. Il y a un seul gestionnaire pour chaque annotation: HandleGetter pour @Getter, HandlerSetter pour @Setter et ainsi de suite. Les Handlers sont (devinez quoi) responsables du traitement des annotations.
Exemple
À titre d'exemple, j'ai codé un "embryon" pour une annotation @Delegate. Une telle annotation sur un champ indique que la classe déclarante doit avoir les mêmes méthodes publiques que la classe du champ et que le corps de chaque méthode doit être un appel à la méthode de son délégué.public class Delegator { @Delegate private DelegateObject object; ... } public class DelegateObject { public void doSomething() { ... } }Le code précédent doit générer le même bytecode que le code suivant:
public class Delegator { private DelegateObject object; public void doSomething() { object.doSomething(); } ... }Encore:
- Il ne gère pas les génériques
- Le seul handler fourni est pour javac
- Il n'est pas configurable
Conclusion
Certaines améliorations pourraient rapidement être apportées à Lombok. Premièrement, je n'aime pas la structure monolithique du JAR. À mon avis, il pourrait être bien découplé en 3 JAR distincts: le client Lombok lui-même, les annotations fournies et les handler associés et enfin, le jar d'installation.De plus, coder deux handlers pour chaque annotation est une perte de temps. Et si on devait également prendre en charge NetBeans? Peut-être que l'utilisation du Service Provider est une erreur ...
Enfin, la dépendance envers l'API du compilateur interne de Sun a un risque trop important. Je pense que si Lombok pouvait fournir une façade à cette API, il pourrait être moins risqué pour les entreprises de prendre cette route et le pontage pourrait être fait par des personnes qui comprennent l'API (l'équipe Lombok) et non des développeurs de base (comme moi).
Dans l'ensemble, et malgré ces défauts, Lombok ressemble à un projet très prometteur qui pourrait bien imiter le succès de Spring. C'est ce que je souhaite de toute façon car c'est une vraie pensée du faite qu'il apporte beaucoup de valeur ajoutée.
Bonne chance pour l'avenir!
Aucun commentaire