B1 Chapitre 1 Le Paradigme Aspect
B1 Chapitre 1 Le Paradigme Aspect
B1 Chapitre 1 Le Paradigme Aspect
Le paradigme aspect
1.1 INTRODUCTION
La programmation orientée aspect (POA) est un nouveau paradigme de programmation
qui trouve ses racines en 1996, suite aux travaux de Gregor Kiczales et de son équipe au
Centre de Recherche Xerox à Palo Alto. La POA est donc une technologie relativement jeune,
puisque les premiers outils destinés à son utilisation ne sont apparus qu’à la fin des années 90.
Cependant, l’adoption de la POA est plutôt rapide puisqu’elle semble déjà bien diffusée
aujourd’hui. A titre comparatif, le langage Simula, pionnier de la programmation orienté
objet, est apparu en 1967, alors que la POO n’a réellement émergé qu’au cours des années 80
avec C++.
En effet, aidée par une compatibilité entre ses concepts sous-jacents et ceux existants, la
POA peut être intégrée à moindre coût par les entreprises en étendant leurs outils. Par
exemple, la POA pour Java est intégrée dans Eclipse via un plugin qui permet l’utilisation du
langage AspectJ. Ce langage, dont les premières versions furent disponibles en 1998, étend en
fait le langage Java en introduisant de nouveaux mots-clés permettant de programmer des
aspects. Mais AspectJ n’est pas l’unique langage orienté aspect. Même si celui-ci reste le plus
utilisé, d’autres outils existent. On peut notamment citer JAC, JBoss AOP et AspectWerkz
rien que pour le langage Java, mais il existe également des outils pour les langages C, C++,
C# ou Smalltalk. La compatibilité entre les concepts utilisés par la POA et les outils existants
est due au fait que la POA ne remet pas en cause les autres paradigmes de programmation
(comme l’approche procédurale ou objet). Au contraire, elle les étend en proposant des
mécanismes complémentaires afin d’améliorer la modularité d’une application (et donc
faciliter la réutilisation et la maintenance.
5
CHAPITRE 1 – LE PARADIGME ASPECT 6
Ces méthodes utilisent intensivement les raffinements successifs. Le plus haut niveau
représente l’ensemble du problème. Chaque niveau est ensuite décomposé en respectant les
entrées/sorties du niveau supérieur. La décomposition se poursuit jusqu’à arriver à des
composants maîtrisables (figure 1.1).
6
CHAPITRE 1 – LE PARADIGME ASPECT 7
En résumé, l’architecture du système est dictée par la réponse au problème (i.e. la fonction
du système).
Dès les années 1980, l'approche objet s'est généralisée dans les tâches d'analyse et de
conception, car elle permet d'affronter la complexité croissante des grands systèmes,
beaucoup plus facilement que ne l'autorise l'approche procédurale. La Conception Orientée
Objet (COO) est la méthode qui conduit à des architectures logicielles fondées sur les objets
du système, plutôt que sur la fonction qu’il est censé réaliser. Les techniques orientées objet
sont mieux adaptées à la modélisation que la décomposition fonctionnelle, qui tend à produire
des modèles plus fragiles aux évolutions et par conséquent plus difficiles à maintenir. Un
système, et surtout, dans le cas des systèmes complexes, peut se modéliser comme une
collection d'éléments (les objets) capables d'interagir pour travailler ensemble.
Un objet est un élément de granularité moyenne, plus petit qu'un système, qu'un sous-
système ou qu'un module, mais plus grand qu'une donnée élémentaire. La taille d'un objet doit
correspondre à une granularité facile à gérer et garantissant la cohésion du contenu de l'objet.
Un objet est une entité logicielle ayant une identité capable de sauvegarder un état c'est-à-
dire un ensemble d’information dans des variables internes, répondant à des messages précis
en déclenchant des activations internes appropriés qui changent l’état de l’objet. Ces opération
7
CHAPITRE 1 – LE PARADIGME ASPECT 8
sont appelées méthodes. Ce sont des fonctions liées à des objets et qui précisent le
comportement de ces objets.
Une classe est un type de données abstrait qui précise des caractéristiques (attributs et
méthodes) communes à toute une famille d’objets et qui permet de créer (instancier) des
objets possédant ces caractéristiques.
1.2.2.4 Agrégation
Il s’agit d’une relation entre deux classes, spécifiant que les objets d’une classe sont des
composants de l’autre classe. Une relation d’agrégation permet donc de définir des objets
composés d’autres objets. L’agrégation permet donc d’assembler des objets de base, afin de
construire des objets plus complexes.
En approche objet, l’évolution des besoins aura le plus souvent tendance à se présenter
comme un changement de l’interaction des objets. S’il faut apporter une modification aux
8
CHAPITRE 1 – LE PARADIGME ASPECT 9
données, seul l’objet incriminé (encapsulant cette donnée) sera modifié. Toutes les fonctions à
modifier sont bien identifiées : elles se trouvent dans ce même objet : ce sont ses méthodes
La programmation orientée objet (POO) offre plusieurs avantages grâce aux différents
atouts qu'elle présente en terme d'héritage, polymorphisme, etc. Cependant, ce paradigme de
programmation n'est pas dépourvu de défauts. En particulier, la réutilisation n'est pas toujours
aisée. C'est notamment le cas pour les applications qui sont sujets à des changements
fréquents et qui nécessitent, en plus de la définition des objets métiers, la prise en compte des
différentes propriétés transversales, telles que la synchronisation des accès concurrents et la
sécurité. De telles propriétés affectent l'exécution de différents objets. De ce fait, leurs
définitions se trouvent mélangées avec le code métier et dispersées entre les différentes
classes.
9
CHAPITRE 1 – LE PARADIGME ASPECT 10
Les exigences non-fonctionnelles sont difficilement prises en compte dans une telle
découpe et on se contente donc de les intégrer dans les différents modules fonctionnels. La
figure 1.2 montre un exemple d'une application composée de 3 modules fonctionnels dans
lesquels on a du y insérer l'implémentation d'exigences de performance, de journalisation
(enregistrement d'informations dans un fichier journal) et de synchronisation.
10
CHAPITRE 1 – LE PARADIGME ASPECT 11
− Maintenance et évolutivité du code difficile: lorsque l'on veut faire évoluer le système,
on doit modifier de nombreux modules. Modifier chaque sous-système pour répercuter les
modifications souhaitées peut conduire à des incohérences.
11
CHAPITRE 1 – LE PARADIGME ASPECT 12
Cette nouvelle notion d’aspect, introduite par la POA, change la façon dont le design
d’une application est réalisé. Les fonctionnalités transversales sont expulsées du code métier
(voir figure 1.3). La première étape du design constitue l’identification des classes en tant que
socle de l’application. Il s’agit des données et des traitements qui sont au coeur de la
problématique de l’application et qui répondent aux besoins premiers de celle-ci.
12
CHAPITRE 1 – LE PARADIGME ASPECT 13
Les préoccupations transversales du programme ne doivent donc pas se retrouver dans les
classes. Elles sont identifiées dans la deuxième partie du design : l’identification des aspects
(voir figure 1.4).
Les aspects identifiés peuvent être implémentés en parallèle. Ainsi, la partie sécurité d’une
application pourra, par exemple, être confiée au service approprié de l’équipe de
développement, pendant que l’aspect persistance sera implémenté par un autre service.
Les points de jointure désignent des points précis dans l'exécution d'un programme. Il
s'agit ici de points bien précis et exploitables comme l'appel d'une méthode, l'affectation d'une
variable,... etc. Un point de jonction est un point dans l’exécution d’un programme autour
duquel un ou plusieurs aspects peuvent être ajoutés.
1. Méthodes. C’est autour des méthodes que les aspects se greffent le plus souvent. Ce
n’est pas étonnant puisque les méthodes forment l’outil principal de la POO et structurent
l’exécution du programme. Les événements liés aux méthodes qui constituent des points de
jonction sont l’appel d’une méthode et l’exécution de celle-ci.
13
CHAPITRE 1 – LE PARADIGME ASPECT 14
1.3.2 Coupes
Points de jonction et coupes sont conceptuellement fort différents : alors qu’un point de
jonction représente un point dans l’exécution d’un programme, une coupe est un morceau de
code défini dans un aspect. C’est à elle qu’est attribué le rôle de définir la structure
transversale d’un aspect. Pour ce faire, une coupe est définie par des mots-clés identifiant des
ensembles de points de jonction. Ces ensembles sont unis dans la coupe par des opérations
ensemblistes de base (intersection, union et complémentarité).
Les mots-clés utilisés par la coupe désignent chacun un ensemble de points de jonction en
spécifiant son type (appel de méthode, lecture d’attributs, ...) et une expression qui précise le
type (la méthode α, l’attribut β, ...). Ces expressions peuvent faire usage de quantificateurs à
des fins de généralité (ex : toutes les méthodes dont le nom est μ, toutes les méthodes qui
prennent en paramètre une instance de la classe λ, tous les attributs de la classe φ,...).
Les outils existants fournissent également des mots-clés identifiant des ensembles ne
dépendant pas d’un type (ex : tous les points de jonction dans le code d’une méthode, tous les
points de jonction d’une classe, ...). Ceci permet une plus riche expressivité dans la définition
de la coupe.
14
CHAPITRE 1 – LE PARADIGME ASPECT 15
Un code advice définit donc un bloc de code qui va venir se greffer sur les points de
jonction définis par la coupe à laquelle il est lié. Il existe différentes manières de greffer un
code advice sur un point de jonction. Le code advice spécifie lui-même la façon dont il
souhaite s’intégrer aux points de jonction de sa coupe.
Les aspects définissent des morceaux de code et les endroits de l’application où ils vont
s’appliquer. Un traitement automatique est donc nécessaire pour intégrer ces aspects dans
l’application afin d’obtenir un programme fonctionnel fusionnant classes et aspects.
15
CHAPITRE 1 – LE PARADIGME ASPECT 16
Cette opération, représentée sur la figure 1.5, se nomme le tissage (weaving) et est réalisée
par le tisseur d’aspects (aspect weaver ).
Le tissage peut se réaliser soit à la compilation, soit à l’exécution. Lorsqu’il est effectué a
la compilation, le tisseur d’aspects se comporte pratiquement comme un compilateur (on le
dénomme même parfois compilateur d’aspects). Il prend en entrée les classes et les aspects
pour donner en sortie une application tissée. La sortie peut être sous la forme d’exécutable, de
byte code ou encore de code source. La dernière solution permettant aux programmeurs
d’observer les effets du tissage. L’entrée, quant à elle, peut être sous forme de code source ou
de byte code. Une entrée sous forme de byte code permet de rendre orienté aspect une
application dont le code source n’est pas connu (une application commerciale par exemple).
Lorsque le tissage est effectué à l’exécution, le tisseur d’aspect se présente sous la forme
d’un programme qui permet d’exécuter à la fois l’application et les aspects. Les aspects ne
sont donc pas intégrés dans l’application à l’avance et existent encore individuellement à
l’exécution. Cette technique est intéressante car il est possible d’ajouter, de modifier ou
d’enlever des aspects au moment de l’exécution (runtime). Le tissage à l’exécution est aussi
appelé tissage dynamique.
Etant donné qu’un aspect greffe des codes advices sur les points de jonction définis par sa
coupe, il se peut que plusieurs aspects aient des points de jonction en communs dans leur
coupe. Or dans certains cas, il est nécessaire qu’un code advice soit exécuté avant un autre
(s’il y a des dépendances entre aspects.). Les outils de la POA fournissent à cet effet des
techniques permettant de spécifier l’ordre dans lequel doivent être tissés les aspects. Si le
programmeur ne spécifie pas d’ordre, aucune garantie n’est donnée en général quant à l’ordre
résultant après le tissage. Cependant, certains outils tels qu’AspectJ proposent des règles
implicites d’ordonnancement d’aspects.
16
CHAPITRE 1 – LE PARADIGME ASPECT 17
Figure 1.6 - Intégration du code des composants et des aspects pour former le système final
17
CHAPITRE 1 – LE PARADIGME ASPECT 18
Ayant présenté en détail le paradigme de la programmation par aspects d’un point de vue
conceptuel et général, nous découvrons dans ce qui suit, les langages de programmation par
aspects. Et en particulier AspectJ, une extension du langage Java permettant la
programmation par aspects.
AspectJ [Xer02], est une extension de Java permettant la programmation par aspects. En
choisissant Java comme langage de base, AspectJ profite de l’ensemble des bénéfices de Java
et rend ainsi facile, pour des programmeurs Java, son utilisation. AspectJ est qualifié
d’extension « compatible » du langage Java [KHH+01] dans la mesure où :
· Tous les programmes valides AspectJ sont capables de s’exécuter sur n’importe quelle
machine virtuelle Java.
· Il est possible d’étendre l’ensemble des outils Java pour supporter AspectJ, ceci inclut
les IDEs, les outils de documentation, et les outils de conception;
Etant un langage de programmation par aspects, AspectJ est une spécification d’un
langage aussi bien qu’un outil assurant le tissage des aspects et la compilation des codes
source.
AspectJ utilise le terme de point de jonction (Join point) décrit dans la POA. Les points de
jonction représentent des points, bien définis, dans le flot d’exécution des composants
fonctionnels de l’application [Xer02]. Ce sont des éléments fondamentaux dans toute
implantation par aspects. Ils sont relatifs à l’ensemble des points où les aspects interagissent
18
CHAPITRE 1 – LE PARADIGME ASPECT 19
avec les composants. Un point de jonction peut être un simple appel à une méthode, une
réception d’un appel à une méthode ou encore une exécution d’une méthode (appelé
respectivement en anglais, method call, method call reception et method execution join point).
Nous distinguons aussi d’autres types de points de jonction de type lecture ou écriture d’un
attribut (appelé respectivement en anglais field get et field set joint point). Le tableau suivant
résume les différents types de point de jonction offerts par AspectJ.
Tableau 1.1 – Différents types de points de jonction offerts par AspectJ [KHH’01]
Une coupe transverse (pointcut) permet la définition des points de jonction à utiliser pour
composer chaque aspect avec les composants. C’est une collection de points de jonction et,
19
CHAPITRE 1 – LE PARADIGME ASPECT 20
• gets (Attribut) / sets (Attribut): Permet de référencer les points de jonction correspondant
à l’accès aux attributs d’un objet. L’accès aux attributs est considéré comme un appel de
méthode.
Il est possible d’utiliser des expressions régulières pour définir des coupes transverses. Par
exemples :
• Receptions (* Point.*(..)) référence toutes les réceptions d’appels de toutes les méthodes
de la classe Point quels que soient leurs paramètres ou leur valeur de retour.
20
CHAPITRE 1 – LE PARADIGME ASPECT 21
Les méthodes d’aspect sont associées à des points de l’exécution d’une application (points
de jonction) afin d’en compléter le comportement. Les méthodes d’aspect ont une structure
proche de celle des méthodes Java. Elles permettent de décrire dans la syntaxe Java classique,
la manière dont les comportements des points de jonction associés sont modifiés, ceci selon
trois possibilités :
• After, la méthode d’aspect sera exécutée après la méthode associée au point de jonction,
after() : moves() {
flag = true;
Cette méthode s’applique sur la coupe transverse appelée moves. Cette méthode d’aspect
est de type after(): elle ne sera exécutée qu’après la fin de l’exécution des méthodes associées
aux points de jonction de la coupe transverse moves. Les parenthèses vides de after()
indiquent que cette méthode d’aspect ne requiert aucun paramètre.
Un aspect est l’abstraction de plus haut niveau du langage AspectJ. Cette structure permet
d’encapsuler le code nécessaire à la modélisation d’une préoccupation transversale tout
comme une classe en Java permet d’encapsuler le code nécessaire à la modélisation d’un
objet.
21
CHAPITRE 1 – LE PARADIGME ASPECT 22
Un aspect est structurellement très proche d’une classe Java même si sa sémantique en est
différente. En plus de contenir les points de coupure et les greffons dont il a besoin, un aspect
peut déclarer des méthodes et des variables, étendre d’autres aspects ou classes et
implémenter des interfaces.
La différence majeure entre un aspect et une classe Java réside dans le fait qu’un aspect
ne peut pas être instancié à l’aide de l’instruction new. En effet l’instanciation des aspects
dans un système se fait via une phase de < tissage > (weaving).
Le tissage (weaving) est l’étape concrète qui permet d’injecter le comportement décrit par
des aspects dans un programme orienté objet. Le tissage se fait de façon statique grâce au
compilateur d'AspectJ.
22
CHAPITRE 1 – LE PARADIGME ASPECT 23
L’approche de France et al. [FRGG04, RFLG04] est basée sur UML2.0, et elle a été
améliorée dans [RGF+06, RFG+05] en proposant des mécanismes de composition plus
aboutis, mais concernant essentiellement les diagrammes de classe. Les modèles d’aspects
(les préoccupations d’aspects modélisées) sont représentés en utilisant des “diagrammes
templates”. Plus précisément, ce sont des templates de diagrammes de classe et de
diagrammes de communications qui décrivent respectivement les parties structurelles et
comportementales des aspects. France et al. proposent également une brève description d’un
processus de conception de modélisation orientée-aspect.
Stein et al. [SHU] proposé une approche pour représenter des expressions de coupe à un
niveau de modélisation, appelée JPDD (pour join point designation diagrams en anglais).
L’idée intéressante de cette approche est d’offrir la possibilité d’utiliser le modèle le plus
adapté à l’expression de coupe souhaitée. Par exemple, pour exprimer la volonté de détecter
des séquences de messages, les diagrammes de séquences d’UML sont bien adaptés.. Des
caractères génériques et d’autres symboles sont utilisés pour augmenter l’expressivité de leurs
expressions de coupe.
Malheureusement, leur approche ne sert qu’à exprimer des expressions de coupe, mais pas
à détecter les points de jonction correspondants. Un travail important portant sur la faisabilité
de leurs JPDD et la proposition de mécanisme de détection correspondant, est nécessaire pour
que leur approche puisse être utilisée.
23
CHAPITRE 1 – LE PARADIGME ASPECT 24
C'est une approche de composition de modèles d'aspect qui utilise les techniques de
transformation de modèle. La procédure de composition est asymétrique, car elle fait la
distinction entre un modèle de base et un modèle d'aspect. MATA définit un modèle d'aspect
comme une combinaison de deux parties dépendantes : un patron et une spécification de
composition. Le patron est utilisé pour détecter un emplacement dans le modèle de base où les
spécifications de composition seront appliquées. Même si les modèles d'aspect et le modèle de
base utilisent la même syntaxe concrète, ils sont différents à cause de la présence des
variables de patron, et des annotations utilisées par la spécification de composition.
MATA définit trois types d'annotations représentés par les stéréotypes create, delete et
context. Le stéréotype create est utilisé pour annoter les éléments qui vont être ajoutés dans le
modèle de base, alors que les éléments marqués par le stéréotype delete vont être supprimés
du modèle de base. Le stéréotype context est utilisé pour éviter d'appliquer un stéréotype à
plusieurs éléments dans le cas où un élément est annoté par un de ces stéréotypes et contient
d'autres éléments. Le processus de composition avec MATA se fait en deux temps : d'abord
un motif décrit par le patron de l'aspect est recherché dans le modèle de base, puis on procède
à la modification de ce motif selon la spécification de composition.
La particularité de cette approche est que les règles de transformation de graphe sont
définies en utilisant la syntaxe concrète du langage de modélisation. Cette propriété distingue
cette approche des approches de transformations les plus connues, par le fait que ces
approches définissent la transformation au niveau du méta-modèle, en utilisant la syntaxe
abstraite du langage de modélisation.
24
CHAPITRE 1 – LE PARADIGME ASPECT 25
1.8 Conclusion
Pour mieux faire face à ces problèmes, une séparation des préoccupations est d'une
importance primordiale. Cette séparation a pour objectif d'encapsuler le comportement d'une
préoccupation transversale (Crosscutting concern) dans une unité appelée aspect tout en
restant indépendant des autres préoccupations fonctionnelles du système. Dans ce contexte, il
y a eu apparition des langages de programmation orientées aspect pour former le paradigme
de programmation orientée aspect POA (Aspect Oriented Programmation, AOP [KIL+97]).
Ce dernier était dédie, au début, à la phase d'implantation pour couvrir ensuite toutes les
phases du cycle de vie d'un logiciel.
25