République Algérienne Démocratique et populaire

publicité
République Algérienne Démocratique et populaire
Ministère de l’Enseignement Supérieur et de la Recherche
Scientifique
UNIVERSITE DES SCIENCES ET DE LA TECHNOLOGIE D’ORAN
MOHAMMED BOUDIAF
Faculté de Mathématique et Informatique
Département d’Informatique
Mémoire
Pour l’obtention du diplôme de magistère en Informatique
Thème
Orthogonalité de persistance dans les
applications orientées aspect
Présenté par : Bendida Aissam
Dirigé par : Prof. Chouarfia Abdallah
Devant la commission d’examen composée de :
Président
Mme H. Belbachir
Prof USTO-MB
Rapporteur
M.
A. Chouarfia
Prof USTO-MB
Examinateur
M.
B. Yagoubi
Prof Université d'Oran
Examinatrice
Mme M. Noureddine
MC-A USTO-MB
Examinatrice
Mme L. Zaoui
MC-A USTO-MB
Année universitaire 2014-2015
REMERCIEMENTS
Je présente mes sincères remerciements pour mon directeur de mémoire , Monsieur le
Professeur Chouarfia Abdallah pour son aide et ses conseils très avisés tout au long
de ma formation.
Je lui témoigne ma profonde gratitude et ma reconnaissance. Son expérience et ses
compétences ont facilité mon travail et m’ont profondément marqué.
Je tiens à remercier très sincèrement l’ensemble des membres du jury qui me font le
grand honneur d’avoir accepté de juger mon travail.
Je remercie madame Belbachir Hafida Professeur à université de science et
technologie d'Oran pour l’honneur qu’elle me fait en acceptant la présidence de ce
jury. Qu’elle trouve donc ici l’assurance de ma profonde gratitude.
Je tiens à exprimer toute ma reconnaissance à Monsieur Belabbas Yagoubi
Professeur à l’université d'Oran et madame Noureddine Myriam Maître de
conférence à l’université de science et technologie d'Oran, ainsi que madame Zaoui
Lynda Maitre de conférence à l’université de science et technologie d'Oran , pour
avoir accepté d’être examinateurs de ce travail et pour le temps qu’ils ont investi à
l’évaluer malgré leurs nombreuses obligations.
Aussi, je remercie tout particulièrement mes parents pour leur encouragement et leur
soutien.
A ma femme et mon fils.
A mes sœurs et mes frères.
A toute ma famille.
A tous mes amis (es).
Avec toute mon affection.
Résumé
La couche de persistance doit assurer l’optimisation des interactions avec la base de
données. A cet effet, plusieurs techniques peuvent être mises en œuvre pour réduire le
nombre et la complexité des accès au support de persistance. Le travail présenté dans
ce papier, s’intéresse à l’utilisation de mémoire cache pour éviter les requêtes
redondantes et l'utilisation optimale des ressources dans un réseau
Nous proposons un système de caching de requête qui permet de traiter le problème
d’invalidation du cache, en cas de modification d’une table, et donc à éviter que les
résultats des requêtes en relation avec cette table deviennent périmés. Nous montrons
qu’il est possible de tirer de la programmation orienté aspect en offrant des capacités
d’ajouter dynamiquement le code du cache à l’application afin d’éviter le goulot
d’étranglement créé par l’utilisation d’un cache. En plus la réutilisation le code de
cache dans des contextes applicatifs différents.
Mots clés : persistance, cache de requête, la programmation orient aspect, AspectJ.
Table des matières
Introduction générale ............................................................................................................... 7
Objectifs de mémoire ........................................................................................................... 8
Plan du mémoire ................................................................................................................... 8
Chapitre I : Etude de la persistance ..................................................................................... 10
1. La problématique de la persistance objet .................................................................... 10
2. Différentes approches pour la persistance objet ......................................................... 12
3. Principe de la persistance transparente ....................................................................... 13
4. Rôle et obligations de la couche de persistance ........................................................... 15
4.1 L’outil de projection du modèle objet ................................................................... 15
5. Fonctionnalités attendues dans un Framework de persistance ................................. 19
5.1 La couche de persistance facilement manipulable ................................................ 19
5.2 Mapping objet relationnel ....................................................................................... 20
5.3 Chargement du graphe objet .................................................................................. 20
5.4 Gestion de différentes bases de données ................................................................. 21
5.5 Concurrence .............................................................................................................. 21
5.6 Transactions .............................................................................................................. 22
5.7 Cache objet ................................................................................................................ 22
6. La gestion cycle de vie et accès aux objets.................................................................... 23
6.1 Cache objet transactionnel : .................................................................................... 23
7. L’externalisation de la Persistance des objets dans un aspect ................................... 24
7.1 Distribution et Persistance avec AOP (Distribution and Persistence in AOP) ... 24
7.2 La Persistance comme un Aspect (Persistence as an Aspect) .............................. 26
7.3 Java Aspect Components (JAC) ............................................................................ 27
8. Concepts et techniques de cache ................................................................................... 28
8.1 Notion de cache ......................................................................................................... 28
8.2 La politique de remplacement ................................................................................ 29
8.3 Anomalie de Belady .................................................................................................. 30
8.4 Les travaux de gestion de cache de donnée ........................................................... 30
9. Conclusion ....................................................................................................................... 31
Chapitre II: Présentation de la Programmation orientée aspect ...................................... 32
1. Introduction .................................................................................................................... 32
2. Problèmes résolus par la programmation orientée aspect ......................................... 33
2.1. Fonctionnalités transversales ................................................................................. 33
2.2. Dispersion du code .................................................................................................. 34
3. Découverte du monde des Aspects ................................................................................ 35
3.1. Historique ................................................................................................................. 35
3.2. Principe de POA ...................................................................................................... 35
3.3. Quelques concepts de la programmation orientée aspect .................................... 36
4. Aperçus sur le langage AspectJ ..................................................................................... 40
4.1 Aspects dans AspectJ ............................................................................................... 40
4.2 Points de jonction dans AspectJ .............................................................................. 40
4.3 Coupes dans AspectJ ................................................................................................ 43
4.4 Codes Advices ........................................................................................................... 44
4.5 Introspection de point de jonction .......................................................................... 45
4.6 Mécanisme d’introduction ....................................................................................... 45
4.7 Héritage dans la POA .............................................................................................. 46
7. Conclusion ....................................................................................................................... 46
Chapitre III: approche proposée .......................................................................................... 47
1 .Introduction .................................................................................................................... 47
2. Le cache sémantique ...................................................................................................... 48
3. Stratégie de mise en cache ............................................................................................ 49
4. Intérêt de mettre la fonction de mise en cache comme aspect................................. 53
4 .Conclusion ....................................................................................................................... 55
Chapitre IV: Etude de cas ..................................................................................................... 56
1. Introduction .................................................................................................................... 56
2. coupes relatives à la persistance .................................................................................... 57
3. Résultats du test .............................................................................................................. 60
4. Conclusion et perspectives ............................................................................................. 61
Référence bibliographique ................................................................................................ 63
Table des Figures
I .1 Approche hybride de représentation d’objets : gestionnaire d’objets……...
16
I .2 Différentes approches de représentation de l’héritage………………………
18
I .3 Les classes de Player et Address avec la convention de nommage DPA…...
25
I .4 Illustre comment faire rendre les classes PLAYER et ADDRESS des classe
Persistante ……………………………………………………………………….
26
I .5 la persistance des objets Players dans JAC…………………………………
27
I .6 Fonctionnement d’un cache…………………………………………………
29
II .1 Dispersion du code d’une fonctionnalité…………………………………..
34
II .2 Localisation du code d’une fonctionnalité transversale dans un aspect….
36
II .3 Identification des aspects d’une application………………………………
37
II .4 Tissage des aspects…………………………………………………………
39
III.1 Fonctionnement d’un cache sémantique…………………………………..
49
III.2 Le cache avant la modification de la Table T1…........................................
50
III.3 Utilisation d’une table temporaire séparé pour les nouvelles insertions et
réutiliser la réponse de la requête précédente (A) avec la réponse(B).......................
51
III.4 Processus de mise en cache les requête…………………………………..
52
III.5 Le Patron de conception DAO…………………………………………….
55
IV.1 Dispersion du code de mise en cache……………………………………..
60
IV.2 Impact d’un aspect sur la location d’une mise en cache...………………..
61
Page |7
Introduction générale
Introduction générale
Le génie logiciel est un ensemble de méthodes et outils permettant de maîtriser les
coûts et le temps de développement des applications logicielles. L'une des principales
idées du génie logiciel est de modulariser les applications [1]. Nous utilisons
actuellement toujours cette notion de modules à travers la programmation orientée objet
et la programmation par composants logiciels.
La programmation orientée objet a été largement utilisée dans les milieux
industriels. Elle a indéniablement fait avancer l'ingénierie des systèmes logiciels à
différents points de vue. Cependant, les nombreuses retombées d'expériences ont
révélé les limites sérieuses qu'elle éprouve dans le développement de systèmes
logiciels complexes. Ces limites sont, entre autres, dues à la difficulté de prise en
compte des préoccupations transverses (qui recoupent plusieurs parties d'un
système). Ces préoccupations sont souvent dupliquées (et dispersées) dans le code.
Ceci affecte la qualité des systèmes, en particulier au niveau de la modularité, et
rend difficile, entre autres, leur compréhension ainsi que leur maintenance et évolution.
L' évolution des systèmes industriels complexes actuels est souvent inéluctable
et présente des enjeux économiques et qualitatifs considérables. Une des solutions
envisagées consiste à utiliser la programmation orientée aspect. Ce nouveau
paradigme de programmation cherche, en effet, à améliorer la séparation (et l’
intégration) des préoccupations en « modularisant » les éléments transversaux des
systèmes sous forme d’ unités séparées appelées « aspects ». La migration d’un
système orienté objet vers un système orienté aspect passe d' abord par
l'identification et la localisation de ces préoccupations dans le code objet (aspect
mining) pour les représenter, par la suite, par des aspects (aspect refactoring).
Dans ce mémoire, nous nous intéressons à la préoccupation transversale ˝ la
persistance˝.
La couche de persistance doit prendre en charge l’instanciation (création, recherche)
des objets requis par l’application depuis le support de persistance. L’interface entre
l’application et le mécanisme de persistance doit être réalisée au niveau objet, et non au
niveau base de données ou requête SQL. La couche de persistance doit gérer les
Introduction générale
Page |8
connexions entre les sessions applicatives, la base de données et l’infrastructure du
serveur d’application, de manière transparente.
Ce mémoire se situe à l'intersection des trois domaines langages de programmation,
le génie logiciel et les bases de données pour réaliser un modèle de persistance en se
basant sur l’approche orientée aspect.
Objectifs de mémoire
L’instanciation, la recherche, et la mise à jour des objets ainsi que le transit de ces
objets entre application et support de persistance sont des opérations très coûteuses en
temps d’accès. L’un des objectifs de ce mémoire est de fournir un mécanisme
fondamental d’optimisation des performances par l’utilisation d’un cache objet, qui
permet de réduire les accès au support de persistance en conservant en mémoire les
objets les plus fréquemment accédés. Grâce à la POA, il est possible de rendre le cache
et les applications qui manipulent cet cache plus indépendante, pour cela nous allons
développer un aspect de mise en cache reposant sur Framework Cacheonix et Aspectj.
L’ensemble de ces objectifs nous amène à proposer une solution combinant la
persistance et l’approche POA de façon orthogonal.
Plan du mémoire
Dans ce mémoire, nous adopterons une organisation comportant quatre différents
chapitres. Les deux premiers présentent l’état de l’art sur les techniques de gestion et
d’optimisation de persistance, et les concepts de la programmation orientée aspect.
 Le premier chapitre de cette étude sera consacré à l’explication de la
problématique de la persistance objet, de l’intégration des modèles objet et
relationnel, et des différents mécanismes mis en œuvre au sein d’un moteur de
persistance objet, ainsi qu’à l’optimisation de persistance où on définira la notion
de cache, les concepts associés et les caractéristiques d’un cache liées au
déploiement afin de mieux comprendre la difficulté de proposer un service de
caches. Nous montrons à travers quelques travaux que l’optimisation de
persistance peut bénéficié des avantages de la programmation orientée aspect.
 Le deuxième chapitre sera consacré sommairement à la programmation orientée
aspect. Nous commençons cette étude par la présentation des problèmes résolus
par la programmation orientée aspect. Puis nous introduisons les concepts de la
programmation orientée aspect et du langage AspectJ.
 Le troisième chapitre nous présentons l’approche globale retenue pour la
persistance dans les applications orientées aspect.
Introduction générale
Page |9
 Le quatrième chapitre est une réalisation de l’approche proposée sur un cas
concret de gestion de budget d’état.
Enfin nous terminons par une conclusion et des perspectives sur des travaux futurs.
Chapitre I : Etude sur les techniques de gestion de persistance
P a g e | 10
Chapitre I
Chapitre I : Etude de la persistance
1. La problématique de la persistance objet
Le modèle objet offre des capacités de modélisation et d’abstraction avancées, mais il
est en revanche handicapé par une grave limitation : il se focalise exclusivement sur les
aspects dynamiques de l’exécution des programmes, sans couvrir réellement la
problématique de la persistance des objets [20]:
Dans une application, les objets représentent des entités, des informations qui peuvent
être partagées par plusieurs applications, et qui peuvent avoir une durée de vie très
longue, dépassant la durée d’une session applicative. Cependant, les objets n’existent
qu’en mémoire ; par conséquent, une fois la session applicative terminée, les objets sont
détruits, et les informations qu’ils contiennent disparaissent avec eux.
La persistance objet est ainsi le fait d'exister dans le temps. Un objet qui reste en l'état
quand il est sauvegardé puis chargé par une autre application, ou à un moment éloigné,
possède la propriété de persistance. En conséquence, l'objet n'est plus dépendant de
l'application qui l'a créé et sa durée de vie est donc totalement indépendante du cycle de
vie des sessions applicatives qui le manipulent.
Dans le modèle relationnel, les données sont persistantes : une fois le schéma
relationnel défini, les données ajoutées restent accessibles durablement. La durée de vie
des données est donc totalement indépendante du cycle de vie des sessions applicatives
qui les manipulent.
Chapitre I : Etude sur les techniques de gestion de persistance
P a g e | 11
La problématique de la persistance objet consiste donc à élaborer et à mettre en œuvre
les mécanismes permettant de sauvegarder de façon fiable et durable l’état des objets
manipulés par une application.
La persistance consiste à sauvegarder l’état d’un objet (les différentes valeurs de ses
attributs) sur un support de stockage permanant pour être en mesure de le reconstituer
ultérieurement. Cependant, plusieurs considérations viennent compliquer la simplicité
apparente de cette tâche :
 Le type de objet : chaque objet appartient à une classe donnée ; il est donc
nécessaire de sauvegarder les informations relatives à l’appartenance de l’objet à
une classe particulière.
 Des références vers d’autres objets : au-delà des types scalaires simples, les
objets peuvent avoir comme attributs des références vers d’autres objets.
Sauvegarder un objet implique la sauvegarde de tous les objets référencés par cet
objet.
 L’identité objet : un identificateur d’objet, ou OID (Object IDentifier), est un
moyen de désigner de façon unique un objet dans le système. Il assure à un objet
une existence indépendante de sa valeur. L’OID peut être physique ou logique.
Dans le premier cas, il contient l’adresse physique de l’objet qu’il désigne, dans le
deuxième cas, il est nécessaire de le décoder pour déterminer cette adresse.
Techniquement, il existe plusieurs approches pour implémenter la persistance objet:
 Sérialisation : La sérialisation d'objets prend l'état de l'objet et le convertit en
un flux d'octets. Ce flux d'octets pourra être sauvegardé sur disque ou encore
être envoyé sur le réseau. On peut définir et utiliser des flux binaires (fichiers
binaires), ou textuels (fichiers XML par exemple).
 Mapping objet/relationnel : est la persistance des objets d'une application
orientée objets dans des tables d'une base de données relationnelle. Pour ce
faire, un fichier qui décrit le mapping entre les objets et la base de données est
employé. Ce fichier est en général écrit en XML (Extensible Markup
Language). ORM (object/relational mapping) transforme donc des données
d'une représentation dans une autre.
 Persistance en base de données objet : Les systèmes de gestion de base de
données objet (SGBDO) permettent de stocker dans les bases de données objet
les valeurs des attributs, les relations d'héritage entre les objets, les références
d'un objet sur un autre objet. Certains SGBDO permettent également
d'exécuter les méthodes des objets dans le cadre des manipulations du contenu
de la base de données. Contrairement aux bases de données relationnelles qui
emploient des structures bi-dimensionnelles (les tables), les bases de données
objet utilisent les mêmes représentations que les objets : des structures
hiérarchiques (graphes).
Chapitre I : Etude sur les techniques de gestion de persistance
P a g e | 12
Au-delà du mécanisme de persistance utilisé, il est également nécessaire
d’implémenter la logique de persistance qui va permettre aux applications d’effectuer la
sauvegarde et la restauration de l’état des objets manipulés. C’est le rôle de la couche de
persistance (ou moteur de persistance). Le moteur de persistance expose une API aux
applications pour la création, la mise à jour, et la recherche d’objets sur le support de
persistance. A ce moteur de persistance, il est également nécessaire d’associer un outil
de projection des objets sur le support de persistance : le rôle de cet outil est de fournir le
moyen de définir.
2. Différentes approches pour la persistance objet
Les systèmes de gestion de bases de données (SGBD) [29] relationnels ont pris une
place importante sur le marché des SGBD. Ils répondent de façon satisfaisante aux
besoins des applications classiques de gestion (administration, comptabilité, banques,
etc.). Des domaines d’application moins classiques sont apparus, comme la CAO
(Conception Assistée par Ordinateur), la bureautique, le génie logiciel, les applications
géographiques, etc. Ces applications gèrent des données beaucoup plus complexes, qu’il
est difficile de représenter avec le modèle relationnel.
Les limites du modèle sont d’une part un manque de capacité de représentation
structurelle, et d’autre part l’impossibilité de représenter pleinement la sémantique des
entités de la base. La seule structure de données disponible dans le modèle relationnel est
le tableau à deux dimensions (qui matérialise une relation n-aire entre plusieurs
domaines de valeurs). Ces structures plates ne permettent pas de représenter directement
des objets complexes comprenant plusieurs niveaux d’imbrication. Il faut alors
décomposer ces objets en plusieurs relations. Cette décomposition est visible à
l’utilisateur qui doit formuler des requêtes permettant de reconstituer de tels objets
(jointures). D’autre part les données stockées sont purement descriptives ; l’essentiel de
la sémantique associée à ces données se trouve dans les programmes de manipulation.
Seules les contraintes d’intégrité permettent de représenter une certaine sémantique
associée aux données. Ces lacunes sont justement comblées par certaines approches de
l’orientation objet.
Les recherches menées dans le domaine des bases de données se sont donc inspirées
de l’approche objet. En réalité, plusieurs approches sont envisageables pour mettre en
œuvre une solution de persistance d’entités métier [18] :
 Purement relationnel : L'application entière est programmée autour du modèle
relationnel et toutes les opérations sont relationnelles et basées sur SQL. Cette
solution peut être très intéressante pour des petites applications comportant peu de
code destinées à être réutilisables. Cependant pour les applications d'une certaine
importance cette solution n'est pas optimale. La raison en est qu'il devient très
compliqué d'étendre l'application car comme le tout est vu sous formes de tables
Chapitre I : Etude sur les techniques de gestion de persistance
P a g e | 13
et relations entre elles, l'ajout de nouvelles tables signifie également un ajout de
nouvelles relations entre elles qui sont souvent difficiles à gérer. De plus il faut
par la suite adapter tout le code SQL.
 Correspondance objet légère (Light Object Mapping) : Les entités sont
représentées comme des classes qui sont mappées manuellement vers les tables du
modèle relationnel. Le code SQL/JDBC est masqué grâce à l'emploi de design
patterns. Cette approche est très répandue et est bonne pour des applications avec
un petit nombre d'entités.
 Correspondance objet moyenne (Medium Object Mapping) : L'application,
contrairement au modèle purement relationnel, est modelée autour d'un modèle
orienté objets. SQL est généré à un outil de génération de code. L'association
entre les objets est supportée par le mécanisme de persistance et les requêtes
peuvent être réalisées grâce à un langage d'expression orienté objet comme par
exemple HQL (Hibernate Query Language). Ce dernier n'est toutefois pas un
langage de manipulation de données comme SQL. Il est utilisé uniquement pour
la récupération d'objets et non pour effectuer des opérations d'insertion, de mise à
jour ou de suppression. Le Medium object mapping convient bien aux
applications de moyenne taille contenant quelques transactions complexes.
 Correspondance objet complète (Full Object Mapping) : Ce procédé supporte
des procédés complexes propres au monde orienté objet : héritage, composition,
polymorphisme. La couche persistance implémente de la persistance transparente;
les classes persistantes n'héritent d'aucune classe de base et ne doivent pas
implémenter d'interface spéciale.
3. Principe de la persistance transparente
Un problème difficile de l’utilisation des SGBD relationnels dans le contexte d’un
programme objet est la nécessité d’effectuer la conversion entre les types de données du
langage objet et les types de données du SGBD. Dans le cas d’un SGBD relationnel, il
faut traduire les objets sous forme de lignes dans des tables. Il faut en même temps gérer
l’identification des objets par des clés primaires qui servent aussi à réaliser les
associations.
Un objectif visé par les bases de données objet est la possibilité de supporter la
persistance des objets de manière directe et transparente sans avoir à effectuer de
conversion entre les types du programme et les types du SGBD.
Chapitre I : Etude sur les techniques de gestion de persistance
P a g e | 14
En particulier l’écriture de code source d’une classe persistante doit s’effectuer sans
préoccupations de mécanismes sous-jacents liés à la persistance de son état. Les bases
d’une solution de persistance orthogonale ont été établies de manière théorique :
Persistance orthogonale : est le découplage total entre l’application et
l’infrastructure de persistance. En d’autres termes, garantir le découplage entre
applications, moteur de persistance, et base de données.
Le principe de persistance orthogonale est apparu à la fin des années 1970, dans le
domaine des langages de programmation. Il proclame que toute donnée doit être
habilitée à persister pendant un délai aussi long qu’il est utile, et que la méthode d’accès
à une donnée doit être indépendante de la nature de sa persistance. Permet de masquer au
développeur les mécanismes de transformation entre l’objet en mémoire et sa
représentation sur le support de stockage.
Afin de démontrer ce caractère de persistance orthogonale, une application doit
posséder les caractéristiques suivantes définies par M. Atkinson [2], [4], [5] :
Règle 1: l'indépendance de la persistance
Le statut de persistance pour un objet doit être indépendant des programmes qui les
manipulent: un objet persistant ne l'est pas pour des programmes particulier.
Réciproquement, le code des programmes manipulant des objets persistants doit
pouvoir être indépendant de leur statut persistant ou volatile.
L'intérêt de cette règle se situe essentiellement dans le domaine de la réutilisation des
composants. Il est important de ne pas être obligé de considérer, au moment de l'écriture
d'un composant, le statut des objets manipulés (persistant ou volatile).
Règle 2: l'orthogonalité des types de données persistants
En accord avec le principe général de conception des langages de programmation sur la
complétude des types de données, tous les objets, quelque soit leur type, doivent pouvoir
être rendus persistants et manipulés comme tels sans limitations.
Quelque soit son type, un objet a le droit de devenir persistant; on ne veut pas, à cause
de la non possibilité de rendre certaines structures persistantes, influencer les choix de
conception d'un programme.
Chapitre I : Etude sur les techniques de gestion de persistance
P a g e | 15
Règle 3: l'orthogonalité de la gestion de la persistance
La manière d'introduire et de reconnaitre le statut persistant d'un objet est orthogonale au
système de type, au modèle d'exécution et aux structures de contrôle du langage.
Cette règle garantit l'intégrité des objets quelque soient leur statut: tous les objets
référencés par un objet persistant restent accessibles après la terminaison du processus,
c'est-à-dire sont eux-mêmes persistants. Réciproquement, un objet ne peut être effacé
que lorsqu'il n'y a plus aucun objet qui le référence.
A ces considérations théoriques sur le fondement de la persistance transparente, il faut
ajouter les exigences pratiques auxquelles doit satisfaire toute couche de persistance.
4. Rôle et obligations de la couche de persistance
La partie du code responsable de l’accès aux données dans une application multi
niveaux doit être encapsulée dans une couche dédiée aux interactions avec la base de
données de l’architecture généralement appelée couche de persistance. Celle-ci permet
notamment :
 D’ajouter un niveau d’abstraction entre la base de données et l’utilisation qui en
est faite.
 De simplifier la couche métier qui utilise les traitements de cette couche.
 De masquer les traitements réalisés pour mapper les objets dans la base de
données et vice et versa.
 De faciliter le remplacement de la base de données utilisée.
Le rôle principal du moteur de persistance est d’implémenter [20], de façon
transparente, la logique de persistance des objets des applications. En plus, il doit être
associé un outil de projection qui va permettre de définir les structures utilisées pour la
persistance des objets, ainsi que les règles de transformation entre la représentation des
objets en mémoire et leur représentation sur le support de persistance.
4.1 L’outil de projection du modèle objet
En tenant compte des divergences croissantes apparaissant entre les formalismes de
modélisation conceptuelle et logique, depuis les années 1990, plusieurs études ont été
menées en vue de concilier l’univers objet de l’approche relationnelle. Deux grandes
approches ont été proposées [23]:
1. La connexion des applications objets directement aux bases données relationnelles
en codant dans les méthodes de classes ("getters", "setters", constructeurs,
Chapitre I : Etude sur les techniques de gestion de persistance
P a g e | 16
destructeurs, etc.) l’accès aux données. Cet accès se fait généralement par du
"Embedded SQL" repartit dans tout le code des applications.
2. La définition d’un gestionnaire d’objets (ou Object Layers) entre les applications
objets et les bases de données relationnelles (figure I .1). Le gestionnaire d’objets
(1) reçoit les requêtes (OQL par exemple) venant des applications objets, (2) les
traduit en SQL et les envoie au SGBDR pour exécution ; (3) récupère les résultats
et enfin (4) les traduit de nouveau dans le format adapté (OQL par exemple) pour
les applications objets.
Les deux approches précédentes partagent le fait que les objets des classes de
l’application sont stockés dans des bases de données de type relationnel (ou relationnelobjet). Ces approches nécessitent donc de définir des correspondances entre les concepts
objets et les concepts relationnels, puis de gérer de façon la plus simple possible les
transformations associées à ces correspondances.
APPLICATION
(1) requêtes
(7) données objets
(OQL)
(OQL)
2)
Traduction
GESTIONNAIRE D’OBJETS
Requêtes en
SQL(3) Envoie de la
requête au
SGBDR/O
(5) récupération
de données
(6)
Traduction
des données
en objets
(OQL)
SGBDR/O
(4) exécution de la
requête SQL
Figure I .1 – Approche hybride de représentation d’objets : gestionnaire d’objets
Parmi les principaux concepts objets qui exigent des règles de transformations
particulières pour être représentés en relationnel, les relations d’héritage, d’associations
et d’agrégations.
4.1.1 Représentation de la relation d’héritage
Les propositions de représentation de la relation d’héritage peuvent être classées en
trois catégories [23] :
Chapitre I : Etude sur les techniques de gestion de persistance
1.
2.
3.
P a g e | 17
Représentation "à plat",
Représentation horizontale,
Représentation verticale.
 Représentation "à plat" : une table par arborescence
Représenter toutes les classes d’une arborescence d’héritage par une seule table
relationnelle. C'est la solution la plus simple à mettre en place. Pour consulter les
différents objets d'un même type, aucune jointure n'est nécessaire, ils sont situés à
chaque ligne d'une même table. La table peut être très dense car elle regroupe plusieurs
types d’objets. Deux autres attributs sont ajoutés. Le premier représente l’identifiant, ou
clé primaire de la table. Le second est généralement un code spécifiant le type effectif de
l’objet instancié ((1a) dans la figure I .2). Une variante de cette approche consiste à
remplacer ce second attribut par plusieurs attributs de type booléen ((1b) dans la figure
I .2) ; chacun d’eux correspondants à un des types possibles.
Cette approche est simple et supporte le polymorphisme car tous les objets
polymorphes appartiennent à la même table. Ils peuvent donc être référencés par une
même clé étrangère.
L’accès aux instances d’un niveau quelconque de la hiérarchie demande seulement la
projection d’une sélection car toutes les instances sont rangées dans une seule table.
C’est la seule méthode qui sera économe en jointure. L’inconvénient, par contre, se
situe au niveau de l’espace de stockage car les tables peuvent être très grandes et
contenir de nombreuses valeurs nulles. Ceci est en particulier le cas lorsque des motifs
de classes abstraites sont utilisés pour représenter des mécanismes génériques, tels, par
exemple, le motif Modèle-Vue-Controleur (MVC) [19]. La mise à plat impose alors de
regrouper un très grand nombre de classes disparates, qui n’ont pas d’autres points
communs que d’utiliser le même mécanisme.
 Représentation horizontale : une table par classe concrète
Dans cette approche ((2) dans la figure I .2), une table est créée pour chaque classe
concrète. Tous les attributs de la classe concrète et ceux hérités des super-classes de cette
dernière constituent les colonnes de la table. A ces colonnes, s’ajoute une clé primaire.
Lorsqu’il n’y a qu’un seul niveau de classes concrètes, l’avantage de cette approche est
qu’il est facile d’obtenir et de stocker les informations sur les objets existants car toutes
les informations sur un objet se retrouvent dans une seule table.
Les inconvénients principaux de cette représentation sont (1) qu’une requête générique
sur une classe abstraite nécessite des unions de projections des tables des sous-classes et
Chapitre I : Etude sur les techniques de gestion de persistance
P a g e | 18
(2) que le polymorphisme n’est pas supporté de façon aisée car un lien vers une classe
abstraite se matérialise par une référence vers des tables différentes selon les instances.
 Représentation verticale : une table par classe
Dans cette approche ((3) dans la figure I .2), on crée une table pour chaque classe.
Chaque table a pour colonnes les attributs définis au niveau de la classe qu’elle
représente. Un même identifiant est utilisé comme clé primaire pour toutes les tables. Au
niveau des sous-classes, il représente à la fois une clé primaire et une clé étrangère.
L’avantage de cette approche est qu’elle représente de façon très adéquate les
concepts orientés objets. Le polymorphisme peut se représenter assez aisément par une
clé étrangère unique (avec jointure automatique avec les super-classes) parce que nous
avons un enregistrement dans la table correspondant à chaque classe auquel un objet
appartient.
Il est facile également de modifier les super-classes et d’ajouter de nouvelles sousclasses car cela correspond respectivement à la modification et à l’ajout d’une table.
Outre le nombre important de tables dans la base de données (une pour chaque classe), le
principal inconvénient de cette approche est que les informations sur un objet d’une
classe se retrouvent reparties entre grand nombre de tables. Ainsi, tout accès à un objet
nécessite de faire de nombreuses jointures, ce qui peut devenir très coûteux.
Figure I .2 – Différentes approches de représentation de l’héritage
Chapitre I : Etude sur les techniques de gestion de persistance
P a g e | 19
Pour ce qui concerne les associations, agrégations et compositions, on trouve
également dans la littérature, plusieurs propositions de représentation [40], [34], [35],
[36], [37]. Ces propositions sont définies en fonction des cardinalités des relations (1 : 1,
1 : n, n : m) et des propriétés des relations d’agrégations (dépendance, partage,
exclusivité, prédominance). [38] énumère toutes les solutions envisageables pour la
représentation de ces relations en relationnel. Ces différentes solutions se résument soit à
la création de tables intermédiaires entre les tables des classes participantes à la relation,
soit à la déclaration de clés étrangères sur des colonnes de tables. Ces différentes
propositions ne s’appliquent que lorsque le choix de représentation de l’héritage est
vertical ou à plat. Lorsque seules les classes concrètes sont représentées, il est nécessaire
de représenter tout lien par un aiguillage comportant en particulier une colonne qui
indique le type effectif de l’instance référencée.
- La possibilité de répartir les attributs d’un objet dans plusieurs tables
(mapping multi-table).
- La possibilité d’utiliser des champs binaires (BLOB) pour sauvegarder l’état
d’objets dépendants.
- Des mécanismes de conversion de types entre types objet et types de bases de
données.
4.1.2 La gestion de l’identité objet :
Dans le modèle objet, l’unicité des objets est uniquement fonction de l’unicité des
pointeurs, tandis que dans le modèle relationnel, l’unicité des tuples est garantie par
l’utilisateur de clés primaires.
La notion d’unicité est commune aux mondes objet et relationnel. Dans le monde
relationnel, elle se retrouve dans deux contraintes d’intégrité. Pour rappel, une contrainte
d’intégrité vise à garantir la cohérence des données.
Pour assurer l’unicité d’un enregistrement dans une table, ou tuple, la première
contrainte qui vient à l’esprit est la clé primaire. Une clé primaire (primary key) est un
ensemble de colonnes dont la combinaison forme une valeur unique. La contrainte
d’unicité (unicity constraint) possède exactement la même signification.
5. Fonctionnalités attendues dans un Framework de persistance
5.1 La couche de persistance facilement manipulable
Il faut avant tout que la couche d’accès soit très facilement manipulable, et que le
programmeur puisse exploiter un système de données de façon très intuitive.
Chapitre I : Etude sur les techniques de gestion de persistance
P a g e | 20
Concrètement, il faut que des méthodes CRUD soient implémentées, si possibles des
patterns Factory permettant de charger des objets de différentes manières. Il faut aussi
que chaque attribut ou relation du modèle de classe soit interprété en tant qu’accesseurs
sur les champs et les entités correspondants, chargeant de manière transparente les
entités en question.
5.2 Mapping objet relationnel
Une couche Mapping Objet Relationnel(ORM) est une interface logicielle qui permet
de représenter et de manipuler sous forme d’objet tous les éléments qui composent une
base de données relationnelle.
Ainsi, une table ou bien un enregistrement de celle-ci est perçu comme un objet du
langage sur lequel il est possible d’appliquer des actions (les méthodes). L’avantage de
cette approche est de s’abstraire complètement de la technologie de gestion de la base de
données qui fonctionne en arrière plan, et de ne travailler qu’avec des objets ayant des
liaisons entre eux.
Il doit être possible de modéliser une couche de données avec un modèle entièrement
objet, gérant les concepts d’héritage, de relations complexes, et autres. De manière
générale, on pourra par exemple utiliser un éditeur UML du marché, ou créer un fichier
XML représentant ce modèle.
Cette méthodologie permet une plus grande souplesse de modification du modèle et
de la base de données, les modifications du modèle étant répercutées automatiquement
sur la base de données de façon transparente pour le programmeur
5.3 Chargement du graphe objet
L’accès aux données et donc la récupération des objets est une partie sensible de
l’application, sur laquelle l’optimisation peut jouer un grand rôle.
Java Persistance fournit une solution complète pour maîtriser l’accès aux données, et ce
selon les trois axes principaux suivants :
 Le chargement à la demande, ou lazy loading. pour éviter le chargement
d’instances inutiles ;
 Chargement des instances associées à l’exécution afin de permettre le chargement
d’un réseau d’objets plus large que celui défini par défaut et de limiter ainsi le
nombre de requêtes générées ;
 Optimisation du SQL généré, afin de tirer parti d’un certain nombre de
spécificités du dialecte de la base de données cible.
On appelle « Lazy Loading » la technique qui consiste à ne charger que les éléments
correspondants à la demande spécifique du programmeur. A l’inverse, on parlera d’ «
Chapitre I : Etude sur les techniques de gestion de persistance
P a g e | 21
aggressive loading » si la couche d’accès aux données charge aussi tous les
enregistrements qui ont une relation avec celui demandé, provenant de tables différentes.
On comprendra facilement que le lazy loading permet d’optimiser le code, et ne
surcharge pas le serveur de bases de données inutilement. Mais il faut bien comprendre
qu’il peut arriver que cette technique crée par moment plus de requêtes au serveur que
nécessaire. Elle reste tout de même la technique la plus utilisée, car en général plus
rapide, et moins gourmande en ressources que l’aggressive loading.
5.4 Gestion de différentes bases de données
L’abstraction vis-à-vis de la base de données est très importante pour le programmeur.
Mais l’abstraction vis-à-vis du serveur de bases de données est peut être encore plus
importante.
En théorie, une couche d’accès aux données peut être construite pour être
indépendante du serveur de bases de données. En pratique il existe deux méthodologies
possibles : utiliser un langage de communication standard (SQL), ou exploiter une API
telle qu’ADO.Net et les différents fournisseurs de données. On instancie alors les
fournisseurs adéquats au moment voulu, en utilisant par exemple le pattern abstract
factory.
5.5 Concurrence
La stratégie de concurrence d’accès influence directement les performances et les
capacités pour une application client serveur, à partir de laquelle plusieurs utilisateurs
peuvent modifier les mêmes objets simultanément.
Dans les systèmes objets il y a généralement deux approches pour aborder le problème
de la concurrence d’accès :


l’approche pessimiste.
l’approche optimiste.
Dans l’approche pessimiste les objets sont systématiquement verrouillés lorsqu’ils
entrent dans une transaction. Les verrous sont gérés de manière à garantir qu’à un instant
« t » un seul utilisateur puisse modifier un objet donné. Cette méthode radicale a le
désavantage d'être coûteuse en termes de performances, car elle verrouille l’accès à
l’objet tant qu’il n’a pas été complètement libéré, même si aucune modification n’est
effective.
Dans l’approche optimiste les objets ne sont pas verrouillés lorsqu’ils entrent dans
une transaction. Lors de la mise à jour la couche d’accès vérifiera qu’ils n’ont pas été
modifiés par un autre utilisateur entre le moment où ils ont été lus et le moment où ils
sont mis à jour. Au cas où un objet a été modifié l’ensemble de la transaction est
annulée.
Chapitre I : Etude sur les techniques de gestion de persistance
P a g e | 22
La méthode optimiste ne modifie pas le niveau de concurrence d’accès que peut
supporter une application, simplement en général elle est plus efficace car elle
économise le coût de la gestion des verrous.
Une bonne couche d’accès aux données doit rendre ce fonctionnement transparent
pour le programmeur, et lever automatiquement une exception typée lui permettant
d’effectuer les traitements adéquats.
5.6 Transactions
Une transaction permet de ne valider un ensemble de traitements sur le base de
données que si ils se sont tous effectués correctement, la couche d’accès doit
implémenter des services permettant de définir le début et la fin d’une transaction, et
proposer un mécanisme d’interception des erreurs pour annuler cette dernière.
5.7 Cache objet
Lorsque l’on cherche l’utilité d’un cache objet, on pense tout d’abord à la notion de
performance. Dans le cas d’une couche d’accès aux données, cette partie est surtout
nécessaire pour conserver la cohérence des instances générées.
Les caches peuvent ainsi différer en plusieurs aspects, telles que les informations
manipulées, ou encore les politiques de remplacement ou de résolution employées.
L’amélioration des performances étant fortement liée à la configuration du cache en
fonction de l’environnement d’exécution, les caches sont très souvent construits de bout
en bout, rendant le développement coûteux (en temps et en argent).
Le cache a une taille maximale qu’il ne peut pas dépasser. Cette taille est gérée par le
Framework de persistance, plus le cache est grand, plus le SGBD sera rapide. Si le cache
est plein, il garde en mémoire les objets récemment utilisés et supprime les autres de
remplacement. Le cache stocke les dernières données récupérées de la base. Par
exemple, si on fait une requête qui ramène la liste de tous les objets d’un certain type, le
temps d’exécution sera différente que si l’on exécute la requête pour la première fois.
A la première exécution, le cache ne contient pas le résultat de la requête donc cette
dernière va jusqu’au serveur, interroge la base puis le résultat est retourné au client et est
mémorisé dans le cache. A la deuxième exécution, la base de données n’est pas
interrogée étant donné que le cache possède déjà la réponse. Le résultat est ainsi
récupéré beaucoup plus rapidement sans avoir besoin d’interroger la base. Le
rapatriement d'objets dans le cache se fait par pages, ce qui signifie que les objets
demandés ainsi que les objets présents sur les mêmes pages sont remontés dans le cache.
On peut donc trouver dans le cache des objets auxquels on n'a jamais accédés mais qui le
seront peut-être, d'où le gain de performance.
Chapitre I : Etude sur les techniques de gestion de persistance
P a g e | 23
Un Framework de persistance a beau implémenter un cache [31], il faut surtout
voir ce dont il se charge, car entre une simple pile d’objets et un cache qui distingue les
accès en lecture/écriture, qui automatise le recyclage des instances à l’aide d’un ramasse
miette (garbage collector) et qui gère les accès concurrentiels, la différence peut vite être
énorme.
6. La gestion cycle de vie et accès aux objets
La couche persistance nommée aussi couche d’accès aux données. Elle prend en
charge l'accès à la source de données (SGBDR, fichiers XML, LDAP, …). La couche
Persistance offre les fonctionnalités de base qui permettent de créer, rechercher, modifier
et supprimer des composants objets métiers dans le respect des propriétés
transactionnelles classiques. D’utiliser le mécanisme de projection objet vers relationnel
(mapping Objet / Relationnel) qui consiste en la transformation de la représentation des
données en une représentation objet. Elle est structurée en routines ou méthodes qui
contiennent les accès aux tables des bases de données et réalisent les fonctions
élémentaires de gestion : création, modification, lecture.
La couche de persistance doit prendre en charge l’instanciation (création, recherche)
des objets requis par l’application depuis le support de persistance.
L’instanciation, la recherche, et la mise à jour des objets, ainsi que le transit de ces
objets entre application et support de persistance, sont des opérations très coûteuses en
temps d’accès. Le mécanisme fondamental d’optimisation des performances est
l’utilisation d’un cache objet, qui va permettre de réduire les accès au support de
persistance en conservant en mémoire les objets les plus fréquemment accédés et donc
d’accroître les performances du système.
6.1 Cache objet transactionnel :
L’utilisation d’un cache a toujours été importante dans les systèmes informatiques,
afin de fournir une haute qualité de service et notamment une amélioration des temps de
réponse perçus par les utilisateurs. En effet, un cache fournit un accès rapide aux
données et permet de conserver en mémoire une partie des objets stockés sur le support
de persistance. Lorsque l’application demande le chargement d’un objet, cet objet est
chargé depuis le support de persistance, et stocké dans la mémoire cache. Si l’application
accède ultérieurement à cet objet, la couche de persistance peut utiliser la copie de
l’objet en cache pour satisfaire la demande de l’application, ce qui évite un accès à la
base de données. Au fur et à mesure de l’exécution, les objets chargés par l’application
remplissent le cache. De plus, employer un cache réduit la charge sur les serveurs et
éventuellement sur les liens de communication, la récupération des éléments étant alors
plus rapide.
Chapitre I : Etude sur les techniques de gestion de persistance
P a g e | 24
La politique de remplacement est utilisée pour déterminer les entrées du cache à
remplacer, appelées victimes. Il n’existe pas de politique de remplacement meilleure que
les autres pour toutes les séquences d’accès. C’est pourquoi, de nombreuses solutions
sont proposées dans la littérature. Le choix d’une politique est fortement lié à
l’application et aux objectifs fixés par le développeur de la solution de cache. Les
politiques de remplacement peuvent, en particulier, s’appuyer sur le principe de localité
pour le choix des éléments à supprimer, notamment sur la localité spatiale ou la localité
temporelle.
A travers la couche de persistance, l’accès aux objets doit être réalisé de façon
transactionnelle, afin de permettre la concurrence d’accès aux objets et d’assurer les
propriétés transactionnelles de base lors des opérations de mise à jour: atomicité,
cohérence, isolation, et durabilité. Par conséquent, le cache objet doit lui-même être
transactionnel, et assurer la gestion des accès concurrents aux objets à travers
l’utilisation de stratégies de verrouillage paramétrables [20].
7. L’externalisation de la Persistance des objets dans un aspect
Dans la littérature de la programmation orientée aspect, la persistance a été identifiée
comme un aspect [25] [26]. Le problème de la persistance est de savoir où ajouter son
code. La motivation pour les systèmes d’aspects conçus pour fournir une meilleure
séparation des préoccupations de persistance sont basées sur les caractéristiques
suivantes de ces systèmes. Tout d'abord, point de jonction, il s’agit d’un point dans
l’exécution d’un programme autour duquel l’aspect de persistance peut être ajouté.
Ensuite, le code advice définissant le comportement d’un aspect et chaque advice est
associé à une coupe, le coupe fournit l’ensemble des points de jonction autour desquels
sera greffé le bloc de code advice. Enfin, le mécanisme de tissage ajoute le
comportement aspect de persistance définie dans code advice aux points de jonction
sélectionné.
Dans la suite, nous présentons trois exemples d’approches dans chacune pour résoudre
le problème de la persistance.
7.1 Distribution et Persistance avec AOP (Distribution and Persistence in AOP)
Soares et Laureano [09] mis en place une solution orientée aspect pour les deux
préoccupations, la persistance et la distribution. Ils distinguent l'aspect de distribution
sur le côté serveur et le celui du côté client suivant le patron de conception façade [10].
Chacun de ces aspects propose un service d'accès distant en utilisant le RMI (Java
Remote Method Invocation) [11].
Aspect de persistance fournir des fonctionnalités de base parmi lesquelles : la
connexion à la base de données, la gestion des transactions, la gestion cache et la
Chapitre I : Etude sur les techniques de gestion de persistance
P a g e | 25
synchronisation l'état de l'objet avec base de données. Les auteurs ont considéré le
problème de synchronisation de l'état objet comme une préoccupation transversale entre
la distribution et l’aspect de persistance, ils ont choisi de résoudre cette dépendance
comme une partie de l’aspect de persistance. Enfin, les auteurs soulignent certaines
faiblesses dans le langage AspectJ pour soutenir une bonne modularisation et suggérer
certaines propositions.
Dans [09], les auteurs ont émis un certain nombre de conventions de nommage qui
doit être suivi. Par exemple, les classes de la couche métier doivent avoir le suffixe
«Record», chaque type persistant déclaré doit implémenter l’interface PersistentObject
dans l'aspect persistance et les méthodes setter et getter aussi doivent commencer par
"set" et "get", respectivement. De plus, les développeurs doivent également déclarer que
les méthodes de la façade ont des paramètres sérialisables et les types de retour à
l'intérieur de l'aspect persistance côté serveur en étendant leurs types par
l'implémentation de l'interface Serializable. Pour utiliser ce Framework, les
développeurs doivent étendre deux aspects abstraits: le AbstractPersistenceControl et
AbstractTransactionControl.
public class Player {
String plyerID;
Address address;
// …
public void setPlayerID(String playerID) { … }
public Address getAdddres() { … }
// …
}
public class Address {
// …
public void setStreet(String street) { … }
public String getStreet() { … }
// …
}
Figure I .3 – Les classes de Player et Address avec la convention de nommage DPA
Pour des raisons de simplicité, cet exemple n'est pas concerné par la distribution et les
aspects de transaction, il considérait comme une simple partie d'une application qui peut
se conformer à la structure du système de plaintes de la santé. En particulier, il montre
comment les types simples de logique métier sont déclarés comme persistants.
Chapitre I : Etude sur les techniques de gestion de persistance
P a g e | 26
7.2 La Persistance comme un Aspect (Persistence as an Aspect)
Rashid et Chitchyan [12] ont proposé la première tentative d'un Framework de
persistance basé sur les concepts de la programmation orientée aspect (POA). Ce
Framework utilise une base de données relationnelle, il se compose de plusieurs aspects
qui offrent des différentes fonctionnalités de persistance. Ces fonctionnalités incluent
une connexion à la base de données, les opérations de persistance, mécanisme de
traduction SQL et les démarcations des transactions. Ce Framework est annoncé pour
soutenir la persistance par accessibilité.
Comme dans DPA, le Framework PAA s'appuie sur les annotations, les types
persistants devraient être déclarés à étendre la classe PersistentRoot.
PAA permet également l'utilisation des conventions de nommage des méthodes setter
et getter qui doivent être utilisées à l'intérieur du code de base chaque fois qu'on veuille
rendre un objet persistant.
public aspect ApplicationDatabaseAccess {
declare parents: (Player || Address) extends PersistentRoot;
pointcut traplnstantiations: call(PersistentRoot+.new(..));
pointcut trapupdates(PersistentRoot obj): … &&
this(obj) && execution(public void PersistentRoot+.set*(..);
// …
}
public aspect EstablishMapping dominates DatabaseAccess {
pointcut setupMapping():
ApplicationDatabaseAccess.establishconnection();
before(): secupMapping() {
LookupTable mappingTable = LookupTable.getLookupTable();
mappingTable.createClassToTableMapplng(“Player", “PLAYER");
mappingTable.createClassToTableMapping(“Address",“ADDRESS");
}
Figure I .4 – illustre comment faire rendre les classes PLAYER et ADDRESS des classe
persistante
Chapitre I : Etude sur les techniques de gestion de persistance
P a g e | 27
7.3 Java Aspect Components (JAC)
Composants Java Aspect (JAC) [13] est un Framework basé sur l’aspect qui est utilisé
pour construire des applications distribuées en java. Les objets distribués sont également
possible de se définir comme des objets persistants dans JAC. Les développeurs utilisent
deux niveaux du Framework JAC afin de définir la distribution et la persistance de leurs
objets POJO. Un programme orienté aspect avec JAC est un ensemble d'objets d'aspects
qui peuvent être dynamiquement déployés et retirés sur des objets applicatifs en cours
d'exécution.
Les objets d'aspects peuvent définir trois types de méthodes d'aspects: des méthodes
encapsulantes (qui encapsulent des méthodes applicatives et permettent d'exécuter du
code avant et après la méthode encapsulée), des méthodes de rôle (qui ajoutent de
nouvelles fonctionnalités aux objets applicatifs) et des gestionnaires d'exceptions.
Le problème de la composition d'aspects est traité à l'aide d'un contrôleur
d'encapsulation bien défini qui spécifie pour chaque objet encapsulé, au moment de
l'encapsulation, à l'exécution ou dans les deux cas, l'ordre d'exécution des objets
d'aspects.
Deux aspects de persistance sont disponibles avec JAC : PersistanceAC et
HibernateAC. PersistanceAC permet de sauvegarder des données soit dans des fichiers,
soit dans une base de données via JDBC. HibernateAC s’appuie sur le Framework de
persistance Hibernate pour réaliser cette sauvegarde.
// déclarer la classe Player comme une classe persistante
1. MakePersistent roster. Player;
// define the aspect
2. public class RosterAC extends AspectComponent {
3. public RosterAC() {
4.
pointcut(“.*", // all objects
5.
“Player", // classe Player
6
. “set*(*):void", // setter methods
7.
“ObjChanged", // the name of wrapper (advice)
8.
null, // no Exception handler
9.
false); // wrapper cardinality, here is singleton
10. }
11. class ObjChanged extends Wrapper { // advice code
12. public Object invoke(MethodInvocation mi) throws Throwable
13. { // …}
14. }
15.}
Figure I .5 – la persistance des objets Players dans JAC
Chapitre I : Etude sur les techniques de gestion de persistance
P a g e | 28
Dans la figure I .5, le fichier de configuration JAC précise que la classe Player
déclarer comme une classe persistante. Dans l’aspect RosterAC, la méthode Pointcut
(ligne 4) spécifie que la méthode sélectionne toutes les invocations de méthodes (ligne
12) qui commencent par Set (ligne 6) de n'importe quel objet (ligne 4) du type Player
(ligne 5).
8. Concepts et techniques de cache
8.1 Notion de cache [24]
Cache et un Espace physique d’accès rapide, généralement de taille limitée, utilise
pour stocker des copies des éléments les plus susceptibles d’être référencés.
L’utilisation d’un cache a toujours été importante dans les systèmes informatiques,
afin de fournir une haute qualité de service et notamment une amélioration des temps de
réponse perçus par les utilisateurs. En effet, un cache fournit un accès rapide aux
données, pouvant tirer bénéfice de l’utilisation d’un support physique efficace, d’un
ensemble d’éléments gérés plus petit autorisant des recherches plus rapides, ou encore
d’un placement évitant des communications réseaux. De plus, employer un cache réduit
la charge sur les serveurs et éventuellement sur les liens de communication, la
récupération des éléments étant alors plus rapide.
Ainsi un cache améliore généralement les performances, en dépit des couts de
déploiement, d’administration, de gestion et éventuellement des problèmes de cohérence
qu’il peut engendrer.
Le fonctionnement classique d’un cache est illustré par la figure I.6 . A la suite
d’une demande d’un client (1), un cache vérifie la présence de l’élément dans son espace
de stockage. Si celui-ci est contenu en cache (succès de cache ou cache hit), il est fourni
directement au client (2). Dans le cas contraire (défaut de cache ou cache miss), il est
nécessaire de contacter le serveur (2’) afin de le récupérer (3’). Le cache renvoie
l’élément (4’) au client et le stocke pour une utilisation future. A noter qu’en général,
l’utilisation du cache est transparente, le client n’ayant pas conscience qu’il accède aux
données au travers d’un cache. Cependant, la transparence est parfois levée, permettant
notamment à un client de contacter directement le serveur s’il veut s’assurer d’obtenir la
dernière version d’un élément.
Chapitre I : Etude sur les techniques de gestion de persistance
(1)
P a g e | 29
(2’)
CLIENT
CACHE
SERVEUR
(4’)
(2)
(3’)
Figure I .6 – Fonctionnement d’un cache
Définition 2.2. Succès de cache
Un succès de cache (cache hit) se produit, lorsque l’élément demande est présent en
cache.
Définition 2.3. Défaut de cache
Un défaut de cache (cache miss) se produit, lorsque l’élément demandé n’est pas présent
en cache.
8.2 La politique de remplacement
La politique de remplacement qui a pour charge de déterminer les éléments à
supprimer lorsqu’il n’y a pas suffisamment d’espace libre pour stoker un nouvel
élément. Cette fonctionnalité peut être réalisée par un grand nombre d’algorithmes,
parmi lesquels nous retiendrons :
 L'algorithme optimal : La règle de remplacement est «remplacer la page qui ne
sera pas utilisée pendant la durée la plus longue». Malheureusement, cet
algorithme nécessiterait de connaître l'avenir.
 FIFO (First In First Out) : La page la plus ancienne est la victime (celle qui a été
placé en mémoire depuis le plus long temps). Cet algorithme est très simple à
implémenter.
 LRU (Least Recently Used) : Il consiste à choisir comme victime le cadre qui n'a
pas été référencé depuis le plus longtemps.
 LFU (Least frequently used) «la moins souvent utilisée» : on garde un compteur
qui est incrémenté à chaque fois que le cadre est référencé, et la victime sera le
cadre dont le compteur est le plus bas.
 ZIZE : le plus gros élément en cache est expulsé.
Le choix d’une politique est fortement lié à l’application et aux objectifs fixés par le
développeur de la solution de cache. Les politiques de remplacement peuvent, en
Chapitre I : Etude sur les techniques de gestion de persistance
P a g e | 30
particulier, s’appuyer sur le principe de localité pour le choix des éléments à supprimer,
notamment sur la localité spatiale ou la localité temporelle.
8.3 Anomalie de Belady
L’anomalie de Belady caractérise un cache dont l’augmentation de l’espace physique
ne produit pas une réduction du nombre de défauts.
8.4 Les travaux de gestion de cache de donnée
De nombreux travaux ont été mènes à l’optimisation des ressources en cache afin
d’augmenter la charge locale et réduire le nombre de requêtes évaluées sur les serveurs
et la consommation de bande passante. Par exemple :
Un site web à usage intensif de données est un site Web qui gère un grand nombre de
pages dont le contenu est construit dynamiquement, à partir de grandes bases de
données. Dans ce contexte, la demande d'une page par un client peut nécessiter une
interaction couteuse avec le système de gestion de bases de données (pour la connexion
au système et l'exécution des requêtes nécessaires à la récupération des données),
risquant ainsi d'augmenter considérablement le temps de réponse. Les auteurs [14]
adressaient ce problème de performance en s'appuyant sur la spécification déclarative de
sites Web.
Ils ont proposé une architecture configurable de caches à plusieurs niveaux et sa mise
en œuvre dans le cadre de Weave, un système de gestion de sites web développé à
l’INRIA. Des fragments XML et/ou des fichiers HTML. Ils illustraient leur approche à
l’aide d’un site Web construit à partir de la base de données du benchmark TPC/D. Puis
ils évaluaient expérimentalement, les performances de différentes stratégies de gestion
de cache en utilisant leur plate-forme de test weaveBenche. Enfin, ils donnaient un
ensemble de directives permettant de configurer la gestion du cache en se basant sur les
spécifications du site Web.
Les travaux de chercheurs [15], [16] tels qu’ARUN IYENGAR et JIM
CHALLENGER présentent une nouvelle approche pour la mise en cache des pages
Web dynamiques afin d'améliorer les performances. Selon les chercheurs l’algorithme
appelé propagation des mises à jour des données (Data Update Propagation -DUP-)
déterminent la façon dont les pages Web mises en cache sont affectés par les
modifications. Par exemple, un ensemble de plusieurs pages Web en cache peuvent être
construit à partir de tables appartenant à une base de données. Dans cette situation, une
méthode est nécessaire pour déterminer quelles sont les pages Web sont touchées par les
mises à jour de la base de données. De cette façon, les caches peuvent être synchronisées
avec les bases de données de sorte qu'ils ne contiennent pas de données périmées.
Chapitre I : Etude sur les techniques de gestion de persistance
P a g e | 31
9. Conclusion
Le problème de la gestion de la persistance dans les langages orientés objet est un
problème capital pour tous les développements logiciels. D’autant plus qu’une partie de
la performance d’une application se joue sur le lien entre celle-ci et la base de données.
Ce problème peut devenir rapidement complexe et coûteux. Ce chapitre introduit de
nombreux concepts qui sont liés au domaine de problème de persistance. Nous avons
présenté les solutions actuelles pour résoudre la persistance des objets en utilisant
l'approche orient aspect.
Dans la suite de ce document, nous présenterons la programmation orientée aspect.
Chapitre II : Présentation de la Programmation orientée aspect
P a g e | 32
Chapitre
II
Chapitre II: Présentation de la Programmation orientée
aspect
1. Introduction
La réutilisation est l'une des principales promesses de la programmation par objets.
Malheureusement, elle n'est pas toujours possible du fait du mélange, lors de
l'implémentation des applications, des définitions des services réalisés (fonctionnalités)
avec des propriétés non-fonctionnelles représentant des mécanismes d'exécution
spécifiques (distribution, tolérance aux fautes, persistance, …). Afin de pallier ce défaut,
le paradigme de la programmation par aspects considère que les services d'une
application et ses propriétés non-fonctionnelles correspondent à des aspects qui doivent
être découplés les uns des autres [08].
La POA se propose de pallier aux faiblesses des paradigmes classiques
(programmation modulaire, POO, programmation par composant) en introduisant un
autre type d’organisation au sein des programmes.
Il existe des fonctionnalités transverses à plusieurs entités logicielles comme par
exemple la persistance, la tolérance aux fautes. De même, il existe, au sein du même
application, des préoccupations complètement réparties dans le code. L’exemple le plus
cité est la gestion des traces au sein d’une application.
En tant que paradigme de programmation, la programmation orientée aspect se
positionne comme le successeur de la programmation orientée objet. Néanmoins, elle ne
vise pas à remplacer entièrement la POO mais a plutôt comme objectif de la compléter
afin d’obtenir des programme mieux structurés et plus clairs.
Il est à noter que la programmation par aspects est indépendante de la programmation
par objets. En effet, il est possible d’utiliser la programmation par aspects conjointement
à d’autres paradigmes de programmation (fonctionnelle, impérative, …) [08].
Dans ce chapitre nous rappellerons d’abord les problèmes résolus pas la
programmation orientée aspect. Puis nous introduisons les concepts de la programmation
orientée aspect, nous présentons aussi le langage AspectJ ainsi que ses concepts. Nous
Chapitre II : Présentation de la Programmation orientée aspect
P a g e | 33
introduirons alors quelques exemples choisis de programmation par aspects écrits
principalement avec le langage AspectJ vu comme une extension du langage Java. Ces
exemples seront l’occasion de caractériser le modèle d’aspects sous jacent en précisant
les notions de points de jonction, de coupes, d’introductions.
2. Problèmes résolus par la programmation orientée aspect
Le développeur d’application ont généralement plusieurs préoccupations à apprendre
en compte dans leurs développement .ces préoccupations peuvent être divisées en deux
catégories : les préoccupations fonctionnelles, qui correspondent au cœur de métier de
l’application, et les préoccupations techniques, liées à l’environnement d’exécution.
Le principe de séparation des préoccupations cherche à rendre indépendantes ces
préoccupations afin d’améliorer la modularité des applications. La programmation
orientée objet a permis d’atteindre un certain degré d’indépendance sans pour autant
casser totalement les liens entre les préoccupations fonctionnelles restent encore
dépendantes des préoccupations techniques.
La programmation orientée aspect est un nouveau paradigme de programmation qui
cherche à améliorer la séparation des préoccupations en modularisant les éléments
transversaux des applications. bon nombre de préoccupations, elles sont modularisées
sous forme d’aspects.
L’objectif de la POA est la séparation des préoccupations. La contrainte principale est
la dispersion des préoccupations transversales à travers le code métier. [06]
Dans cette section nous expliquons les problèmes résolus par la programmation
orientée aspect.
2.1. Fonctionnalités transversales
La POO s’efforce de découper une application en classes cohérentes et
indépendantes. Cependant, ces entités peuvent parfois être liées. Pawlak, Retaillé et
Seinturier [17] nous donnent comme exemple un cas de contrainte d’intégrité
référentielle : un objet client ne peut être supprimé s’il n’a pas honoré toutes ses
commandes.
Comme la classe client n’est pas censée connaitre les contraintes imposées par les
autres classes et que la classe commande n’a aucune raison de permettre la suppression
d’un client, nous nous retrouvons face un problème quant à la séparation indépendante
des tâches. C’est ce que l’on appelle une fonctionnalité transversale (crosscutting
concern).
Chapitre II : Présentation de la Programmation orientée aspect
P a g e | 34
2.2. Dispersion du code
La programmation procédurale induit un découpage en fonction des traitements à
implémenter, tandis que la programmation objet induit un découpage en fonction des
données qui seront encapsulées dans les classes. Certaines fonctionnalités
s’accommodent mal de ce découpage, et les instructions correspondant à leur utilisation
se retrouvent dispersées dans l’ensemble de l’application. Tout changement dans
l’utilisation de ces fonctionnalités implique dés lors de devoir consulter et modifier un
grand nombre de fichiers. On dit en ce cas que leur code est éparpillé, ou dispersé.
La figure II .1 schématise une application composée de trois classes. Les traits
représentent les lignes de code correspondant à des fonctionnalités (par exemple, la
gestion de persistance). Ces fonctionnalités sont transversales à l’application car elles
affectent toutes ses classes.
Figure II .1 – Dispersion du code d’une fonctionnalité
Outre le problème de mélange de code, la réutilisation d’une propriété nonfonctionnelle est d’autant plus difficile que sa définition se trouve dispersée. De ce fait,
elle ne peut être isolée pour être réutilisée. En effet, une même propriété nonfonctionnelle peut toucher plusieurs objets [08].
Chapitre II : Présentation de la Programmation orientée aspect
P a g e | 35
3. Découverte du monde des Aspects
Dans la présente section nous rappellerons les grandes lignes des paradigmes de
programmation sur lesquels s’appuiera la programmation par aspects.
3.1. Historique
La programmation orientée aspect (POA) est un nouveau paradigme de
programmation ont été définies au centre de recherche de Xerox à Palo Alto[07] au
milieu des années 1990 .
La POA a émergé à la suite de différents travaux de recherche, dont l’objectif était
d’améliorer la modularité des logiciels de faciliter la réutilisation et la maintenance.
Elle ne remet pas en cause les autres paradigmes de programmation, comme
l’approche procédurale ou l’approche objet, mais les étend en offrant des mécanismes
complémentaires pour mieux modulariser les différentes préoccupations d’une
application et améliorer ainsi leur séparation.
3.2. Principe de POA
Une solution aux problèmes de mélange et de dispersion du code des propriétés nonfonctionnelles rencontrés avec la programmation par objets, consiste à séparer et
découpler leurs définitions comme le veut le principe de la separation of concerns.
La programmation orientée aspect complémente la POO en apportant des solutions
aux deux challenges que sont l’implémentation de fonctionnalités transversales et le
phénomène de dispersion du code.
Une application orientée aspect fondée sur la POO est composée de deux parties, les
classes et les aspects :
 Les classes constituent le socle de l’application. Il s’agit des données et des
traitements qui sont au cœur de la problématique de l’application et qui répondent
aux besoins de celle-ci.
 Les aspects intègrent aux classes des éléments (classes, méthodes, données)
supplémentaire, qui correspondent à des fonctionnalités transversales ou à des
fonctionnalités dont l’utilisation est dispersée.
Il est important de souligner que la programmation par aspects utilise la technologie
objet dans un cadre qui en conserve les bénéfices tout en palliant les limitations
suscitées.
Chapitre II : Présentation de la Programmation orientée aspect
P a g e | 36
3.3. Quelques concepts de la programmation orientée aspect
Dans cette section, nous introduisons les concepts de ce nouveau paradigme. Nous
expliquons quelques les constituants de l’aspect, comment les points de jonction, les
coupes, le ‘codes advice’, ‘Tissage d’aspects’, ‘Mécanisme d’introduction’ .
a) Notion d’Aspect
La programmation orientée aspect propose l’utilisation d’aspects qui permettent
d’implémenter des fonctionnalités transversales, ou dont l’utilisation s’avère dispersée
dans le code, en intégrant aux classes des éléments (comme des méthodes ou des
données) supplémentaires.
Un aspect est une unité modulaire qui recouvre et concerne la structure des autres
unités modulaires globalement.
Des aspects existent au niveau de la conception et de l’implémentation. Un aspect de
niveau conception est une unité de conception qui s'applique à l’ensemble de la structure
de conception. Un aspect de niveau programmation ou code est une unité de programme
qui, là encore, concerne la structure de la plupart, voire de tous les autres modules du
programme.
L’intégration de ces éléments supplémentaires dans les classes se fait au moyen de
codes advices et de coupes qui permettent de spécifier le code de la fonctionnalité et où
celui-ci va s’appliquer. Ainsi, les aspects résolvent le problème d’indépendance des
classes puisqu’ils se chargent des fonctionnalités transversales et permettent de réduire la
dispersion de code dont nous avons parlé grâce à une localisation de l’utilisation des
services (voir Figure II .2) [07].
Figure II .2 – Localisation du code d’une fonctionnalité transversale dans un aspect
Chapitre II : Présentation de la Programmation orientée aspect
P a g e | 37
L’apport essentiel de la POA est de fournir un moyen de rassembler dans un aspect du
code qui autrement, serait dispersé au sien d’une application.
Figure II .3 – Identification des aspects d’une application
Le développement de logiciels en utilisant l'approche orientée aspect est similaire au
développement de logiciels avec d'autres méthodologies (Figure II .3) : identification
des préoccupations, leur implémentation, et leur combinaison pour former le système
final. La communauté des chercheurs de l'AOP définit ces trois étapes comme suit :
1. Décomposition aspectuelle : Les besoins sont ici décomposés pour identifier les
préoccupations fonctionnelles et transversales. Par exemple, un développeur
pourra identifier les préoccupations suivantes : cache, gestion transactionnelle de
la persistance, authentification, etc. Ensuite, il pourra décider que seul le logique
métier est une préoccupation fonctionnelle. Toutes les autres préoccupations sont
des préoccupations transversales au système et qui vont être utilisées par plusieurs
modules.
2. Implémentation des préoccupations : Chaque préoccupation est implémentée
indépendamment des autres. Le développeur aura à implémenter le logique
métier, le logging, le cache, la gestion transactionnelle de la persistance,
l'authentification, etc.
3. Recomposition aspectuelle : Des règles de recompositions sont spécifiées en
créant des unités appelées aspects. Le processus de recomposition, aussi connu
sous le nom de tissage ou d'intégration, et le programme qui la réalise est un
tisseur d’aspect. L’application obtenue à l’issue du tissage est dite tissée.
b) Notion de Point de jonction
Un aspect était une entité logicielle implémentant une fonctionnalité transversale à
une application. La définition de cette structure transversale passe par la notion de point
de jonction [17]. Un point de jonction est un point dans le flot de contrôle d'un
programme dans lequel un ou plusieurs aspects peuvent être appliqués.
 Méthodes : Les différents scénarios d'exécution d'une application peuvent être
exprimés en termes de séquences de messages qui déclenchent l'exécution de
Chapitre II : Présentation de la Programmation orientée aspect
P a g e | 38
méthodes. Les appels et les exécutions de méthodes sont donc deux types de
points de jonction couramment utilisés. Les trois principaux événements qui
constituent des points de jonction de méthodes sont l’appel, le début et la fin
d’une méthode.
 Constructeur : Les constructeurs sont des méthodes qui revêtent un caractère
particulier puisqu’ils sont exécutés lorsqu’un objet est instancié. Comme pour les
méthodes, la POA permet d’intercepter cet événement.
 Attributs : Les opérations de lecture et d'écriture sur les attributs comme des
types de points de jonction.
 Exception : La levée et la récupération d’une exception constituent donc des
points de jonction. Le code à exécuter lors de la levée de cette exception sera
défini dans un aspect.
c) Notion de Coupes
Une coupe désigne un ensemble de points de jonction [07]. Elles permettent au
programmeur de spécifier les points de jonction comme l'appel à une méthode,
l'instanciation d'objet ou l'accès à une variable). Tout "pointcut" est une expression
vérifiant la correspondance d'un point de jonction. Les points de coupure représentent
des coupes qui sont de deux types : les coupes simples et les coupes composées. Une
coupe est définie à l’intérieur d’un aspect .dans les cas simples, une seule coupe suffit
pour définir la structure transversale d’un aspect. Dans les cas plus complexes, un aspect
est associé à plusieurs coupes.
d) Codes advice
Un aspect définit une fonctionnalité transversale. Comme nous l’avons vu, il spécifie
le caractère transversal grâce aux coupes. La fonctionnalité est, quant à elle, spécifiée
par des codes advices. [07]
Une fois la coupe définie, il faut écrire le code à exécuter au moment où l'événement
décrit par la coupe est levé. Avant d'écrire ce code advice, il faut décider à quel moment
exécuter le code : avant l'événement, après ou autour de l'événement.
 Advice before (avant) : Le mot-clé before permet d'exécuter du code avant
d'entrer dans le code lié à l'événement (exemple appel de méthode, lecture
d'attribut, etc...).
 Advice after (après) : Le mot-clé after permet quant à lui permet d'exécuter du
code après l'événement.
 Advice around (autour): Le mot-clé around permet soit de remplacer
l'événement en lui même, soit d'exécuter du code avant et après le point de
jonction. Pour exécuter le code de l'événement il faut utiliser le mot-clé proceed à
l'intérieur du code advice. Si la méthode a un type de retour, alors il faut faire
Chapitre II : Présentation de la Programmation orientée aspect
P a g e | 39
précéder le mot-clé around de Object. L'appel à proceed renvoie alors un type
Object qu'il est possible de récupérer pour le renvoyer [33].
Un code advice définit quant à lui ce que l’aspect greffe dans l’application, autrement
dit les instructions ajoutées par l’aspect.
e) Tissage d’aspects
Une application orientée aspect contient des classes et des aspects. L'opération qui
prends en entrée les classes et les aspects et produit une application qui intègre les
fonctionnalités des classes et des aspects est connu sous le nom de tissage d'aspect
(aspect weaving) [07]. Le programme qui réalise cette opération est appelé tisseur
d'aspects (aspect weaver) ou bien tisseur (Weaver) tout court (Figure II .4).
Figure II .4 – Tissage des aspects
L’opération de tissage peut être effectuée à la compilation ou à l’exécution [22]. Dans
le cas du tissage à la compilation, le tisseur est un programme qui, avant l’exécution,
prend en entrée un ensemble de classes et un ensemble d’aspects et fournit en sortie une
application augmentée des aspects.
Dans le cas du tissage à l’exécution, le tisseur est un programme qui permet
d’exécuter à la fois l’application et les aspects qui lui ont été ajoutés. Les aspects ont une
existence propre lors de l’exécution.
f) Mécanisme d’introduction
L'objectif du mécanisme d'introduction est d'être capable d'étendre le comportement
d’une classe à l'aide de méthodes ou d'attributs définis dans un aspect. Le terme
introduction renvoie au fait que ces éléments sont introduits, c’est-à-dire ajoutés à
l’application.
L’introduction est donc un mécanisme purement additif, qui ajoute de nouveaux
éléments à une classe. A la différence de l’héritage en POO, l’introduction ne peut
Chapitre II : Présentation de la Programmation orientée aspect
P a g e | 40
étendre les classes qu’en rajoutant de nouveaux éléments, il n’est donc pas possible de
redéfinir une méthode.
4. Aperçus sur le langage AspectJ
AspectJ est aujourd'hui une référence pour la programmation par aspects telle que
définie par Kiczales. C’est un langage qui étend Java et permet la définition des aspects.
Ce langage représente l’application des aspects dans le paradigme de l’Orienté Objet.
AspectJ est en fait une extension à Java [08]. Les composants sont toujours écrits en
Java pur. Grâce aux nouvelles possibilités offertes par la syntaxe d’AspectJ, nous
pouvons définir des aspects accompagnés de leurs règles d'intégration. Un aspect est
donc un mélange de règles AspectJ et d'instructions Java qui modularise une
préoccupation.
4.1 Aspects dans AspectJ
Un aspect est une entité logicielle qui capture une fonctionnalité transversale à une
application [07].
Un aspect est une entité logicielle très similaire à une classe. Il définit du code, lequel
Abstrait et modularise une préoccupation.
AspectJ introduit le mot-clé aspect qui permet de spécifier que l’entité logicielle
définie est un aspect, à l’instar du mot-clé class qui spécifie la définition d’une classe.
L’exemple suivant illustre la définition d’un aspect [21]:
public aspect PremierAspect {
/* code de l’aspect */
}
Un aspect est défini dans un fichier qui porte le même nom que le nom de l’aspect. Ce
fichier porte l’extension .java, mais il est fortement conseillé d’utiliser les extensions .aj
ou .ajava pour des aspects.
4.2 Points de jonction dans AspectJ
Un ensemble de points de jonction est identifié dans une coupe à l’aide du mot-clé
pointcut. Une expression est également fournie pour filtrer l’ensemble obtenu. Un point
de jonction représente un événement dans l’exécution du programme qui peut être
intercepté pour exécuter un code advice correspondant.
Chapitre II : Présentation de la Programmation orientée aspect
P a g e | 41
Bien que n'importe quel point d'exécution dans du programme puisse être défini
comme un point de jonction, AspectJ limite les points de jonction à ceux qui peuvent
être utilisés de manière systématique [39].
a) Types de point de jonction
Les types de points de jonction fournis par AspectJ peuvent concerner des méthodes,
des attributs, des exceptions, des constructeurs ou des blocs de code statique (static). Un
dernier type concerne les exécutions de code advice. [32].
Les points de jonction, les plus utilisés, dans la POA sont : les méthodes, les attributs, les
constructeurs et enfin les exceptions.
 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. La spécification de ces
points se fait dans l’aspect par call (methexpr) ou execution (methexpr) qui identifient
tous les appels vers des méthodes dont le profil correspond à une description donnée par
methexpr.
 Appel de méthode : call (methexpr) : Ce mot-clé identifie tous les appels vers
des méthodes dont le profil correspond à la description donnée par ‘methexpr’.
 Exécution de méthode : execution (methexpr) : Ce mot-clé identifie toutes les
exécutions de méthodes dont le profil correspond à l’expression ‘methexpr’.
La différence fondamentale entre les types call et execution concerne le contexte dans
lequel le se trouve l’application lors de l’exécution du code advice associé. Un point de
jonction donnée par call (methexpr) correspond à l’appel d’une méthode compatible à
methexpr. Il se trouve donc dans le code de la méthode appelante. Alors qu’un point de
jonction donnée par execution (methexpr) se trouve dans la méthode appelée. L’ordre
d’exécution des différents codes advices serait le suivant :
1. Dans la méthode appelante : Exécution de la première partie du code advice
associé au point de jonction call.
2. Dans la méthode appelée : Exécution de la première partie du code advice associé
au point de jonction execution.
3. Dans la méthode appelée : Exécution de la méthode appelée.
4. Dans la méthode appelée : Exécution de la deuxième partie du code advice
associé au point de jonction execution.
5. Dans la méthode appelante : Exécution de la deuxième partie du code advice
associé au point de jonction call.
Chapitre II : Présentation de la Programmation orientée aspect
P a g e | 42
 Attributs :
La lecture et la modification d’attributs constituent également des points de
jonction. On peut penser notamment à une utilisation à des fins de persistance.
La spécification de ces points se fait dans l’aspect par get (attrexpr) qui identifie
tous les points de jonction représentant la lecture d’un attribut dont le profil
vérifie attrexpr et set (attrexpr) qui identifie toutes les modifications d’un
attribut dont le profil est compatible à attrexpr. Ces mots clés sont intéressants
pour des aspects qui souhaitent intercepter la modification de l’état d’un objet
[13].
 Constructeurs :
Peuvent être considérés comme des méthodes particulières. Il s’agit de
méthodes invoquées lorsqu’un objet est instancié. Comme pour les méthodes, la
POA permet d’intercepter cet événement. Il est intéressant de remarquer que l’on
peut intercepter les appels des constructeurs avec le mot-clé call que nous avons
explicité précédemment. Il suffit de fournir une methexpr identifiant les méthodes
de nom new.
Aspectj définie des coupes prenant en compte les constructeurs de classe. Pour
cela deux types de point de jonction sont disponibles : initialization et
preinitization. La façon la plus simple d’appréhender la différance ces deux types
consiste à étudier deux situations, selon que le fais ou non appel à un constructeur
hérité.
 Exceptions :
Les événements de levée et de récupération d’exceptions peuvent aussi constituer
des points de jonction. Le code à exécuter lors de la levée de cette exception sera
défini une seule fois dans un aspect. La spécification de ces points se fait dans
l’aspect par handler (exceptexpr) qui identifie toutes les récupérations d’exception
dont le profil vérifie exceptexpr. Il s’agit donc, en Java de l’exécution des blocs
catch. AspectJ ne permet pour le moment que l’utilisation de codes advice de type
before sur les points de jonction de récupération d’exception.
AspectJ introduit d’autres de point de jonction, comme par exemple :
Les points de jonction de type staticinitialization correspondent aux exécutions des blocs
de code static. Le point de jonction, adviceexecution permet de déclencher un aspect avant
ou après l’exécution d’un code advice. Il est ainsi possible de définir un aspect qui modifie
le comportement d’un autre aspect.
Chapitre II : Présentation de la Programmation orientée aspect
P a g e | 43
b) Définition des profils
Tous les mots-clés que nous avons vus requièrent un paramètre. Ce paramètre est une
expression qui permet, en spécifiant un profil, de filtrer l’ensemble de points de jonction
donné par le mot-clé.
L’expression précisant le profil des éléments qui nous intéresse peut faire usage de
quantificateurs (appelés wildcards) afin d’introduire de la généricité dans les profils
sélectionnés. Ces wildcards sont *, .. et +. [32]
4.3 Coupes dans AspectJ
Elles permettent au programmeur de spécifier les points de jonction comme l'appel à
une méthode, l'instanciation d'objet ou l'accès à une variable). Tout "pointcut" est une
expression vérifiant la correspondance d'un point de jonction [32]. Les points de coupure
représentent des coupes qui sont de deux types : les coupes simples et les coupes
composées.
Une coupe est introduite grâce au mot clé pointcut. La syntaxe est :
pointcut nomDeLaCoupe (paramètres) Définition de la coupe
Une coupe permet de regrouper un ou plusieurs points de jonction. Pour savoir quelle
syntaxe de définition de coupe utiliser, il faut savoir sur quelle sorte de point de jonction
on souhaite faire une coupe pour exécuter du code. Un point de jonction peut être une
méthode. Le mot clé alors utilisé pour définir la coupe peut être call ou execution.
Les coupes d’un aspect sont identifiées par un nom et des paramètres. Les paramètres
sont des informations qui sont transmises de la coupe vers les codes advice qui
l’utilisent.
Selon le type de point de jonction, le mot clé à utiliser pour définir la coupe est
différent.
Chapitre II : Présentation de la Programmation orientée aspect
P a g e | 44
La syntaxe est résumée dans le tableau suivant [13].
Syntaxe
call (methodeExpression)
Execution (methodeExpression)
Get (attributExpression)
Get (attributExpression)
Handler (exceptionExpression)
Initialization (constanteExpression)
Preinitialization (constanteExpression)
Staticinitialization (classeExpression)
Adviceexecution ()
Description du point de jonction
Appel d'une méthode dont le nom vérifie
methodeExpression.
Exécution d'une méthode dont le nom vérifie
methodeExpression.
Lecture d'un attribut dont le nom vérifie
attributExpression.
Exemple :
get(int Point.x)
Ecriture d'un attribut dont le nom vérifie
attributExpression.
Exécution d'un bloc de récupération d'une
exception (catch) dont le nom vérifie
exceptionExpression.
Exemple :
Handler (IOException+)
Exécution d'un constructeur de classe dont le
nom vérifie constanteExpression.
Exemple :
Initialization (Customer.new (..))
Exécution d'un constructeur hérité dont le nom
vérifie constanteExpression
Exécution d'un bloc de code static dans une
classe dont le nom vérifie classeExpression.
Exemple :
staticinitialization(Point)
Exécution d'un code advice.
Tableau II.1 - Tableau récapitulatif des points de jonction possibles et la syntaxe à utiliser
pour définir la coupe
4.4 Codes Advices
Le code advice définit le code greffé par l’aspect dans l’application d’origine. Dans
le cas de code advice de type before (resp. after, around), celui-ci sera intégré avant
(resp. après, autour) le pointcut de l’aspect. AspectJ introduit deux nouveaux types :
after returning et after throwing. Ces deux types supplémentaires représentent
respectivement le retour normal et anormal (avec levée d’exception) d’un point de
jonction.
Chapitre II : Présentation de la Programmation orientée aspect
P a g e | 45
Il existe trois modes d’exécution des advices :
- before : le compilateur insère un appel à l’advice avant le code correspondant au
pointcut.
- after : le compilateur insère un appel à l’advice après le code correspondant au
pointcut.
- around : le compilateur insère un appel à l’advice à la place du code
correspondant au pointcut et fournit au programmeur un moyen d’appeler le code
original avec les arguments qu’il souhaite et de récupérer l’éventuelle valeur de
retour.
4.5 Introspection de point de jonction
Le terme introspection peut être interprété comme l’action d’inspecter à l’intérieur. Il
s’agit d’obtenir des informations sur le point de jonction courant. Ce point de jonction
peut correspondre à l’exécution d’une méthode ou d’un constructeur. A cet effet,
certains outils de POA tels que AspectJ propose un mécanisme d’introspection de point
de jonction.
AspectJ permet d’utiliser le mot-clé thisJoinPoint pour référencer à un objet décrivant
le point de jonction en cours. Ce mot-clé appartient à la classe prédéfinie
org.aspectj.lang.JoinPoint.
4.6 Mécanisme d’introduction
Il s’agit d’un mécanisme qui permettre d’étendre le comportement en ajoutant des
éléments. Les catégories d’éléments peuvent êtres ajoutés concernent: l’attribut, la
méthode, le constructeur, la classe héritée, l’interface implémentée et exception non
conditionnelle à l’exécution d’un point de jonction [32].
AspectJ permet l’ajout de cinq types d’éléments : attribut, méthode, constructeur,
classe héritée et interface implémentée L’introduction de ces éléments se déclare à
l’intérieur d’un aspect. En réalité, l’aspect déclare des éléments pour le compte des
classes. C’est ce que l’on dénomme une déclaration intertype. Le programmeur doit
toutefois faire attention à ne pas introduire un élément déjà existant dans la classe visée
sous peine de voir la compilation échouer.
Bien évidemment, les éléments introduits ne peuvent être utilisés que par des aspects.
L’application n’est pas supposée en connaitre l’existence.
Cependant, il est quand même possible d’utiliser certains de ces éléments grâce au
package java.lang.reflect. En effet, il est par exemple possible de récupérer toutes les
méthodes d’une classe au runtime. Les méthodes introduites se retrouvent alors dans
l’ensemble obtenu.
Chapitre II : Présentation de la Programmation orientée aspect
P a g e | 46
4.7 Héritage dans la POA
AspectJ permet également de modifier la hiérarchie d’héritage des classes. A l’aide du
motclé declare parents. AspectJ offre la possibilité de rendre une classe héritière d’une
autre. Mais cette introduction n’est pas sans condition, il se peut en effet que la classe
visée hérite déjà d’une surclasse. Dans ce cas, l’introduction ne sera possible que si la
nouvelle surclasse est une sousclasse de l’ancienne surclasse.
Le mécanisme d’introduction d’interface implémentée est similaire à l’introduction de
classe héritée. Elle se réalise à l’aide du même mot-clé mais l’introduction d’interface
implémentée est sans condition. Le code suivant montre un exemple de cinq types
d’éléments du mécanisme d’introduction.
7. Conclusion
Le développement applicatif et les méthodologies liées ont fortement évoluées tout au
long de l’histoire de l’informatique. Le but recherché étant de pouvoir produire des
logiciels répondant le mieux possible à la demande du client en moins de temps possible.
La programmation orientée objet a su introduire de nouveaux concepts intéressants
avec ce même objectif de produire des produits de qualité. Toutefois, nous pouvons
encore trouver certaines limites à ces concepts que l’on aimerait pouvoir surpasser. Ce
sont ces limites que la POA se propose de résoudre en introduisant les notions de
séparation des préoccupations. [39]
Nous avons présenté dans ce chapitre les principes concepts de la programmation
orientée aspect, les points de jonction, les coupes, les codes advice, et le mécanisme
d’introduction. Nous avons aussi présenté les concepts de langage AspectJ, support de
notre travail de recherche.
Comme notre travail consiste à propose une approche intégrant des techniques de
persistance des données dans un seul aspect, nous avons choisi d’optimiser les
performances des systèmes d’interrogation, avec l'utilisation d’un cache objet, qui va
permettre de réduire les accès au support de persistance en conservant en mémoire les
objets les plus fréquemment accédés.
Chapitre III: La proposition
P a g e | 47
Chapitre
III
Chapitre III: approche proposée
1 .Introduction
Notre objectif principal est de définir une approche qui intègre de la persistance dans
le domaine de la programmation orientée aspect afin de bénéficier des avantages de
localisation, de réutilisation et de réduire le temps et le coût dans le développement et la
maintenance des systèmes orientés aspects. Ces avantages sont considérés comme le but
majeur de notre travail.
Nous commençons tout d’abord par la présentation de notre stratégie sur la gestion du
cache objet. Ce dernier constitue un espace mémoire pour le stockage d’objets, le
mécanisme de gestion de cet espace permet de conserver en mémoire une partie des
objets stockés sur le support de persistance. Lorsque l’application demande le
chargement d’un objet, ce dernier est chargé depuis le support de persistance et stocké
dans la mémoire cache. Si l’application accède ultérieurement à cet objet, la couche de
persistance utilise la copie de l’objet en cache pour satisfaire la demande de l’application
et ainsi évite un accès à la base de données. Au fur et à mesure de l’exécution, les objets
chargés par l’application remplissent le cache. Plusieurs techniques existent pour gérer
efficacement le cache : on peut choisir de ne conserver que les objets les plus récemment
utilisés, ou bien les objets tels qu’ils sont référencés par l’application.
L’utilisation d’un cache est toujours importante dans les systèmes informatiques, afin
de fournir une haute qualité de service et notamment une amélioration des temps de
réponse. En effet, un cache fournit un accès rapide aux données, pouvant tirer bénéfice
de l’utilisation d’un support physique efficace, d’un ensemble d’éléments gérés plus
petit autorisant des recherches plus rapides, ou encore d’un placement évitant des
communications réseaux. De plus, employer un cache réduit la charge sur les serveurs et
éventuellement sur les liens de communication, la récupération des éléments étant alors
plus rapide. Ainsi un cache améliore généralement les performances, en dépit des coûts
Chapitre III: La proposition
de déploiement, d’administration, de gestion et
cohérence qu’il peut engendrer.
P a g e | 48
éventuellement des problèmes de
La mise en cache d'objets offre plusieurs avantages avec un accès rapide aux données,
mais il souffre également de certains inconvénients tels que la complexité de la
synchronisation et la surcharge de la mémoire.
Notre objectif est de proposer et étudier le problème de la synchronisation et de
définir un modèle qui permet la gestion de la cohérence du contenu de la mémoire cache
avec le serveur. Cette solution est valable pour les systèmes d’interrogation de données,
notamment dans des contextes à grande.
Pour réaliser ce travail on se base sur le cache sémantique et les déclencheurs
(triggers). Un cache sémantique est utilisé pour conserver des résultats de requêtes, en
maintenant une connaissance des données présentes, permettant des accès intelligents
aux entrées stockées.
Les applications de grande taille sont souvent difficiles à maintenir et à faire évoluer
car elles contiennent un trop grand nombre de préoccupations emmêlées les unes aux
autres. Les modèles de composants à base de conteneurs tels que les Enterprise Java
Beans (EJB) ou le modèle de composant de CORBA (CCM) proposent une séparation
des préoccupations. Les conteneurs sont chargés de réaliser des préoccupations telles
que la gestion de persistance ou la sécurité, de façon transparente pour les composants.
Ces préoccupations sont appelées des services non fonctionnels. Cependant, les
conteneurs actuels ne gèrent qu'un nombre limité de services non fonctionnels, avec des
sémantiques fixes. Avec l’approche Orientée aspect il est possible de rendre le cache
indépendant de l’application. Dans notre approche, nous définirons un modèle qui
facilite l’ajout de services non fonctionnels. Et nous exposons les avantages et les
inconvénients de cette approche. On se base sur la programmation aspect et le patron de
conception (Data Access Object DAO), ce dernier permet de séparer la couche d’accès
aux données de la couche logique applicative. Son utilisation permet d’abstraire la façon
dont les données sont stockées au niveau des objets métier. L’ensemble de ces objectifs
nous amène à garantir l'orthogonalité de la persistance.
Dans ce qui suit, nous décrivons la notion de cache sémantique. Nous terminons ce
chapitre par la présentation d’un modèle de conception par aspects, en s’appuyant sur le
patron de conception DAO.
2. Le cache sémantique
Dans les systèmes de gestion de données repartis, deux types d’architectures existent:
les architectures par rapatriement de données (data shipping) et les architectures par
rapatriement de requêtes (query shipping). Avec la première approche, les données sont
récupérées en terme d’objets ou de pages à l’aide de leur identifiant. On parle alors
Chapitre III: La proposition
P a g e | 49
d’accès navigationnel, les opérations étant exécutées du côté des clients. La seconde
approche repose sur un accès associatif, les requêtes étant transférées et calculées sur les
serveurs. Les caches sémantiques visent à fusionner ces deux architectures en proposant
un travail d’évaluation local dans un système d’accès associatif. L’accès associatif évite
de récupérer des données inutiles et le cache autorise un raisonnement fin sur son
contenu, autorisant l’évaluation de requêtes sur les entrées stockées.
Figure III.1 – Fonctionnement d’un cache sémantique
Les caches sémantiques gèrent leur contenu (recherche, remplacement et résolution)
en termes de résultats de requêtes. Dans la littérature, ces résultats sont appelés régions
sémantiques ou segments Sémantiques. Le fonctionnement d’un cache sémantique est
illustre par la Figure III.1 Quand une requête est posée, elle est décomposée en deux
parties disjointes : la requête de consultation (probe query), qui récupère la portion de
résultat disponible dans le cache, la requête restante (remainder query) utilisée pour
récupérer tous les objets absents. Si la requête restante n’est pas nulle, autrement dit si
celle-ci couvre une partie de l’espace sémantique qui n’est pas présent en cache, elle est
envoyée au serveur pour être évaluée.
3. Stratégie de mise en cache
Le cache de requêtes sauvegarde la requête Select conjointement avec le résultat
qui a été envoyé au client. Les requêtes sont comparées avant l’analyse.
Si une requête identique est reçue plus tard, le serveur récupère les résultats stockés
dans le cache de requête plutôt que de l'analyser et l'exécuter à nouveau. Le cache de
requête est partagé entre les sessions, un jeu de résultats généré par un client peut être
envoyé en réponse à la même requête émise par un autre client.
Le cache de requêtes est utile dans un environnement où les tables ne changent pas
très souvent, et pour lesquelles le serveur reçoit plusieurs requêtes identiques. C'est une
situation typique pour de nombreux serveurs Web qui génèrent beaucoup de pages
dynamiques basées sur le contenu de base de données.
Chapitre III: La proposition
P a g e | 50
Chaque fois qu'une table est modifiée, le cache doit être vérifié, Si une table change
(INSERT,
UPDATE,
DELETE,
TRUNCATE,
ALTER
ou
DROP
TABLE|DATABASE), alors toutes les requêtes mises en cache qui utilisaient cette table
deviennent obsolètes. Afin d’éviter l'invalidité du résultat de premier SELECT, on peut
calculer le résultat comme suit : nous gardons les lignes récemment insérées dans des
tables distincts appelées des tables temporaires, pour chaque table temporaire
correspond une table de base de données. La valeur de chaque champ dans les lignes de
la table temporaire est la même que si les lignes étaient présentes dans la principale
table. A la réception d'une requête de sélection, le résultat de la requête finale est obtenu
par la fusion de résultat de l’exécution de la requête sur la table temporaire avec les
résultats de la requête en cache avant la modification de la base de données. Cette
optimisation a des avantages potentiels d’interroger des résultats, qui autrement seraient
invalides par des changements dans la base de données. La Figure III.2 montre un
SELECT qui récupère un grand nombre de lignes (A) serait invalidé par une suite
INSERT (∆T1).
Figure III.2 – Le cache avant la modification de la table T1
En place les nouvelles lignes insérées (∆T1) dans une table temporaire, pour que nous
évitions d'invalider le résultat de premier SELECT, on peut calculer le résultat
rapidement par la fusion de la réponse mise en cache (A) avec la réponse (B) calculée à
partir de la table temporaire (Figure III.3). Dans le cas d'une requête de mise à jour
(update ou delete) l’exécution d'une requête nommée suit le m êm e processus comme
INSERT.
Chapitre III: La proposition
P a g e | 51
Figure III.3 – Utilisation d’une table temporaire séparé pour les nouvelles insertions et
réutiliser la réponse de la requête précédente (A) avec la réponse (B)
Dans le cas d’une requête contenant des jointures de deux ou plusieurs tables,
l’exécution de requête se déroule selon la formule suivante :
Notre stratégie présente plusieurs avantages, elle réduit le coût d'une jointure, parce
que les tables temporaires sont moins volumineuses, elle fournit des requêtes
concurrentes permettant aux applications de sauvegarder les d'objets persistants et les
résultats en mémoire pour les partager entre les unités d'exécution, ainsi que
l'optimisation du temps de réponse.
On ce qui concerne les tables temporaires on se base sur la notion de trigger
(déclencheurs) pour historiser les modifications d'une table. Les déclencheurs sont donc
des objets de la base qui nous permet d’automatiser des actions. La particularité des
déclencheurs du LMD (Langage de Manipulation des données), ils vont nous permettre
P a g e | 52
Chapitre III: La proposition
d’effectuer une instruction, à chaque fois qu’une instruction du LMD est effectuée pour
une table donnée. Pour mieux comprendre, prenons un exemple : nous avons deux
tables T1 et sa table temporaire tA1. Nous définissons un déclencheur du LMD sur T1,
qui fait après tout INSERT sur T1, le même insert est appliqué sur la table temporaire
tA1 .
C’est de cette manière que sont automatisées les actions sur les objets de la base. Pour
une instruction donnée sur un objet, une action liée s’exécutera à la suite, ce qui perm et
d’éviter de lire la table modifiée ligne par ligne pour chercher les m odifications faites
sur la table.
REQUETE SQL
SELECT
OUI
NON
Le Résultat de la
requête Existe-t-il
dans cache ?
NON
OUI
Le serveur traite la requête
Modification
d’une table
(insert, update...)
Ecriture du résultat de la
requête dans le cache
Exécute la requête de sélection
sur la table temporaire.
Le résultat final de la requête
est obtenu par la fusion de la
réponse mise en cache avec la
réponse calculée à partir de
la table temporaire
Envoi du résultat
de la requête
Figure III.4 – Processus de mise en cache les requête
P a g e | 53
Chapitre III: La proposition
3.2 Intérêt de mettre la fonction de mise en cache comme aspect
La mise en cache d'objets offre plusieurs avantages tels qu’un accès rapide aux
données. Mais elle possède aussi des inconvénients comme surcharge de la mémoire et
la complexité de synchronisation. La mise en œuvre en tant qu'aspect fournissant la
possibilité d'ajouter dynamiquement le code du cache à l’application. Nous pouvons
également désactiver la mise en cache chaque fois qu'il devient un goulot d'étranglement
en termes d'utilisation de la mémoire.
La mise en cache d'objet possède des caractéristiques qui en font un candidat de choix
pour la mise en œuvre en tant qu’un aspect. Certaines de ces caractéristiques sont:



Code de la mise en cache est souvent dupliqué dans une application.
Il n'est pas facile de tourner ou de désactiver la mise en cache dynamique
lorsqu’elle est une partie du logique métier.
La mise en cache n'est pas liée au domaine métier.
Le tableau suivant résume les étapes à suivre pour faire une demande d'accès aux
données avec et sans mise en œuvre d'un cache en tant qu’aspect :
Accès aux
données
Type de mise
en cache
Première
demande
Scénario 1
Scénario 2
Scénario 3
Pas de mise en œuvre mise en œuvre d'un mise en œuvre d'un cache en
d'un cache
cache traditionnel en tant qu’aspect
Récupérer les données 1. Vérifier si les
1. Intercepter l'accès aux
de la base et remettre les données disponibles données à l'aide d'un
résultats au client.
dans le cache
Pointcut.
2. Aucune
2. Utilisation des codes advice
correspondance n'est
de type around.
trouvée
3. Vérifier si les données
3. Récupérer des
disponibles dans le cache
données à partir de 4. Aucune correspondance n'est
la base
trouvée alors appeler la
4. Stocker le résultat
méthode PROCEED () qui à
dans le cache et
son tour exécute la méthode de
renvoyer les
chargement de données.
résultats au client. 5. Stocker le résultat dans le cache,
remettre le résultat au client.
Les demandes Récupérer les données 1. vérifier si elles sont
1. Intercepter l'accès aux
ultérieures
de la base à nouveau et
disponibles dans le
données à l'aide d'un
P a g e | 54
Chapitre III: La proposition
renvoyer le résultat au
client.
logique de
Aucune.
mise en cache
Non
Modifier le
code source
cache.
2. Retourner les
données trouvées
dans le cache au
client.
3. Si les données dans
le cache sont
obsolètes, récupérer
les données de
nouveau depuis la
base de données.
4. Stocker le résultat
dans le cache et le
remettre au client.
Pointcut.
2. Vérifier si les données sont
dans le cache en utilisant
les codes advice de type
around.
3. Une correspondance est
trouvée, renvoyer le
contenue du cache au
client.
Intégré dans le code Encapsulée dans un aspect.
d'application.
Oui (changements dans Non (complètement séparé du
le code d'application code de l'application. Mise en
sont nécessaires pour cache est dynamiquement tissée.
activer ou désactiver la dans l'application)
mise en cache)
Sur la base des exigences de la mise en cache comme un aspect, on fixe des objectifs
suivant :
1. Éviter de dupliquer la logique de mise en cache à chaque point d'exécution dans
l’application.
2. Écrire le code lié au cache d'une manière non intrusive, afin de ne pas affecter le
code de l’application. La logique de la mise en cache n'a rien à voir avec les
fonctionnalités de base de l'application. Elle est utilisée principalement pour des
raisons de performances.
3. La possibilité de commuter entre les scénarios de fonctionnement de l'application
avec et sans mise en cache, afin d'évaluer l'efficacité de la mise en cache dans
l'accès aux données. Si la mise en cache ne s'avère pas vraiment efficace, nous
nous sommes pas obligés de modifier le code source pour supprimer la logique de
mise en cache. Cette approche est très utile lors de la phase de test unitaire où
nous voulons tester la fonctionnalité de mise en cache avec des paramètres
différents pour arriver au meilleur scénario.
4. La flexibilité de basculer facilement ou remplacer la mise en œuvre d'un cache
avec une autre sans affecter le code d'application. Il y a beaucoup de différents
algorithmes et paramètres de configuration pour obtenir la configuration optimale
et les meilleurs résultats de la mise en œuvre d'un cache.
P a g e | 55
Chapitre III: La proposition
5. La capacité de retracer et de suivre les statistiques de mise en cache pour une
meilleure gestion des objets stockés dans le cache. Nous devons constamment
surveiller l'utilisation du cache pour déterminer son efficacité et faire les
ajustements nécessaires. En outre, comme les exigences opérationnelles et les
changements au fil du temps des fonctionnalités de l'application sont primordiaux,
nous devons nous assurer de stocker que les données fréquemment demandées
dans le cache.
Pour consolider l’application et arriver à une bonne modulation, nous avons mis en
œuvre le Patron de conception (ou pattern) Data Access Object qui permet de séparer
la couche d’accès aux données de la couche logique applicative. Son utilisation permet
de s’abstraire de la façon dont les données sont stockées au niveau des objets métier.
Utilisate
ur
Couche interface
utilisateur
Couche métier
Couche d'accès aux
Données
Données (DAO)
Application
Figure III.5 – le Patron de conception DAO
Le Data Access Object (DAO) vise à faciliter le travail avec les technologies d'accès
aux données, comme JDBC, Hibernate ou JDO d'une manière cohérente. Cela permet de
basculer entre les techniques de persistance aisément et aussi à coder sans se soucier de
la capture des exceptions qui sont spécifiques à chaque technologie.
Les opérations de base pour la persistance des données sont toutes identiques quel
que soit l’objet à sauvegarder, les méthodes en question sont celles d’un CRUD :
enregistrement (Create), lecture (Read), mise à jour (Update) et suppression (Delete). La
plupart du temps ces méthodes sont répétées et redéfinies dans chacun des DAO de
l’application, le travail repose sur les méthodes de la classe DAO pour localiser les
points de tissages (pointcut) afin d’introduire le système cache.
4 .Conclusion
Le but de ce chapitre est la présentation de la proposition. Dont nous décrivons de
façon détaillée notre approche qui consiste à utiliser les résultats d'une requête placés
dans le cache pour calculer le résultat de la requête. Cette méthode permet d'améliorer la
performance.
Notre méthode de conception repose sur l'approche orientée aspect pour
développer une architecture faiblement couplée et distribuée et d'assurer l'indépendance
entre le code lié au cache et le code métier.
Chapitre I IV: Implémentation
P a g e | 56
Chapitre
IV
Chapitre IV: Etude de cas
1. Introduction
La représentation théorique de notre approche consistait à résoudre le problème de la
gestion cohérente du contenu du cache avec le serveur, ainsi que le problème de
dispersion et d’enchevêtrer du code.
Dans cette section, nous essayons de développer un aspect de mise en cache reposant
sur Aspectj et Framework cacheonix. Ce dernier est un cache Open Source distribué. Il
permet aux organisations de développement de logiciel de gérer leurs applications métier
et de répondre à leurs besoins sur le plan de performance.
Avant de décrire notre aspect de mise en cache, nous devons écrire une classe DAO
qui encapsule les accès aux bases de données telles que la connexion JDBS, cette classe
est nommé aspect_SIO. L’intérêt de cette classe est d’abstraire au maximum des appels
techniques, qui représentent principalement la gestion des exceptions et la séquence de
connexion et de fermeture d’une session normale qui suit une exception.
Afin de valider notre solution. Nous essayons d’implémenter un logiciel de gestion
de budget d’état. Ce système permet de gérer les opérations inscrites sur les programmes
au titre des différents budgets (programme communal développement PCD, programme
sectoriel développement PSD). La figure IV.1 présente un diagramme de classe
simplifié représentant l’application.
P a g e | 57
Chapitre I IV: Implémentation
NUMERO DE L’OPERATION
REALISATEURS
Crédit paiements par chapitres
PLAN
1
CODE DE CHAPITRE
PROGRAMME
INTITULE DE CHAPITRE
FINANCEMENT
EXERCICE
CHAPITRE
PROGRAMME
ARTICLE
CP INITIAL
CODE DE GESTION
CP FINAL
INDICATIF
CONSOMMATION
Etat d’avancement du projet
MAITRE DE L’OUVRAGE
NATURE JURIDIQUE
1
1
ANNEE
N°SEQUENTIEL
N
IDENTIFICATION FISCAL
MAITRE DE L’ŒUVRE
BUDGET DE L’ETAT
OBSERVATIONS
N
NON ET PRENOM DU GERANT
DEGRE DE QUALIFICATION
N° REGISTRE DE COMMERCE
MODE DE PASSATION
INTITULE DE L’OPERATION
COMMUNE/DIRECTION
IMPACT DU PROJET
MONTANT AP INITIAL
LIBELLE DE LOTS
MONTANT AP FINAL
DELAI
CONSOMMATION
CUMULEES
UNITE
TAUX REALISATION PHYSIQUE
NOMBRE DE FOYERS BENEFICIAIRES
EMPLOIS CREES TEMPORAIRES
EMPLOIS CREES PERMANENTS
SITUATION D’OPERATION
Figure IV.1 –Diagramme de classe simplifié de l’application gestion de budget d’état
2. coupes relatives à la persistance
Le composant d’aspect de cache permet de définir les coupes liées à la persistance
ainsi que les codes advice qui y sont attachés. Nous définissons les coupes suivantes :
 Un point de jon Get_Cache désigne les points où la méthode Find_Requet de
classe ASPECT_SIO est invoquée .le code advice de type around associé à cette
coupe exécute son code avant l’exécution de la méthode Find_Requet pour
interroger le cache et voir si le résultat de la requête est disponible dans le cache
et détermine si la table a été changé. S'il ya un défaut de cache le advice utilise
proceed() pour déclencher l’exécution du point jonction.
Chapitre I IV: Implémentation
P a g e | 58
 Un coup pour sélectionner toutes les exécutions de méthode Find_joint_Requet,
qui permet de gérer une requête avec jointure, et la sauvegardé ou la
suppression d’un objet persistant.
L’extrait de code présente l’implémentation, en langage AspectJ, de l’aspect de mise en
cache
package SIO;
Import java.sql.Connection;
// Réalise la connexion et l’authentification à la BD
Import java.sql.DriverManager;
// Charge et configure le pilote de la BD
Import java.sql.PreparedStatement;
// Contient la requête SQL et la transmet à la BD
Import java.sql.ResultSet;
// Permet de parcourir les informations retournées par la BD
Import java.sql.SQLException;
// Gestion des erreurs SQL
Import java.sql.Timestamp;
Import java.text.SimpleDateFormat;
Import java.util.ArrayList;
Import java.util.Date;
Import java.util.Iterator;
Import java.util.List;
Import cacheonix.Cacheonix;
/**
Cacheonix Framework fournit
Import cacheonix.cache.Cache;
des fonctionnalités de mise en cache **/
public aspect aspect_Cache_modifie {
pointcut Get_Cache( String dat , String query): args ( dat , query)&&(execution(* aspect_SIO.Find_table(..)));
pointcut Get_Cache( String dat , String query ): args (dat , query)&&(execution(* aspect_SIO. Find_Requet
(..)));
/** Code advice pour mise en cache. */
Resuqute_resulta around (String dat, String query): Get_Cache (dat , query ) {
if(Activer_cahe) /** verifier si le cache est activé */
{
/** Déclaration de variables */
/**Obtenir le résultat du cache */
final Cache<key_requete, resuqute_resulta> queryCache =
cacheonix.getInstance().getCache("ASPECT_PERSISTANCE");
final key_requete queryKey = new key_requete(query, queryParameters);
queryResult =(resuqute_resulta) queryCache.get(queryKey);
if (queryResult!= null ) /** verifier si le resultat en cache */
{
/** Le résultat de la requête est en cache */
/** Chercher le temps de dernière modification de la table
* et comparer avec le temps de conserver le résultat d'une requête en cache. */
if (résultat du cache est modifié) /** vérifie si un cache de résultat valide*/
{
P a g e | 59
Chapitre I IV: Implémentation
/**le résultat dans le cache mais avec une modification sur la table */
/** calculer le résultat de la requête par la fusion de la réponse mise en cache
/* * avec la réponse calculée à partir de la table temporaire */
long stop = System.currentTimeMillis();
\** le délai de traitement
System.out.print ("\n délai de traitement : "+ (stop – start )+"" );
de la requite*/
}
e ls e {
/**Le résultat dans le cache mais sans modification faite sur une table */
}
return queryResult;
}
/** Le résultat de la requête n'est pas mis en cache
* proceed permet l'exécution du point jonction (méthode ASPECT_SIO) */
queryResult = proceed ( dat,query); /* Calculer le résultat par le point de jonction */
queryCache.put (queryKey, queryResult);
/** mettre le résultat en cache */
long stop = System.currentTimeMillis();
System.out.print ("\n time final : "+ (stop - start )+"" );
return queryResult;
}
}
\** le délai de traitement
de la requite*/
Cet extrait de code, est une partie de l’aspect (aspect_cache_modifié), qui déclare
qu’un advice est invoqué avant et après chaque exécution de la méthode Find_Requet
(* aspect_SIO. Find_Requet (..)) De la classe aspect_SIO, l’aspect
(aspect_cache_modifié) déclare un greffon de type around. L’instruction proceed
permet de revenir à l’exécution du programme, autrement dit l’exécution du point
jonction. En premier lieu, le code advice vérifie si un cache de résultat valide est
disponible en mémoire. S’il est, le résultat est récupéré du cache directement. Par contre,
si le résultat de la requête est disponible dans le cache mais non valide, le résultat est
calculé suivant notre proposition. Si le résultat n'est pas disponible, la requête est
exécutée normalement. Puis la réponse est adressée au client. Après l’exécution du point
de jonction, le résultat est sauvegardé en cache, et finalement l’exécution du programme
reprend juste après le point de jonction.
A cet effet, nous pouvons constater que cette application est complètement
indépendante du code de mise en cache.
P a g e | 60
Chapitre I IV: Implémentation
3. Résultats du test
Le résultat produit par l’exécution de cette application avec cache et sans cache, ainsi
après la modification dans les tables de la base de données.
Première demande
Les demandes ultérieures
Les demandes ultérieures
(après modification dans
les tables)
Sans mise en cache
(ms)
Avec la mise en cache
(ms
587
571
530
657
31
35
Nous avons observé la rapidité d'accès aux données dû à l’utilisation d’un cache pour
stocker les requêtes fréquemment utilisées. Il a fallu peu de temps pour obtenir des
données mises en cache, par rapport au temps qu’il dispose pour l'obtenir à partir d’une
base de données (31 millisecondes avec mise en cache par rapport à 571 millisecondes
sans mise en cache). Suite à notre proposition, nous avons constaté dans le cas où une
table d'une base de données a été modifiée par une requête d’insertion, le délai entre une
requête d'un client et la réponse du serveur est court. Un avantage d'utiliser un aspect
par rapport à la programmation traditionnelle orientée objet, c’est que l'ajout ou le retrait
de l'aspect peut être parfaitement fait sans aucun impact sur le code d'application.
Un outil tel qu’Aspect browser permet d'analyser le phénomène de dispersion du
code. En fournissant une vue graphique la Figure IV.2 montre ce phénomène avant et
après la mise en cache comme un aspect, les rectangles verticaux symbolisent les classes
de notre application, et les traits les lignes de code utilisant L'API de gestion de cache,
comme nous le constatons, les traces sont utilisées à nombreux endroits. La
fonctionnalité de gestion de cache est entièrement dispersée.
Figure IV.2 – Dispersion du code de mise en cache
Chapitre I IV: Implémentation
P a g e | 61
Par contre, la Figure IV.3 montre que l'appel à l'API de cache est regroupé dans un
aspect, est donc bien assurer la maintenance et à l'évolutivité d'application.
Nous avons atteint nos objectifs suivant :
 Une architecture faiblement couplée.
 La séparation de la logique.
 L’optimisation des performances d'accès aux données.
Figure IV.3 – Impact d’un aspect sur la localisation du code de cache
4. Conclusion et perspectives
Dans ce mémoire, nous nous sommes intéressés à l'introduction de la persistance dans
un langage orientés aspect. En particulier, l’objectif et d’aborder les problèmes de
gestion de la cohérence du contenu de cache avec le serveur, à l’aide des technologies
orientés aspect. Aussi de trouver une meilleure structuration des programmes,
notamment au travers de l’encapsulation et de la séparation des préoccupations
transversales au découpage des applications en termes de classes
La programmation orientée aspect est un nouveau paradigme qui permet la
production d ‘un code métier découplé du code non-fonctionnel. C’est une solution aux
problèmes de mélange et de dispersion du code des propriétés non fonctionnelles
rencontrés avec la programmation par objets, elle consiste à séparer et découpler leurs
définitions comme le veut le principe de la séparation des préoccupations dans le but de
permettre une meilleure réutilisation.
Deux sortes de perspectives sont envisageables après un travail comme celui-ci. Les
premières concernent la gestion du cache. Les solutions habituellement utilisées sur la
base d’une gestion statique par tuples ou pages, c'est-à-dire on stocke des données qui
sont plus proches de la réponse d’une requête en termes de localité dans la base de
données. On peut réaliser une gestion pareille suivant des solutions qui reposent sur les
Chapitre I IV: Implémentation
P a g e | 62
sémantiques. L’autre classe de perspectives est de créer un système de mise en cache
pour pouvoir fonctionner et réagir de manière autonome aux changements de son
environnement. Ainsi, il convient d’étendre les travaux sur la gestion de caches à la
gestion de l’environnement d’exécution, Afin d’assurer une bonne qualité de service.
Référence bibliographique
P a g e | 63
Référence bibliographique
[1]:D. L. Parnas. “On the Criteria for Decomposing Systems into modules". Communication of the
ACM, 15(12) pp: 1053-1058, Decembre 1972.
[2]: M.P. Atkinson, P. Bailey, K.J. Chisholm, W.P. Cockshott, R. Morrison, “An approach to
persistent programming”, the computer journal, Vol. 26 N°4, November 1983, pp. 360-365, also in
[3] pp. 141-146.
[3]: S.B. Zdonik, D. Maier, “readings in object-oriented database systems”, eds. S.B. Zdonik and D.
Maier, 1990.
[4]: M.P. Atkinson,”Persistent architectures”, proc. third international workshop on persistent
object systems, eds. J. Rosenberg and D. Koch, Newcastle, Australia, January 1989.
[5]: M. Atkinson, “Questioning persistent types”, proc. of the 2nd workshop on database
programming languages, eds R. Hull, R. Morrison, D. Stemple, Morgan Kaufmann publishers Inc.,
1989, pp. 2-24.
[06] : Guillaume Dufrêne, Simon Morvan, ”La programmation Orientée Aspects AspectJ et
JAC”.
[07] : Antoine MAROT,” L’animation d’algorithmes en programmation orientée aspect” 2006.
[08] : Ferut Térence, Leroy Sébastien,” La programmation Orientée Aspects”, Juin 2004.
[09] : S. Soares, E. Laureano, and P. Borba. “Implementing distribution and persistence aspects
with aspect”. In OOPSLA '02: Proceedings of the annual ACM SIG-PLAN conference on Object
oriented programming, systems, languages, and applications, pages 174-190, Seattle, Washington,
USA, November 2002. ACM Press.
[10]: E. Gamma, R. Helm, R. Johnson, and J. Vlissides. “Design Patterns: Elements of Reusable
Object-Oriented Software”. Addison-Wesley, 1994. ISBN 0-20163- 361-2.
[11]: SUN. Java Object Serialization
Specification. Sun Microsystems, Inc., 2006b. URL
http://java.sun.com./javase/6/docs/technotes/guides/serializeation /index.html.
[12]: A. Rashid and R. Chitchyan.” Persistence as an aspect”. In AOSD '03: Proceedings of the
International Conference on Aspect-Oriented Software Development, pages 120-129, Boston, MA,
USA, March 2003. ACM Press.
[13]: R. Pawlak, L. Seinturier, L. Duchien, G. Florin, F. Legond-Aubry, and L. Martelli.
Jac: “an aspect-based distributed dynamic framework”. Software - Practice and Experience (SPE),
34(12):1119-1148, 2004.
[14]: K. Yagoub, D. Florescu, V. Issarny, and P. Valduriez. “Caching strategies for data-intensive
web sites”. In Proceedings of the 26th International Conference on Very Large Databases, pages
188–199, Sept. 2000.
Référence bibliographique
P a g e | 64
[15]: J. Challenger, A. Iyengar, and P. Dantzig. “A scalable system for consistently caching
dynamic web data”. In Proceedings of IEEE INFOCOM’99, pages 294–303, Mar. 1999.
[16]: A. Iyengar and J. Challenger. “Improving web server performance by caching dynamic data”.
Dec. 1997.
[17] : Renaud pawlak, jean-philippe Retaillé, lionel seinturier, Programmation orientée aspect pour
Java/J2EE , 2004.
[18] : Thibaut Schorderet, thèse :”Compiere Installation et adaptation avec Hibernate ”, Septembre
2005.
[19]: E. Krasner, P. Glenn, and T. Stephen. “A cookbook for using the model-view controller user
interface paradigm in smalltalk-80”. Journal of Object-Oriented Programming, 3(1): 26–49, 1988.
[20] Denanot, Laurent. «Maîtriser la persistance objet métierau sein d’une architecture J2EE.» avril
2003.
[21] : Allouch Bachir, Trantoul Gilles, “Les nouvelles formes de programmation“, juin 2003
[22] : Thomas GIL, “ la Conception Orientée Aspects 2.1 ”, 21 janvier 2006.
[23] : Hondjack DEHAINSALA, thèse :” Explicitation de la sémantique dans les bases de données :
Base de données à base ontologique et le modèle OntoDB ”, Avril 2002.
[24] : Laurent D’ORAZIO, thèse :” Caches adaptables et applications aux systèmes de gestion de
données répartis à grande échelle”, décembre 2007.
[25]: K. Mens, C. Lopes, B. Tekinerdogan, and G. Kiczales. “Aspect-oriented programming
workshop report. In ECOOP Workshops”, volume 1357 of LNCS, pages 483{496, Jyvaskyla,
Finland, June 1997. Springer-Verlag.
[26]: A. Rashid. On to aspect persistence. In GCSE " International Symposium on Generative and
Component-Based Software Engineering ” , volume 2177 of Lecture Notes in Computer Science,
pages 26-36, Erfurt, Germany, October 2000. Springer.
[27] : Assia AIT ALI SLIMANE, Muhammad Usman BHATTI, ” Utilisation des services et des
aspects pour la réutilisabilité du logiciel d’un automate pour l’analyse de plasma”.
[28] : NGUYEN Manh Tien, Programmation Orientée Aspect, Juillet 2005.
[29] : François EXERTIER, thèse :” Extension orientée objet d’un SGBD relationnel ”, décembre
1991.
[30] : Ouafa Hachani, thèse :”Patrons de conception a base d’aspects pour l’ingénierie des systèmes
d’information par réutilisation ”,2006.
[31] : Sébastien Ros : ”Livre blanc sur le Mapping objet-relationnel, la couche d’accès aux données
et les Frameworks de persistance ”, Février 2003.
Référence bibliographique
P a g e | 65
[32]: G. Kiczales, E. Hilsdale, J. Hugunin, M. Kersten, J. Palm et W.G. Griswold ’’An Overview of
AspectJ”. In Proceedings of ECOOP 2001, European Conference on Object- Oriented
Programming, Budapest, Hungary, LNCS, vol. 2072, Springer, pp. 327-353, 2001.
[33] : Sophie LEVY,” Programmation on Orientée Aspect avec Aspectj ” , Février 2006.
[34] : W. Rahayu, E. Chang, and T. Dillon. “A methodology for the design of relational databases
from object-oriented conceptual models incorporating collection types “. In 18th Internat. Conf. on
Technology of Object-oriented Languages and Systems. Prentice-Hall, 1995.
[35]: W. Rahayu, E. Chang, T. Chang, and D. Taniar. “Aggregation versus association in object
modelling and databases ”. In Australian Conf. on Information Systems, 1996.
[36]:W. Rahayu, E. Chang, and T. Dillon. “Implementation of object-oriented association
relationships in relational databases ”. In IDEAS, pages 254–263, 1998.
[37]: W. Rahayu, E. Chang, and T. Dillon.” Representation of multi-level composite objects in
relational databases”. In Internat. Conf. on Object-oriented Information Systems OOIS’98.
Springer, 1998.
[38]: C. Soutou. “Modeling relationships in objectrelational databases ”. Data and Knowledge
Engineering, 36(1):79–107, 2001.
[39]: http://en.wikipedia.org/wiki/Aspect-oriented_software_development
[40]: P. Eric, J. Rahayu, and D. Taniar. “Mapping methods and query for aggregation and
association in object-relational database using collection”. In ITCC ’04: Proceedings of the
International Conference on Information Technology: Coding and Computing (ITCC’04) Volume
2, pages 539–543. IEEE Computer Society, 2004.
Téléchargement