Le but de cet article est de vous donner un aperçu des possibilités offertes par la Programmation Orientée Aspect, ou Aspect Oriented Programming (AOP). En partant d’un exemple concret, nous définirons les concepts de Weaver, PointCut, JoinPoint, Advice, inter-type declaration, … Nous parlerons ensuite des usages possibles de cette technologie dans vos projets, pour terminer par quelques réflexions sur les paradigmes de programmation.
Imaginons que vous arrivez sur un projet Java avec un lourd passé, comportant plusieurs dizaines de milliers de lignes de code pas ou peu commentées, des styles de codes hétérogènes, des dizaines de classes de plus de 3000 lignes, des interactions alambiquées entre le client, le serveur, la base de données, les applications exernes, le tout avec des traitements multithreads. Les « développeurs » coupables de ces méfaits ne sont évidemment plus là, et vous êtes chargé de la maintenance de cette magnifique application qui est part ailleurs critique pour ses utilisateurs. Cette situation périlleuse (toute ressemblance avec des personnes ou des faits ayant existé ne serait que pure coïncidence) vous impose de
Nous allons voir comment utiliser l’AOP pour régler ces problèmes. L’exemple cite volontairement un projet existant, car l’AOP n’est pas une technologie réservée à des nouveaux projets, elle peut être introduite sur des projets existants, parfois sans recompilation. L’exemple cite un projet Java, mais les concepts introduits ici peuvent également s’appliquer sur d’autres langages tels que C# ou même sur le bon vieux langage C.
Pour résoudre le point 2 – Tracer, la méthode classique serait de
En AOP, nous allons procéder de manière similaire :
Les endroits du code qui vont faire l’objet d’une trace sont des JoinPoint. Un JoinPoint est un point précis d’exécution de code. Cela peut être l’entrée dans une méthode, l’appel d’une méthode, la lecture d’un attribut, l’entrée dans une clause catch. Grosso modo c’est un endroit sur lequel votre débugger peut s’arrêter.
La sélection des JoinPoint pour lesquels on va écrire une trace (ici, « à l’entrée et à la sortie de toutes les méthodes publiques du package com...services« ) est un PointCut. Une syntaxe particulière va nous permettre de définir notre PointCut.
Avec AspectJ, nous écrirons :
Ce qui signifie « à la place des JoinPoint définis par le PointCut tracedMethods(), exécute le code qui suit ». Si on n’appelle pas proceed(), on peut même shunter complètement l’exécution de la méthode interceptée. L’exemple montre un around advice, il existe également des before et des after advices.
Un Aspect est un ensemble de PointCuts et d’Advices, de la même manière qu’une classe est un ensemble d’attributs et de méthodes. Avec AspectJ, un Aspect est par ailleurs également une classe Java. Il peut donc également recevoir des attributs et des méthodes.
Pour notre exemple, nous écrirons :
La mécanique qui permet de tisser notre Advice aux différent JoinPoint est le Weaving. Selon le framework d’Aspects que vous utiliserez, vous aurez le choix entre une ou plusieurs de ces techniques de Weaving :
Si vous avez oublié de tracer quelque chose, il est très simple de modifier le PointCut ou l’Advice et de reweaver. Si vous utilisez le plugin AspectJ pour Eclipse, des marqueurs vous indiquent après la compilation les JoinPoint « Advised » :
Une telle déclaration permet par exemple de dire à votre tisseur « je veux que toutes les classes *Dto implémentent l’interface Serializable », ou encore « je veux que toutes les classes *Dto aient un attribut private Long id avec un getter et un setter associé ». Cela permet en plus de contourner une limitation du langage Java qui est de ne pas autoriser d’héritage multiple.
Exemple AspectJ :
Vous pouvez ensuite appeler les méthodes injectées dans les classes du package domain :
Grâce à une déclaration légèrement différente, vous pouvez aussi améliorer votre compilateur pour qu’il vous signale des violations de vos règles d’architecture ou de codage. Cela vient un peu en concurrence d’outils comme PMD ou CheckStyle, mais si vous êtes déjà familiarisés avec la syntaxe AOP, vous n’aurez pas à apprendre une nouvelle syntaxe pour définir vos règles.
Exemple : « Je veux que mon compilateur signale une erreur si un domain object appelle directement un service »
Exemple AspectJ :
Avec ces quelques concepts, vous êtes déjà capables d’imaginer la puissance de l’AOP. Le logging est un exemple classique, mais on peut également utiliser l’AOP pour :
L’AOP, nouveau paradigme de programmation ?
Dans l’histoire des langages de programmation, nous avons tout d’abord programmé en assembleur, ensuite sont nés les langages procéduraux comme le C ou le Pascal. Puis sont venus les langages objets comme SmallTalk, C++, Eiffel, Java, Parallèlement nous avons vu se développer des langages fonctionnels comme LISP, ML, Erlang …. A chaque nouveau paradigme de programmation, nous prenons de la distance par rapport à la machine, nous manipulons des concepts toujours plus abstraits, qui aboutissent à des programmes de plus en plus riches.
La programmation orientée aspects, ou Aspect Oriented Programming, propose également une nouvelle approche. Ce n’est par contre pas une approche visant à remplacer une famille de langages ou une autre, elle vient en complément aux langages existants. Je dirais qu’elle est orthogonale aux langages. Elle ne remplace pas un langage, mais l’enrichit par une autre vision.
L’intérêt de ce type de programmation est de pouvoir alléger au maximum le code qui va effectivement traiter les règles métier de votre application. Le code n’est plus pollué par du code technique ayant un rapport avec telle ou telle technologie, par des constructions complexes, redondantes, et sources d’erreurs. Il devient plus lisible, plus facile à tester et à maintenir ; il peut être appréhendé par des juniors.
L’AOP permet également de gagner en flexibilité. Vous n’êtes plus obligés de penser dès le démarrage du projet à la façon dont vous gérez la sécurité, le logging ou le look and feel de votre application. Vous savez que vous avez un outil puissant qui vous permettra d’ajouter tout ça plus tard, à partir du moment ou chaque élément de votre architecture est bien défini (DAO, DTO, Service, Factory, Contrôleur, …).
Malheureusement, bien que les outils soient maintenant bien au point, l’AOP reste peu utilisée en entreprise. C’est d’ailleurs un peu par militantisme que j’écris cet article. Lorsque les frameworks majeurs l’utiliseront et proposeront des aspects utilisables directement, je pense qu’on verra cette programmation se déployer. C’est déjà un peu le cas avec Spring et comme beaucoup de personnes c’est via ce framework que je me suis intéressé à l’AOP.
On pourrait également assister à la naissance de frameworks d’Aspects, qu’il suffirait de configurer ou sous-classer (on peut avec AspectJ définir des Aspects abstraits contenant des PointCuts abstraits) pour les adapter à nos besoins. Peut être qu’on pourra à partir de ce moment parler d’un nouveau paradigme de programmation.
Excellent article Mikael!
Vivement la suite
Tout à fait d’accord avec M-L, un excellent article qui explique assez bien ce qu’est l’AOP aux initiés Java.
En attendant de passer à la pratique…
En tout cas, Geekeries gagnerait beaucoup à être plus fourni en articles de cette qualité