Programmation par Aspect (AOP) Frédéric Fondement Quelques méta-informations Le cours: • 5 séances + 1 colle • Mélange cours ex cathedra + dojos entrelacés – Pas aujourd’hui • 2 séances de travaux pratiques • ??? La matière • L’AOP a été inventé en 1997 • J’en entends parler depuis 2003 • Un nouveau paradigme met 10 ans à être mature… (J-M Jézéquel) • Première expérience (open source) 2011 • Mapping objet/relationnel • Quelques projets d’étudiants • Accueil le plus souvent enthousiaste -2- © F. Fondement Le plan général Un problème de modularisation Des solutions possibles Quelques « rappels » sur l’introspection et les annotations Le langage d’aspect AspectJ -3- © F. Fondement Le plan général Aujourd’hui • Donner un aperçu du problème et de l’AOP • Parcours du plan général Les fois suivantes • Maîtrise d’AspectJ • Maîtrise des annotations et de la réflexion (?) Des références • Ramnivas Laddad, AspectJ In Action, 2nd Edition, Manning, 2009 – orienté Spring, je préfère la 1ère édition de 2003… • Siobhan Clarke, Elisa Baniassad, Aspect-Oriented Analysis And Design: The Theme Approach, Addison-Wesley Educational, 2005 une méthode de développement universitaire • http://www.eclipse.org/aspectj/ • D’autres sur Moodle (article original, cours de S. Lévy, AspectJ Quickref) -4- © F. Fondement Modularisation ? En phase d’architecture A quoi bon modulariser ? • Appréhension de la complexité • Division et ordonnancement du travail, des releases • Réutilisation Les composants • Contrats • Interfaces requises et fournies, protocole, comportement, qualités non fonctionnelles • Implémentations • COTS (component off the shelf) – composants sur l’étagère • Code source ou seulement binaires • Peu d’évolutivité dans le contrat • « C’est presque ce que je veux, mais… » -5- © F. Fondement Mauvaise modularisation Problème de traçabilité • Comment retrouver le besoin correspondant à une ligne de code ? • Comment retrouver les lignes de code correspondant à un besoin ? Problème de productivité • S’occuper de plusieurs besoins à la fois divise la cohérence et l’attention Problème de réutilisabilité • Plus un module implante de besoins, moins il est réutilisable (fonctionnalités en trop) Problème de qualité • Difficulté de la revue de code Problème d’évolutivité • Un nouveau besoin qui apparaît ou un besoin déjà implémenté qui change entraîne le changement de nombreux modules. -6- © F. Fondement Un problème de modularisation On commence par un exercice: Réaliser une librairie de dessin vectoriel • • • • • • • Créer une planche avec une taille variable Ajouter / retirer une figure: point, ligne, rectangle, texte Déplacer une figure Redimensionner une figure Une figure ne peut pas sortir du dessin Représenter les figures Enregistrement des activités sur les figures: ajout/retrait du dessin, déplacement Commencer par le domaine • Diagramme de classes • Une couleur par besoin Architecture : séparation en modules -7- © F. Fondement Un problème de modularisation Leçons de l’exercice: • Tous les besoins ne sont pas toujours séparables • Toutes les fonctionnalités ne sont pas toujours séparables • Touts les aspects (les facettes) d’un système ne sont pas toujours séparables Préoccupation (concern) • Un besoin • Ex: déplacer une figure • Une fonctionnalité • Ex: afficher une figure • Une facette • Ex: contrôler la cohérence d’un rectangle • On souhaite les séparer dans des modules distincts Le problème • Apparition quasi fatale de « code spaghetti » • Une définition plus formelle suit -8- © F. Fondement L’exemple de Tomcat Parser de l’XML • Une classe suffit -9- © F. Fondement L’exemple de Tomcat Analyse d’URL • 2 classes suffisent - 10 - © F. Fondement L’exemple de Tomcat Logs • Plein de classes suffisent • Code éparpillé (code scattering) • Typique d’une préoccupation transverse (crosscutting concern) - 11 - © F. Fondement L’exemple de Tomcat Logs + Analyse d’URL • Des classes réalisent les deux. • Entrelacement des aspects techniques avec le code métier (code tangling) - 12 - © F. Fondement Le problème Encapsuler chacun des aspects du système en des modules distincts Solutions ? - 13 - © F. Fondement Les composants Encapsuler les fonctionnalités dans un composant • Découplage des modules via des interfaces • Les appels au composant sont explicitement inclus dans les autres modules; • Exemple: la librairie Log4J • Il faut encore dire quels sont les messages à archiver • Dépendances non voulues ! • Ici, MyApp dépend de l’API Log4J «component» «component» MyApp Log4J Log4JAPI - 14 - © F. Fondement Les composants idéaux (?) Encapsuler les fonctionnalités dans un composant • Une « colle » qui ajoute « à distance » des fonctionnalités à un module sans que ce dernier soit « au courant » • Cette « colle » doit pouvoir elle-même tout autant • Vivre avec d’autres « colles » • Accepter d’être « collée » «component» MyApp «component» «component» Log4MyApp Log4J Log4JAPI - 15 - © F. Fondement Design patterns Meilleure modularité, réutilisabilité: • Visiteur • Facade • … Quelques possibilités: • Des modules de fonctionnalités / propriétés additionnelles sur des classes ? - 16 - © F. Fondement Design patterns Meilleure modularité: • Visiteur • Facade • … Quelques possibilités: • Des modules de fonctionnalités / propriétés additionnelles sur des classes Ajouter des fonctionnalités à l’existant Pattern Décorateur - 17 - © F. Fondement Design patterns Meilleure modularité: • Visiteur • Facade • … Quelques possibilités: • Des modules de fonctionnalités / propriétés additionnelles sur des classes • Déclencher des comportements en fonction d’appels de messages de manière transparente pour le client ? - 18 - © F. Fondement Design patterns Meilleure modularité: • Visiteur • Facade • … Quelques possibilités: • Des modules de fonctionnalités / propriétés additionnelles sur des classes • Déclencher des comportements en fonction d’appels de messages de manière transparente pour le client Intercepter des messages puis réagir Pattern Proxy - 19 - © F. Fondement Design patterns Meilleure modularité: • Visiteur • Facade • … Quelques possibilités: • Des modules de fonctionnalités / propriétés additionnelles sur des classes • Déclencher des comportements en fonction d’appels de messages de manière transparente pour le client • Interdire la création d’objets sans les nouveautés ci-dessus ? - 20 - © F. Fondement Design patterns Meilleure modularité: • Visiteur • Facade • … Quelques possibilités: • Des modules de fonctionnalités / propriétés additionnelles sur des classes • Déclencher des comportements en fonction d’appels de messages de manière transparente pour le client • Interdire la création d’objets sans les nouveautés ci-dessus Gestion décentralisée de la création des objets Pattern Abstract Factory - 21 - © F. Fondement Design patterns Meilleure modularité: • Visiteur • Facade • … Quelques possibilités: • Des modules de fonctionnalités / propriétés additionnelles sur des classes • Déclencher des comportements en fonction d’appels de messages de manière transparente pour le client • Interdire la création d’objets sans les nouveautés ci-dessus Il faut que toutes les classes soient prévues pour à l’avance ! - 22 - © F. Fondement Design patterns Un patron de conception apparaît pour répondre à un problème récurrent Leçon du GL et de l’IDM: introduire des abstractions • Les abstractions solutionnent les problèmes récurrents Un patron de conception identifie un défaut d’un langage • Un patron de conception objet identifie un défaut commun aux langages objets Solution: augmenter le langage pour intégrer des design patterns ! • Ex: systématiser l’utilisation des interfaces. - 23 - © F. Fondement Augmenter un langage Cas typique d’un langage *.java *.java Source Source Files Files Parser Code Generator Java AST *.class *.class “Binary” “Binary”Files Files Type Checker - 24 - © F. Fondement Augmenter un langage Exemple « Replier » le langage étendu dans le langage d’origine Annotations Java Code Generator Folder *.java++ *.java++ Source SourceFiles Files Parser ++ Java++ AST *.class *.class “Binary” “Binary”Files Files Java AST Type Checker - 25 - © F. Fondement Annotations Java Un exemple: package fr.uha.ensisa.ff.decorations; import java.lang.annotation.*; @Documented //Should appear in Javadoc for annotated elements @Inherited //Annotation is inherited @Retention(value=RetentionPolicy.RUNTIME) //Visible by reflexion @Target(value=ElementType.TYPE) //For types (no method, param, var…) public @interface Decorations { Class<? extends Decorator<?,?>>[] value(); //Mandatory param String[] args() default {}; //Optional param } - 26 - © F. Fondement Annotations Java Un exemple: package fr.uha.ensisa.ff.deco.figs; import …; … import fr.uha.ensisa.ff.decorations.DefaultImpl; @DefaultImpl(DefaultPoint.class) @Decorations({PointMoveDecoration.class, PointResizeDecoration.class}) public interface Point extends Figure { public int getX(); public void setX(int x); public int getY(); public void setY(int y); } - 27 - © F. Fondement Annotations Java Éléments pouvant être annotés • Packages • Types • Classe, Interface, Enumération, Déclaration d’annotation • Annotation • Champ • Attribut, Énuméré • • • • Méthode Constructeur Paramètre Variable locale Ressemblance avec les profils UML • Il faut également créer les outils pour en faire quelque chose ! • Dans notre cas: injecter des décorateurs - 28 - © F. Fondement Augmenter un langage Exemple du langage Java Visiteurs d’annotation s *.java *.java Annotated Annotated Source SourceFiles Files *.java *.java Source SourceFiles Files *.class *.class Annotation Annotation Processors Processors Parser Ou pas… Annotation Processing Tool Annotated Java AST - 29 - © F. Fondement Annotations java On peut imaginer injecter des patterns à l’aide d’annotations En pratique, on utilise plus souvent la réflexion • Exploration d’annotations au runtime • D’où le @Retention(value=RetentionPolicy.RUNTIME) de tout à l’heure • Exemple intégrable dans une factory: Decorations decorationAnnotation = Point.class.getAnnotation(Decorations.class); for (Class deco : decorationAnnotation.value()) { //Create decorator of class "deco" } - 30 - © F. Fondement Move et Resize avec des annotations Exemple d’architecture sur la figure: move et resize ne se connaissent pas Annotations definitions and machinery. fr.uha.ensisa.ff.decorations Interface definitions. fr.uha.ensisa.ff.deco.figs fr.uha.ensisa.ff.deco.figs.defaultImpl References to decorations and default implementation Could be generated, e.g. by an annotation processor fr.uha.ensisa.ff.deco.figs.move fr.uha.ensisa.ff.deco.figs.resize fr.uha.ensisa.ff.deco.figs.defaultImpl.abstractDecorators - 31 - © F. Fondement Annotations Java Exemple d’architecture sur la figure: Défaut majeur: tous les ajouts sont déclarés à un endroit précis • Ne permet pas de modifier du code existant (COTS) package fr.uha.ensisa.ff.deco.figs; import fr.uha.ensisa.ff.deco.figs.defaultImpl.DefaultPoint; import fr.uha.ensisa.ff.deco.figs.move.PointMoveDecoration; import fr.uha.ensisa.ff.deco.figs.resize.PointResizeDecoration; … @DefaultImpl(DefaultPoint.class) @Decorations({PointMoveDecoration.class, PointResizeDecoration.class}) public interface Point extends Figure { public int getX(); … } - 32 - © F. Fondement Cet exemple Qualités • Séparation des préoccupations • Ni code éparpillé, ni entrelacement – Move et Resize ne se connaissent pas • Simplicité d’intégrer/retirer de nouvelle fonctionnalités • Implicitement disponibles à tout le monde • Identification précise des endroits où sont implantées les fonctionnalités Défauts • Pas de modifications de comportement existant • Encore moins de comportement génériques – Par exemple, l’enregistrement des activités ; propositions ? • Quelqu’un doit tout connaître • Ici: l’interface • Il faut écrire le processeur d’annotations • Générateur de code • Transformateur de programme (c.à.d. de modèle) - 33 - © F. Fondement La réflexion Permet de demander à un objet quel est sa classe • On obtient en retour un objet de type classe La classe classe • Connaît son nom • Connaît ses ancêtres, ses attributs, ses méthodes, ses constructeurs Les classes attribut, méthode, constructeur • Peuvent êtres invoquées - 34 - © F. Fondement La réflexion Certains langages permettent modifier ces données par programme (ex: le Meta Object Protocol de Smalltalk) • • • • Ajouter un attribut Créer une nouvelle classe Ajouter des héritages Changer un corps de méthode On peut alors à distance injecter du comportement par un module séparé (intercession) • Exemple: expliquer à une classe (Point) qu’elle implémente de nouvelles interfaces (Movable, Resizeable) et qu’elle possède de nouvelle méthodes (move, resize) • Exemple: expliquer à une méthode qu’une fois qu’elle a fini, elle doit le signaler à quelqu’un • Avantage: pas de générateur de code • Inconvénient: Il faut maîtriser le métamodèle du langage • Inconvénient (majeur): Il faut avoir un langage qui le supporte • Pas le cas de C, C++, C#, Java (voir tout de même BCEL et ASM), Ada, … - 35 - © F. Fondement La réflexion Un exemple pour le langage MTL: Programme à transformer: library MyTransformation; main() : Standard::Void { new Transformer().run(); } Programme désiré: library MyTransformedTransformation; main() : Standard::Void { new Transformer().run(); 'Transformation performed'.toOut(); } - 36 - © F. Fondement La réflexion Un exemple pour le langage MTL: Métamodèle (extrait): Library name : String 0..1 1 InheritanceProperty Instruction 0..1 instructions 1..* {ordered} parentClasses 1 * parentClasses * 0..1 User Class definedClasses definedOperations * definedMethods 0..1 0..1 * 0..1 0..1 Operation * * definedAttributes {ordered} * parameters Attribute VarDeclaration * 0..1 returnType type 1 BMTLTypeProperty - 37 - 1 type © F. Fondement La réflexion Un exemple pour le langage MTL: La transformation lib : BasicMtlASTView::BasicMtlLibrary; lib.name := 'MyTransformedTransformation'; foreach (op : BasicMtlASTView::Operation) lib.definedOperations) in (l op.name.[=]('main')) { where (o sl := new BasicMtlASTView::StringLiteral(); sl.value := 'Transformation performed'; oi := new BasicMtlASTView::OperationCall(); oi.name := 'toOut'; oi.caller := sl; oi.arguments := newOrderedSet(); op.instructions := op.instructions.append(oi); } Nécessite de connaître le métamodèle du langage manipulé - 38 - © F. Fondement La réflexion En résumé MTL Concrete Syntax MTL Developer «represents» For "Reflective Programming" «metamodel» MTL MTL Compiler Developer - 39 - © F. Fondement L’idée de l’AOP Permettre de décrire des extensions type intercession • L’inventeur de l’AOP (Gregor Kiczales) est à la base un spécialiste de la réflexion • Ce spécialiste y a travaillé au Xerox PARC d’où s’est également évadé Smalltalk… Pas besoin d’avoir connaissance du métamodèle • Les langages d’aspect sont généralement des extensions au langage sous-jacent et en réutilisent une grande part Modifie de l’existant • Besoin d’un langage sous-jacent, avec ses abstractions, ses paradigmes, etc. - 40 - © F. Fondement L’idée de l’AOP L’AOP ne peut pas fonctionner tout seul ! • Il faut quelque chose à modifier L’AOP ne remplace pas les autres paradigmes ! • Comme l’objet n’a pas remplacé de procédural ou le fonctionnel L’AOP ne permet pas de faire plus que la programmation dans d’autres langages • Tous sont Turing-capables • Meilleure modularisation L’AOP est moins permissive que la réflexion ou la transformation de modèle • Simplicité au détriment de la souplesse - 41 - © F. Fondement L’idée de l’AOP Des langages d’aspects pour plein de langages ; selon Wikipedia (10/2011): • • • • • • • • • • • • • • • ActionScript (Flash) 2.0 • AutoHotkey • .NET Framework languages (C# / VB.NET) • C / C++ • Cobol • Cocoa / ObjectiveC • ColdFusion • Common Lisp • Delphi • Delphi Prism • e (IEEE 1647) • Groovy • Haskell • Java - 42 - JavaScript Emacs Lisp Logtalk Lua make ML Perl PHP Prolog Python Ruby Squeak Smalltalk UML 2.0 XML © F. Fondement Concepts fondamentaux de l’AOP L’aspect (aspect) • L’unité fondamentale à l’instar de la classe pour la programmation orientée objet (POO) ou la fonction pour le fonctionnel. • Conteneur pour les notions suivantes La déclaration inter-type (intertype declaration) • En POO: ajout d’attributs, de méthodes, d’extension, d’héritage… La coupe transverse (pointcut) • Désigne les endroits où une modification comportementale doivent avoir lieu La méthode d’aspect (advice) • La modification comportementale en question Merci à granddictionnaire.com pour les traductions… - 43 - © F. Fondement Move et Resize avec des aspects Move et resize ne se connaissent pas Figure ne connaît ni move, ni resize «package» fr.uha.ensisa.ff.aop figs figs.move - 44 - figs.resize © F. Fondement L’architecture complète «package» fr.uha.ensisa.ff.aop drawing figs figs.move figs.resize drawing.figs drawing.figs.rec drawing.figs.indraw figs.awt drawings.fig.rec.move Prevents a figure escapes its drawing - 45 - drawing.figs.rec.resize © F. Fondement Remarques sur l’architecture drawing ne connaît pas figs • Associé par drawing.figs drawing.indraw ne connaît ni move ni resize • S’adaptera aux nouvelles fonctionnalités possibles drawing.figs ne connaît pas l’AWT drawing.rec ne parvient pas à s’adapter automatiquement à move et à resize • Besoins de modules complémentaires Pas besoin de factory • Tous les objets instance de classes définies dans figs (entre autre) disposent de toutes les fonctionnalités requises - 46 - © F. Fondement La machinerie L’AOP en intégration statique: le Tisseur d’aspect (aspect weaver) est invoqué à la compilation Schéma le plus courant Core Core program program Parser Code Generator Core lang. AST Aspect Weaver Aspects Aspects Aspect Parser Aspect lang. AST Compiled Compiled Program Program Core lang. AST Type Checker Remarque: le tisseur n’est qu’une transformation de modèle - 47 - © F. Fondement La machinerie L’AOP en intégration dynamique: le Tisseur d’aspect (aspect weaver) est invoqué au chargement des modules Au chargement du module, on vérifie avec les aspects connus s’il nécessite d’être modifié Pas disponible pour tous les langages • Notion de chargement dynamique de module Plus difficile à construire que le tisseur statique • Modifier le code binaire au vol • Problème d’efficacité - 48 - © F. Fondement La machinerie Le cas AspectJ Le tisseur est invocable sous deux formes • Statique • Compilateur ajc • Capable de tisser des sources ou des jars • Code compilé interprétable par n’importe quelle machine virtuelle (la bibliothèque runtime AspectJ aspectjrt.jar doit être accessible) • Dynamique • Option de la machine virtuelle -javaagent:pathto/aspectjweaver.jar ou commande aj Le langage existe sous deux formes • Extensions au langage Java • Annotations sur le langage Java Excellent support dans Eclipse - 49 - © F. Fondement La machinerie Le cas AspectJ en mode statique L’entrée est indifféremment un code déjà tissé ou non. Peut être un jar. *.class *.class Parser Generator Java AST AspectJ Weaver *.aj *.aj Aspect Parser AspectJ AST *.class *.class Java AST Type checker - 50 - © F. Fondement Un aspect C’est un genre de classe singleton: // Fichier "fr/uha/ensisa/ff/aop/figs/move/Move.aj" package fr.uha.ensisa.ff.aop.figs.move; import fr.uha.ensisa.ff.aop.figs.*; public aspect Move { //Déclarations intertypes //Déclarations de points de coupe //Déclarations de code advice } - 51 - © F. Fondement Un aspect C’est un genre de classe singleton: • On peut également utiliser la syntaxe annotée: // Fichier "fr/uha/ensisa/ff/aop/figs/move/Move.java" package fr.uha.ensisa.ff.aop.figs.move; import org.aspectj.lang.annotation.Aspect; import fr.uha.ensisa.ff.aop.figs.*; @Aspect public class Move { //Déclarations intertypes //Déclarations de points de coupe //Déclarations de code advice } - 52 - © F. Fondement Les déclarations intertypes Ajouter un attribut, une méthode: • Comme décrire un membre • On ajoute avant le nom le nom du type concerné public aspect Move { public void Point.move(int deltaX, int deltaY) { this.setX(this.getX() + deltaX); this.setY(this.getY() + deltaY); } … } - 53 - © F. Fondement Les déclarations intertypes Déclarer une implémentation, une extension • Automatiquement, les méthodes d’interfaces / abstraites doivent être intégrées public aspect Move { declare parents: Figure implements Movable; … } - 54 - © F. Fondement Les déclarations intertypes Déclarer une annotation • Sur un type (@type), une méthode (@method), un constructeur (@constructor), un attribut (@field) public aspect MoveChanges { declare @method: void Movable.move(int, int) : @Change(kind="move"); } - 55 - © F. Fondement Tissage statique vs. dynamique Question performance: Net avantage au tissage statique Question intégration: Net avantage au tissage dynamique: • Tous les modules ne connaissent pas tous les aspects • Imaginons une méthode supplémentaire dans une interface: • L’interface est tissée (forcément) • Connait-on toutes les implémentations de cette interface ? – D’aujourd’hui et de demain ? • Est-on sûr que toutes les implémentations sont incluses dans le tissage ? – Seul le tissage dynamique le garantit. • Nous reverrons arriver ce problème régulièrement… - 56 - © F. Fondement Changements comportementaux Il n’est pas toujours suffisant d’ajouter de nouvelles fonctionnalités: il faut savoir qui et où on les appelle ! Insuffisant en cas de préoccupation transverse • Il faut pouvoir modifier un comportement existant • Plusieurs modifications peuvent intervenir à un même endroit • Une modification peut impacter plusieurs endroits «component» MyApp «component» «component» Log4MyApp Log4J Log4JAPI - 57 - © F. Fondement Changements comportementaux Il n’est pas toujours suffisant d’ajouter de nouvelles fonctionnalités Insuffisant en cas de préoccupation transverse • Il faut pouvoir modifier un comportement existant • Plusieurs modifications peuvent intervenir à un même endroit • Une modification peut impacter plusieurs endroits Endroit ? Point de jonction ! (join point) • • • • • • Un appel de méthode Une exécution de méthode Une lecture de propriété L’évaluation d’une condition … Toute activité dans un programme ; on n’est plus dans la structure - 58 - © F. Fondement Trouver les bons points de jonction C’est le rôle des coupes transverses (pointcuts) Ce que peut faire AspectJ: Lié à une méthode • Détecter un appel de méthode • Détecter une exécution de méthode Lié à un constructeur • • • • Détecter un appel de constructeur Détecter une exécution de constructeur Détecter une initialisation Détecter un chargement de classe Lié à un attribut • Détecter une lecture d’attribut • Détecter une mise à jour d’attribut Lié à une exception • Détecter un traitement d’exception - 59 - © F. Fondement Trouver les bons points de jonction Exemples: L’appel de la méthode Rectangle.move: call(public void Rectangle.move(int, int)) L’exécution du constructeur de rectangle: execution( public Rectangle.new(Point, Point)) - 60 - © F. Fondement Trouver les bons points de jonction Décrire plusieurs points de jonction à la fois On peut décrire les « paramètres » des pointcuts à l’aide de jokers: * pour un nom, un type • Ex: call( public * fr.uha.ensisa.*.aop.*.Point.get*()) Rien pour un paramètre • Ex: call(* Point.get*()) .. Pour des suites de paramètres ou de paquetages * • Ex: call(* fr..aop..Point.get(..)) + pour désigner tous les sous-types • Ex: call(* Point+.get*(..)) - 61 - © F. Fondement Trouver les bons points de jonction Remarques: Il existe d’autres sélecteurs plus « large spectre » • Tous les points de jonction liés à une méthode, un type • Tous les points de jonction pourvu qu’ils soit atteint via un flot spécifique • … Il est possible de faire des opérations sur les sélecteurs • Négation • Conjonction • Disjonction Nous verrons cela plus tard… - 62 - © F. Fondement Trouver les bons points de jonction Définition d’un pointcut: public aspect OwnerFigs { Nom … pointcut allFigureSets(): set(Figure+ Figure+.*); … Sélecteu } r Un pointcut est • Une définition de sélecteur • Un sélecteur (réutilisable). - 63 - © F. Fondement Changements comportementaux Il n’est pas toujours suffisant d’ajouter de nouvelles fonctionnalités Insuffisant en cas de préoccupation transverse • Il faut pouvoir modifier un comportement existant • Plusieurs modifications peuvent intervenir à un même endroit • Une modification peut impacter plusieurs endroits Modification ? Code advice! (advice) • Remplacer • S’insérer avant • S’insérer après - 64 - © F. Fondement Exprimer les modifications On a trouver un (des) endroits (join points). On veut y injecter un comportement Avant l’exécution du join point: before Après l’exécution du join point: after • Dans tous les cas • En cas de réussite de l’exécution (after() returning) • En cas de lancement d’exception (after() throwing) Au lieu de l’exécution du join point: around • Peut exécuter le join point au sein de l’advice - 65 - © F. Fondement Exprimer les modifications Définition d’un advice before: public aspect OwnerFigs { … Sélecteur before(): allFigureSets() { System.out.println( "OwnerFigs.before()"); } Comportement … inséré } - 66 - © F. Fondement Exprimer les modifications Définition d’un advice after: public aspect OwnerFigs { … Sélecteur after(): allFigureSets() { System.out.println( "OwnerFigs.before()"); } Comportement … inséré } - 67 - © F. Fondement Exprimer les modifications Définition d’un advice around: public aspect OwnerFigs { Sélecteur … void around(): allFigureSets() { System.out.println("OwnerFigs.before()"); proceed(); System.out.println("OwnerFigs.after()"); } … Comportement inséré } - 68 - © F. Fondement Exprimer les modifications Définition d’un advice around: public aspect OwnerFigs { Type de retour ; dépend du sélecteur … void around(): allFigureSets() { System.out.println("OwnerFigs.before()"); proceed(); System.out.println("OwnerFigs.after()"); } … Exécution du join point original (ici, retourne void) } - 69 - © F. Fondement En conclusion Un aspect: Est capable d’injecter de nouvelles fonctionnalités • Déclarations inter-types Est capable de sélectionner des points d’exécution dans un programme • Pointcuts permettant d’en sélectionner un précis ou un groupe à l’aide de délecteurs Est capable d’injecter des comportements additionnels, voire différents • Advice injectant aux join points sélectionnés par un pointcut (ou un autre sélecteur) un comportement avant, après, ou en lieu et place - 70 - © F. Fondement En conclusion Simplifie la modularisation, notamment en cas de préoccupation transverse. Injection de nouvelles fonctionnalités - 71 - © F. Fondement En conclusion Simplifie la modularisation, notamment en cas de préoccupation transverse. Préoccupation • • • • Besoin Fonctionnalité Facette … Transverse • Influant sur d’autres fonctionnalités Exemple dans le monde de l’automobile • L’implantation d’airbags est un métier • La création de caisse et de planche de bord sont deux autres métier • La conception des airbags influe et sur la conception de la planche de bord, et sur celle de la caisse - 72 - © F. Fondement En conclusion Simplifie la modularisation, notamment en cas de préoccupation transverse. Injecte des modifications à du code existant • Une modifications peut se retrouver à plusieurs endroits, y compris dans plusieurs modules différents • Pas besoin de savoir précisément où grâce aux sélecteurs et aux wildcards (*, .., +, …) • Exemple: à chaque fois que dans un descendant de Figure, un attribut de type Figure est remplacé. • Possibilité de modifier des modules inconnus, voire futurs. - 73 - © F. Fondement En conclusion Simplifie la modularisation, notamment en cas de préoccupation transverse. Injecte des modifications à du code existant • Le tisseur fait la correspondance • Le tisseur doit donc tout connaître «component» Module2 «component» «component» Recorder Log4J Log4JAPI «component» Module1 - 74 - © F. Fondement En conclusion Simplifie la modularisation, notamment en cas de préoccupation transverse. Injecte des modifications à du code existant • A besoin de code existant • L’AOP ne se suffit pas à elle-même • On pouvait faire cela avant l’AOP avec la transformation de modèle, la génération de code, ou la réflexion • Mais c’était plus complexe. - 75 - © F. Fondement