Télécharger le fichier pdf d’un mémoire de fin d’études
Evaluation des implémentations des patrons de conception
Les patrons de conception sont considérés très importants et utiles pour la réutilisation et l’évolution des logiciels. Malheureusement, leur implémentation sous le paradigme orienté objets n’est pas toujours convenable, cela est dû à la nature et aux limites de ce paradigme. Dans la suite, on cite quelques problèmes.
Problème de Confusion
La représentation d’un patron sous forme de classes rend la partie relative au patron et les autres parties de l’application fortement liées. Dans ce cas, il est difficile de distinguer le comportement relatif au patron des comportements relatifs aux autres classes sur lequel il a été appliqué. Cela réduit la traçabilité, la réutilisation du patron et rend difficile la maintien des patrons une fois le système conçu.
Problème de redirection
Différents patrons de conception utilisent le mécanisme de la redirection explicite afin d’activer leurs comportements spécifiés dans d’autres classes du système. Par conséquent, cela minimise la compréhension du code, sa flexibilité et augmente le taux de communication entre les objets.
Problème de rupture d’encapsulation
L’implémentation des patrons de conception à plusieurs effets habituellement indésirables, cela est dû à la possibilité offerte aux patrons de modifier la structure des systèmes, surtout quand le comportement du patron nécessite d’accéder à certains attributs dans d’autres classes. Ceci implique une violation des droits d’accès à cet attribut, donc, violation du mécanisme de l’encapsulation.
Problème lié a l’héritage
L’intégration d’un patron dans la hiérarchie d’un système orienté objet, nécessite, dans la plupart des cas, l’utilisation du mécanisme de l’héritage ce qui implique une forte liaison entre le patron et le reste du système. Par conséquent, le taux de la réutilisation est réduit. Dans certains cas, l’intégration du patron devient impossible. Par exemple, lors de l’utilisation des modèles d’implémentation qui ne supportent pas le concept d’héritage multiple (comme Java), l’intégration est problématique.
Problème de composition des patrons
Si des plusieurs patrons sont utilisés dans le même système, il devient difficile de garder la trace de l’exécution d’un patron particulier. Cela est particulièrement le cas si les mêmes classes sont impliquées dans plus d’un patron.
Problème de violation des concepts de l’orienté objets
Quelques patrons de conception préconisent de changer le comportement de certaines classes ce qui viole certains principes du paradigme orienté objets
8 Une Evaluation Qualitative et Quantitative des approches de Séparation des préoccupations basée sur les patrons de conception et leur utilisation pour l’intelligence artificielle et les systèmes multi-agents comme l’héritage et les modificateurs d’accès.
La séparation avancée des préoccupations
Les applications d’aujourd’hui contiennent plusieurs préoccupations comme la sécurité, la persistance et la synchronisation. Les problèmes les plus importants qui se produisent dans le développement des logiciels sous le paradigme orienté objets sont : l’enchevêtrement et la dispersion de code source des préoccupations. Le premier se produit quand plus d’une préoccupation sont utilisées dans la même application, ce qui complique la compréhensibilité du code source résultat et diminue le taux de son réutilisation. Alors que, le deuxième se produit quand le code de la préoccupation n’est pas centralisé et qu’il est impossible de l’encapsuler dans une seule entité.
L’enchevêtrement et la dispersion du code source affectent le processus du développement des logiciels de différentes manières: mauvaise traçabilité, manque de productivité, peu de réutilisation, difficulté de l’évolution et de la maintenance, etc. Afin de résoudre ces problèmes, plusieurs techniques sont actuellement considérées, elles tentent d’augmenter le taux d’expression de l’approche orientée objets. Ces techniques sont connues sous l’appellation : Approches Avancées de Séparation des Préoccupations. Parmi ces approches on peut citer : la programmation orientée aspects, les filtres de composition et la séparation multidimensionnelle des préoccupations.
La séparation des préoccupations est un concept clé en génie logiciel. Il fait référence à la capacité d’identifier, d’encapsuler, et de manipuler, indépendamment, des parties d’un logiciel relatives à une préoccupation particulière. L’utilisation des préoccupations a comme motivation fondamentale l’organisation et la décomposition des logiciels en parties maniables et compréhensibles.
Les préoccupations comme la persistance et la synchronisation sont commun. Une séparation des préoccupations appropriée est nécessaire afin de réduire la complexité du logiciel et d’améliorer la compréhensibilité de son code, augmenter la traçabilité, faciliter la réutilisation, l’adaptation et la maintenance et simplifier l’intégration d’autres composants dans les logiciels.
Cette partie du chapitre présente les concepts principaux de chaque approche ASOC: AOP, CF et Hyperespaces, qui seront utilisés dans le chapitre suivants. Le détail de ces approches est donné en annexe 2 sous forme d’une présentation des aspects syntaxiques et sémantiques des langages d’implémentation de ces approches, un pour chaque approche: AspectJ pour AOP, ConcernJ pour CF et Hyper/J pour Hyperespaces.
La programmation orientée aspects (AOP)
La programmation orientée aspects ou AOP, apporte une solution élégante et simple pour le problème de séparation des préoccupations. C’est une technique de programmation qui permet, dans un premier lieu, d’implémenter chaque préoccupation sous forme d’un module appelé aspect. L’ensemble des aspects
Une Evaluation Qualitative et Quantitative des approches de Séparation des préoccupations basée sur les patrons de 9 conception et leur utilisation pour l’intelligence artificielle et les systèmes multi-agents présente une caractéristique importante : celle de leur indépendance mutuelle, ce qui les rend hautement réutilisables. Dans un second lieu, les différents aspects sont combinés avec les classes, représentant les fonctionnalités de base de l’application, selon des règles bien définies. Cette combinaison est faite par un outil spécifique dit tisseur (i.e. Weaver en anglais).
Ce nouveau paradigme propose une restructuration des applications sur la base du concept d’aspect. Un aspect est une particule de l’application qui représente totalement et exclusivement une propriété donnée de l’application. Un aspect se définit comme une préoccupation qui est classiquement dispersé parmi les autres composantes d’un logiciel.
La programmation par aspects est une technique qui permet d’exprimer clairement les programmes qui sont liées à de tels aspects, les encapsule et les isole. En tant que technique de séparation de préoccupations, le but principal de l’AOP est de :
1. Séparer précisément les aspects du code de base de l’application
2. Indiquer comment l’aspect est intégré à l’application
Une fois que le programmeur aura écrit le code source de son application et spécifié ses aspects, il utilise le tisseur (i.e. Weaver) pour les fusionner. Il est à noter que la programmation orientée aspect est indépendante de la programmation orientée objets ; en effet, il est possible d’utiliser la programmation par aspects conjointement à d’autres paradigmes de programmation.
Le but de l’AOP est de rendre le code d’une application plus modulaire, en séparant le code d’une application en deux parties, une partie fonctionnelle qui représente le corps de l’application elle-même et une partie non fonctionnelle qui représente le code des préoccupations. Cela signifie que les préoccupations sont totalement localisées plutôt qu’éparpillées [35, 65, 67, 71, 85, 89, 90, 92]. Depuis la présentation de la technique d’AOP en 1997, l’essentiel des travaux conduits dans ce domaine consiste à développer des tisseurs pour des préoccupations diverses. En particulier, en 1998 AspectJ est mis à la disposition des utilisateurs par les chercheurs du centre de recherche PARC de Xerox.
AspectJ est une extension générique compatible de Java qui étend celui-ci par des concepts afin d’obtenir un langage orienté aspect [34, 83, 84].
AOP étend le modèle objet ordinaire par les cinq nouveaux concepts suivants:
Les aspects
L’aspect est une entité qui ressemble à une classe mais modélise une préoccupation qui entrecoupe plusieurs classes. Les aspects sont définis séparément et plusieurs aspects peuvent exister dans un même système.
Les points de jointure
Une application contient plusieurs points pertinents où plusieurs événements peuvent se produire. Ces points sont appelées points de jointure, parmi ces points on peut cité: l’instanciation d’un objet, l’invocation et exécution d’une méthode, l’accès en lecture ou en écriture à une variable d’instance, etc.
Les points de coupure
Ils sont des formes particulières de prédicats qui utilisent des opérateurs booléens et des primitives spécifiques pour capturer un ou plusieurs points de jointure.
Consignes (Advices)
Des événements spécifiques peuvent être capturés et des actions peuvent être appliquées dès que ces points sont atteints. Ces actions sont appelées consignes. Elles sont semblables aux méthodes. Le code d’une consigne est exécuté quand un point de jointure d’un point de coupure spécifique est capturé.
AspectJ supporte trois genres de consignes. Le genre de consigne détermine comment l’aspect réagit faces aux points de jointures. AspectJ divise les consignes en trois catégories selon qu’elles s’exécutent avant, après ou autour des points de jointure.
Les consignes avant. Une consigne avant (before advice) doit être exécutée avant le code qui a produit l’événement. Par exemple quand une exécution d’une méthode est capturée, le code de la consigne sera exécuté puis la méthode peut continuer son exécution normalement.
L’aspect sémantique des filtres
Il existe différents types de filtres et à chaque type il est associé une spécification propre qui lui permet de déterminer les actions qui doivent être effectuées pour un message particulier. En général il existe cinq types de filtres:
• Dispatch. Quand le message est accepté, le filtre décide vers quel objet doit être redirigé ce message, par contre, si le message est rejeté le message passe au filtre suivant. Ce type de filtre fournit au modèle CF des techniques d’abstractions des données comme l’héritage simple, multiple et dynamique ainsi que la délégation.
• Error. Quand le message est accepté par un filtre, il lui permet de continuer vers le filtre suivant, sinon, le message doit être bloqué ; ce type de filtres fournit au modèle CF les techniques de contrôle multiples et des pré-conditions.
• Wait. Quand le message est accepté il passe au filtre suivant, sinon, l’objet CF le mette dans la queue d’une file d’attente jusqu’à la satisfaction des conditions qui le bloquent.
• Meta. Quand un message est rejeté par un filtre, il passe au filtre suivant, sinon, il le doit être réifié d’abord et envoyé à un autre objet pour le manipuler.
• Substitute. Quand un message est accepté, sa cible ou/et son sélecteur doit être substitué par d’autre valeurs, dans le cas contraire le message est passé au filtre suivant.
Le mécanisme de la superimposition
La superimposition est une technique qui consiste à adjoindre systématiquement de nouveaux comportements à un objet à des endroits spécifiques.
Quatre concepts clés qui doivent être pris en considération pour satisfaire la superimposition :
• Qui. Le module du système qui sera superimposé
• Quoi. Le nouveau comportement à superimposé
• Où. Les endroits où le nouveau comportement sera superimposé
• Quand. Le moment dans lequel la superimposition doit être accomplie.
La séparation multidimensionnelle des préoccupations
Bien que l’appellation « séparation des préoccupations », soit peu utilisée, la notion sous-jacente a toujours été au coeur du génie logiciel, et tous les développeurs l’utilisent, parfois sans le savoir. En fait les développeurs procèdent souvent à cette séparation lorsqu’ils identifient, encapsulent et manipulent des parties pertinentes d’un logiciel. Les préoccupations permettent d’organiser et de décomposer le logiciel en des parties qui sont manipulables et compréhensibles.
Plusieurs types de préoccupations peuvent être identifiés, ceci dépend du développeur, leur rôle, ou une étape du cycle de vie du logiciel. Par exemple, dans le cas de la programmation orientée objet, le type de préoccupation utilisé est la classe, chaque préoccupation de ce type est un type de données défini et encapsulé par une classe.
On peut, bien entendu, identifier d’autres types de préoccupations, comme par exemple : des caractéristiques d’impression, de gestion de bases de données, des règles du marketing, de distribution et beaucoup d’autres selon le domaine d’application. On appelle un type de préoccupations comme les classes, ou tout autre type, une « dimension de préoccupation », et la séparation des conception et leur utilisation pour l’intelligence artificielle et les systèmes multi-agents préoccupations consiste à la décomposition du logiciel en une ou plusieurs dimensions de préoccupations.
Une bonne séparation de préoccupations peut aider à :
• réduire la complexité du logiciel et le rendre plus compréhensible.
• limiter l’impact des changements, facilitant ainsi l’évolution et une adaptation non envahissante
• faciliter la réutilisation.
• simplifier l’intégration de nouveaux composants.
Ces buts, malgré leur importance, n’ont toujours pas été atteints en pratique. Ceci est dû principalement au fait que l’ensemble des préoccupations pertinentes change avec le temps et peut être influencé par plusieurs facteurs tels que : la diversité des activités de développement ou les étapes du cycle de vie du logiciel.
La décomposition en une seule dimension peut promouvoir quelques ambitions, mais elle peut aussi être un obstacle pour d’autres; ainsi, chaque critère de décomposition ou d’intégration sera approprié pour quelques spécifications mais pas pour la totalité. Par exemple la décomposition par classe dans le cas de l’orientée objet facilite beaucoup l’évolutions des détails de la structure de données parce qu’ils seront encapsulés dans des classes, mais rend difficile l’addition et l’évolution des variables d’instance et des méthodes, puisque celles-ci peuvent exister dans plusieurs classes et peuvent être liées les unes aux autres.
Hyperespace (Hyperespaces en anglais) est une approche qui permet une identification explicite de chaque dimension et chaque préoccupation, à n’importe quel étape du développement, l’encapsulation de ces préoccupations, la gestion des relations entre ces préoccupations et leur intégration.
Dans cette approche, l’accent est mis sur 4 concepts principaux:
• préoccupation, (Cocnern)
• hyperespace, (Hyperspace)
• Hyper-module, (Hypermodule)
• Hyper-tranche, (Hyperslice)
Cette méthode est le fruit du travail du laboratoire alphaworks d’IBM, qui ont sorti leur produit Hyper/J qui implémente l’approche hyperespace pour le langage Java, et entre aussi dans le cadre de la suite des travaux commencés sur les méthodes orientées sujet (Subject Oriented Programming) du même laboratoire.
La figure 2.8 illustre l’approche hyperespace, nous expliquons les différents concepts juste après.
L’espace des préoccupations
Le logiciel est composé de plusieurs parties qui sont formulées dans un certain langage. Une unité est une construction syntaxique dérivée d’un tel langage. Elle peut être, par exemple, une méthode, une variable d’instance, une procédure, une fonction, une règle, une classe, une interface, etc. Cependant, on distingue des unités simples qui sont considérées comme étant atomiques, et des unités composées qui sont des regroupements d’unités simples. Ainsi les méthodes, les variables d’instance, les fonctions sont toutes des unités simples tandis que les classes, et les paquets sont des unités composées.
L’espace des préoccupations renferme toutes les unités dans une partie du logiciel, et son rôle est d’organiser les unités de manière à séparer les préoccupations cruciales, décrire plusieurs types de relations, et indiquer comment les systèmes et les composants du logiciel peuvent être construits et intégrés à partir des unités contenues dans ces préoccupations.
Le processus de la séparation multidimensionnelle de préoccupations comprend trois étapes importantes :
• Identification. C’est le processus de sélection de préoccupations ainsi que les unités que renferment ces préoccupations.
• Encapsulation. L’identification est utile, mais pour réaliser entièrement les avantages de la séparation des préoccupations, celles-ci doivent également être encapsulés de sorte à ce qu’elles puissent être manipulées en tant qu’entités de première classe. Une classe Java est un exemple d’une préoccupation encapsulée.
• Intégration. Une fois les préoccupations encapsulées, on doit pouvoir les intégrer pour créer un logiciel capable de manipuler plusieurs préoccupations. Dans Java, les classes sont intégrées en les chargeant. Les préoccupations autres que les classes et les interfaces ne peuvent être intégrées dans Java.
Identification de préoccupations (La matrice des préoccupations)
Un hyperespace est un espace de préoccupations spécialement conçu pour supporter la séparation multidimensionnelle de préoccupations. Ses unités sont organisées dans une matrice multidimensionnelle, chacun de ses axes représente une dimension de préoccupations, et chaque point dans un axe, une préoccupation dans cette dimension. Ceci rend explicite l’identification de toutes les dimensions d’intérêt, les préoccupations qui appartiennent à chaque dimension, et quelles préoccupations sont affectées par quelles unités. Les coordonnées d’une unité indiquent toutes les préoccupations qu’elle affecte; et cette structure montre bien que chaque unités affecte au plus une seule préoccupation pour une dimension donnée.
Chaque dimension, peut être aperçue ainsi comme une partition de l’ensemble de toutes les unités (i.e. l’espace des préoccupations) : une décomposition particulière du logiciel. Chaque préoccupation dans une dimension définit un
« hyperplan » qui contient toutes les unités qui affectent cette préoccupation. La structure de la matrice permet un traitement uniforme de tous les types de préoccupations, et permet aux développeurs de manipuler et de trancher à travers la matrice selon les préoccupations désirées.
Il peut arriver qu’une ou plusieurs unités n’appartiennent à aucune préoccupation, l’approche hyperespace a prévue pour cela une préoccupation appelée none pour chaque dimension, qui renferme toutes les unités qui appartiennent à l’espace des unités, mais qui n’affectent aucune préoccupation de cette dimension, donc la préoccupation none contient généralement les unités qui ne présentent aucun intérêt dans une dimension donnée.
Encapsulation des préoccupations (Les Hyper-tranches)
La matrice des préoccupations identifie les préoccupations et organise les unités selon les dimensions et les préoccupations, mais elle ne permet pas l’encapsulation de ces dernières, c’est à dire que les ensembles d’unités résultants ne peuvent pas être traités comme des modules, sans un mécanisme additionnel. Dans l’approche hyperespace, ce mécanisme est appelé hyper tranche (hyperslice) [40] qui est un ensemble de préoccupations « complets en déclaration», ce qui veut dire qu’elles déclarent tout ce à quoi elles font référence.
Les unités sont souvent reliées entre elles de différentes manières, une méthode peut invoquer une autre ou peut utiliser une variable d’instance, et quand ce genre de relations existe un fort couplage en résulte. La complétude déclarative est une propriété des hyper-tranches qui a pour but d’éliminer ce fort couplage qui peut exister entre différentes hyper-tranches [40]. La complétude déclarative inclut que chaque hyper-tranche doit au minimum déclarer chaque méthode que ces unités membres invoquent, et chaque variable que ces membres utilisent, une définition complète n’est pas requise pour ces déclarations, par exemple, on peut déclarer des méthode sans les implémenter, ainsi cette déclaration peut être abstraite.
Intégration des préoccupations (Les Hyper-Modules)
Les hyper-tranches construisent des blocs, qui peuvent être intégrés pour former d’autres blocs. Ceci est fait par des relations d’intégration. Il arrive parfois qu’on soit ramené à utiliser une hyper-tranche qui a quelques déclarations abstraites, et qu’on utilise une autre hyper-tranche qui contient l’implémentation complète de ces déclarations, et en profiter pour implémenter tout ce qui a été déclaré abstrait. Ce genre de relations s’appelle la correspondance. Dans un hyperespace, ce contexte d’intégration s’appelle hyper-module.
Un hyper-module est donc un ensemble de hyper-tranches qui vont être intégrées, et des relations d’intégration qui spécifient la manière dont les hyper-tranches doivent être intégrées. La correspondance est une relation d’intégration très importante qui indique quelles unités des différentes hyper-tranches vont être intégrées. D’autres détails peuvent être précisés, comme par exemple, si deux méthodes correspondent, est ce que l’une doit couvrir l’autre, ou est ce qu’elles doivent être exécutées ensembles, et si c’est le cas dans quel ordre ? Comment la valeur de retour sera t-elle calculée?
Il existe en pratique, des outils qui permettent de réaliser l’intégration selon les relations d’intégration précédemment décrites, donc on peut procéder à la production d’un ensemble d’unités intégrées. Cet ensemble sera bien entendu complet en déclaration et pourra être considéré comme une hyper-tranche
composée, obtenu par l’intégration de nombreuses hyper-tranches subordonnées, ce qui permet à de grands systèmes, complets, d’être construits en partant d’un ensemble de plusieurs hyper-tranches et de relations d’intégrations successives.
La complétude déclarative, la correspondance et les relations d’intégration sont des caractéristiques qui peuvent promouvoir l’évolution d’un système logiciel [40], et puisqu’une hyper-tranche ne dépend pas d’une autre directement, les différents artifices sont sujet à une contrainte de complétude dans laquelle chaque définition d’une unité doit correspondre à, soit une ou plusieurs définition(s), éventuellement abstraite(s), soit à une ou plusieurs implémentation(s) appartenant à une ou plusieurs hyper-tranche(s). Changer une définition ou une implémentation devient alors non envahissant, la correspondance nous procure une certaine flexibilité et supporte directement la substitution des unités au sein d’une ou plusieurs hyper-tranche(s).
Mise en Oeuvre des Patrons de Conception en CF
L’approche de composition de filtres est une extension modulaire aux langages objets tel que Java [51], C++ [68] et Smalltalk [94]. Vu que toutes les interactions du système objets sont faites en envoyant des messages, la manipulation des messages reçus sont à la charge de l’objet ce qui complique extrêmement le comportement de ce dernier. Pour séparer la manipulation des messages reçus du comportement de l’objet, une couche extérieure appelée interface, qui enveloppe l’objet, a été mise en œuvre.
Dans cette section, nous entreprenons la description de nos trois patrons de conception choisis en utilisant le modèle CF qui est considéré l’une des meilleures stratégies proposées par la communauté ASOC. Cette description de la mise en oeuvre des patrons a été présentée par une extension au diagramme de classe d’UML, cette extension est basée sur les règles suivantes:
Le rectangle jaune avec le stéréotype « Concern » représente une spécification de la préoccupation.
La partie noyau sera présentée par un rectangle blanc.
Une Boîte bleue avec flèches entrant et sortant corresponde un ensemble de filtres d’entrée.
La croix blanche dans la préoccupation symbolise la spécification de la superposition qui dénote un ensemble d’objets où l’interface des filtres est insérée.
Les lignes rouges interrompues indiquent le processus de superimposition.
|
Table des matières
Chapitre I. Introduction
1. Objectifs
2. Motivation
3. Contexte
4. Structure de la thèse
Chapitre II. Les Patrons de Conceptions, La Séparation des Préoccupations et les Systèmes Multi-Agents
1. La philosophie des patrons
1.1. La forme d’un patron
1.2. La classification des patrons de conception
1.3. Evaluation des implémentations des patrons de conception
2. La séparation avancée des préoccupations
2.1. La programmation orientée aspects (AOP)
2.1 .1. Les aspects
2.1 .2. Les points de jointure
2.1 .3. Les points de coupure
2.1 .4. Les consignes (Advices)
2.1 .5. Les introductions
2.2. La Composition de Filtres (CF)
2.2 .1. La partie noyau
2.2 .2. La partie interface
2.2 .3. L’aspect sémantique des filtres
2.2 .4. Le mécanisme de la superimposition
2.3. La séparation multidimensionnelle des préoccupations
2.3 .1. L’espace des préoccupations
2.3 .2. Identification de préoccupations
2.3 .3. Encapsualtion des préoccupations
2.3 .4. Intégration des préoccupations
2.4. Les Syatèmes Multi-Agents
3. Conclusion
Chapitre III. L’implementing des patrons de conception par les approches ASOC
1. Mise en oeuvre des patrons de conception en AOP
1.1. Le patron Adapter
1.2. Le patron Chain Of Responsibility
1.3. Le patron Singleton
2. Mise en oeuvre des patrons de conception en CF
2.1. Le patron Adapter
2.2. Le patron Chain Of Responsibility
2.3. Le patron Singleton
3. Les patrons de conception dans l’approche Hyperespace
3.1. Le patron Adapter
3.2. Le patron Chain Of responsibility
3.3. Le patron Singleton
4. Conclusion
Chapitre IV. ASOC: Une étude Comparative basée sur les patrons de conception
1. Le Mapping des Concepts
2. Comparaison basée sur les patrons de conception
2.1. Etude Qualitative
2.2. Discussion
2.3. Etude Quantative
2.3.1. Les métriques intervenant au moment de la compilation
2.3.2. Les métriques intervenant au moment de l’exécution
2.4. Les outils d’expérimentation
2.5. Resultats et Discussion
3. Conclusion
Chapitre V. Discussions & Conclusion
1. Application des patrons de conception pour l’IAPatterns
1.1. Les patrons et la représentation des connaissances
1.2. Les patrons et les modes de raisonnement
1.3. Les patrosn et les systèmes Multi-Agents Systems
2. Conclusion
3. Perspectives
Bibliographie & Références
Télécharger le rapport complet