Le cours introductif File - UHA

publicité
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
Téléchargement