Commentaires Récents
30.07.2008
Va voir ca mec, c'est le MOD de BF2 ultime avec...
Par : Jean-Sébastien

06.10.2007
En fait tu n'as qu'a utiliser le gestionaire...
Par : Carl-Hugo Marcotte

24.09.2007
C'est cool ta source j'ai réussi a faire 3...
Par : Nicolas

j'ai mis à jour le lien...
Par : Carl-Hugo Marcotte

Il n'y a plus de lien vers...
Par : Lapie

Nom d'utilisateur :

Mot de passe :


 
Programmation orientée aspect (concepts de base) [1ère partie]

Avant-propos

Voici un document que j'ai transformé en post. En fait c'est un travaille que j'ai du faire et que je voulais publier ici... Je crois que c'est une bonne introduction à la programmation aspect.

Introduction

Paradigmes de programmation

Qu’est-ce qu’un paradigme ? Un paradigme n’est rien d’autre qu’un style fondamental de programmation informatique. Il existe divers paradigmes, le paradigme objet, que nous connaissons bien, le paradigme fonctionnel, qui est une suite d’évaluation de fonctions sans état, etc.

Divers langages de programmation emploient ces paradigmes, certains sont restreints à un seul, certains en supportent plusieurs, c’est le cas entre autre de C++.
Pour une liste complète des techniques de programmation, voir [1] Paradigme (programmation).

Le programmation orienté aspect (POA)

La POA (ou en anglais AOP : aspect-oriented programming) est un concept fort ingénieux. Il consiste à séparer certains aspects, comme sont nom l’indique, et de les isoler dans des modules indépendant. Ces modules, que nous nommerons désormais, aspect, regroupent une sorte de fonctionnalité bien spécifique d’un programme informatique.

Plusieurs aspects importants viennent envenimer le code de la programmation OO, par exemple : la gestion des erreurs. De plus, ce code, est souvent redondant, dupliqué et divisé dans plusieurs classes, ce qui nuit à la maintenabilité du programme.

La POO (programmation orienté objet) est très puissante mais impose certaines limites. Dans un programme de grande envergure, par exemple, certaines modifications à la logique applicative peuvent devenir une tâche très lourde. En pouvant encapsuler certains aspects d’un programme dans un module indépendant, la seul modification de ce module propage la modification à l’ensemble de l’application, ce qui sauve beaucoup de temps.

Voilà où la magie de la POA intervient. Par contre, prenez garde, quand je dis magie, cela n’apparaît malheureusement pas comme par magie, c’est une nouvelle forme de pensée et une nouvelle façon de programmer. La POA consiste en l’implémentation de fonctionnalités transversales (cross-cutting concerns) aux classes d’un système. J’ai antérieurement parlé « d’injection », c’est exactement ce que la POA fait, les aspects sont injectés dans le code OO. L’injection peut ce faire « at compile time » (statique) ou « at runtime » (dynamique).

Une particularité intéressante, soulevant également quelques inquiétudes, est que les aspects peuvent être injectés dans les programmes déjà compilés ainsi que dans les programmes en cours de développement. La POA facilite donc le développement logiciel, de même que l’injection de code de tierce partie sans le consentement des créateurs du logiciel. Ceci, peut laisser place à l’injection de « Malware » ou au piratage du logiciel (exemple : remplacer le corps d’une méthode d’authentification par return true;).

Le vif du sujet

Cross-cutting concerns

Qu’est-ce qu’une fonctionnalité transversale (Cross-cutting concerns) ?
Une fonctionnalité transversale n’est en fait qu’une certaine logique divisée dans plusieurs parties d’un système. Nous pourrions dire ici que la POO est de la programmation verticale et que la POA est de la programmation horizontale.

Voici un schéma illustrant les orientations énoncés ci-haut :

NOTE : Les rectangles blancs représentent des classes et les rectangles gris des aspects.
 
Par exemple, un système où vous devez posséder un compte utilisateur (login, password), doit sécuriser certaines parties, voire l’entièreté du système. Ce qui implique l’ajout de codes de sécurité dans plusieurs classes du système. L’ajout d’un journal des opérations (log) est également un élément impliquant plusieurs lignes de codes divisés dans plusieurs classes. Ce code peut être extrêmement redondant, voire simplement dupliqué. Le déploiement d’un système dans différents environnements peut également être une contrainte. Certaines parties du code peut être optimisé pour un système X mais pas pour le système Y, ce qui entraîne une perte de performance dans le système Y. La POA permet donc de régler ces problèmes. Un aspect sécurité peut être créé ainsi qu’un aspect « log ». Un aspect d’optimisation peut être créé pour chaque environnement visé par l’application. Ainsi, le logiciel développé aura toujours des performances optimales sur toutes les plates-formes où il sera déployé.
 
Voici un schéma démontrant à quoi ressemble, graphiquement, la division des aspects énumérés ci-haut dans un programme n’utilisant que la POO :

Maintenant, voyons ce que pourrait avoir l’air un programme utilisant la POO et possédant une couche de POA :

Nous voyons maintenant le principe fondamental, le code dupliqué ou semblable est retiré des classes (ou évidement n’a jamais été écrit) et est introduit dans des aspects.
 
Les responsabilités superflus étant maintenant retirés, entraînent une plus forte cohésion à l’intérieur des composantes du système, ainsi qu’une meilleure abstraction puisque chaque classe peut maintenant se soucier uniquement de sa propre responsabilité.
 
Comment ces aspects font-ils pour jouer le rôle de plusieurs petits bouts de codes ? Voilà la question qui amène le prochain point : où est la magie ?

Où est la magie ?

En fait, il n’y a pas de magie, mais plutôt un « Weaver », un tisseur d’aspects. Le tisseur, comme énoncé plus haut, permet d’injecter (introduire) le code aspect à l’intérieur du code objet existant. Le tisseur permet également de remplacer complètement certaines portions de code, voire étendre les fonctionnalités existantes en ajoutant des méthodes, des propriétés, etc. aux classes.
 
Le tisseur d’aspects peut intervenir à plusieurs niveaux. Les aspects peuvent être intégrés au code OO à la compilation (compile-time). Le code généré par le compilateur est donc modifié, introduisant ainsi le code encapsulé dans les aspects par un « post-compilateur » aux endroits désirés.
 
Remarque : il est possible qu’un pré-compilateur soit utilisé, ou une autres techniques. La post-compilation n’est qu’une façon comme une autre que le Weaver peut utiliser pour injecter les aspects.
 
Le tisseur d’aspects peut également injecter le code lors de l’exécution du programme (at runtime). Par contre, cette technique peut considérablement diminuer les performances de l’application. Il faut donc être vigilant avant d’injecter du code aspect « at runtime », il faut être sûr et certain que cet aspect ne peut PAS être ajouté « at compile-time ».

La POA plus en profondeur

Avant d’aller plus loin, je vais parler des termes spécifiques à la POA. Et oui, la POA ne fait pas exception aux autres techniques de programmation, elle possède, elle aussi ces propre termes spécifiques.

Terminologie

Cross-cutting concerns

Nous avons déjà vu ce qu’est une fonctionnalité transversale, mais voyons ici un résumé de la définition.

La plupart des classes OO sont créées pour représenter une seule et unique tâche. Par-contre, elles ont la responsabilité de gérer différentes tâches secondaires. Le code spécifique d’une classe est généralement très différent du code spécifique d’une autre classe, mais le code des tâches secondaires est souvent identique. Ces tâches secondaires peuvent donc être extraites et être mises dans des aspects. Ces dernières sont nommées fonctionnalités transversales.

Advice

Un « advice » représente le code que l’on veut injecter dans notre programme. Le « corps » d’un aspect.

Point-cut

Un « point-cut » représente l’endroit où le code de notre « advice » doit être injecté : Avant l’exécution d’une méthode, après l’exécution d’une méthode, à la place de l’exécution d’une méthode, autour de l’exécution d’une méthode, etc.

Aspect

Un aspect représente la combinaison de l’ « advice » et du « point-cut ». L’aspect est, ni plus ni moins, l’aspect du programme qui doit être isolé, la fonctionnalité transversale concernée.

Comment le code OO et le code OA s’intègrent (Processus statique) ?

Jusqu'à présent nous avons parlé des avantages de la POA. Nous avons fait un survol de l’architecture de la POA. Nous avons également vu quelques termes spécifiques. Mais comment, tout ceci, peut-il devenir un programme digne de ce nom ? Nous avons quand même deux couches différentes, la couche OO et la couche OA.
 
Voici un schéma démontrant la fusion entre les classes objets et les aspects « at compile-time » (après la compilation).

Dans le schéma ci-haut, on voit clairement comment sont injectés les aspects dans le code OO. Le code OA est ajouté après la compilation standard par le « Weaver ». Du moins, c’est le principe du « Weaver » que je vais utiliser dans mes exemples. Le Weaver modifie le code MSIL (.NET) ou Bytecode (Java) pour créer le programme final. Comme énoncé antérieurement, il existe des processus d’injection dynamique qui ajoute « at runtime » les aspects. Le schéma ci-haut ne prend pas en compte le tissage dynamique.

Description détaillée du processus

  1. Le code des classes OO est premièrement compilé par le compilateur.
  2. Le code nommé code standard dans mon schéma est le code intermédiaire généré par les compilateurs Java et .NET. Ce code est prêt a être exécuté.
  3. Le code généré (MSIL ou Bytecode) est ensuite modifié par le Weaver, injectant ainsi le code contenu dans les aspects.
  4. Le programme final, en langage intermédiaire est finalement compilé et prêt à l’exécution.
Pour conclure, le résultat final de l’intégration OO et OA (at compile-time) n’est en rien différent à un programme uniquement fait avec du code OO et compilé en langage intermédiaire. L’atout principal est que la maintenabilité est grandement affectée à l’avantage du développeur puisque c’est le Weaver qui recrée le code redondant.
 

Comment le code OO et le code OA s’intègrent (Processus dynamique) ?

Vu le manque d’information en cette matière, je n’ai malheureusement pas pu faire de schéma concret sur l’implémentation dynamique des aspects. Par contre, je peux quand même donner une brève explication de l’implémentation dynamique.
 
Premièrement, les aspects ne sont ni intégrés avant, ni pendant et ni après la compilation, mais bien lors de l’exécution du programme.
 
Dans certains cas, les aspects sont ajoutés au code lors du premier appel du constructeur d’une classe impli-quée. J’ai même remarqué que certain « Weaver » propose un processus de réinjection si un aspect a été modifié. Un processus de vérification des changements est donc impliqué dans la mise à jour des aspects.
 
Plusieurs projets « at runtime » sont présentement en cours de développement. Le gros problème semble être le manque de supports des API de programmation (Visual Studio, Eclipse, etc.). Une solution ne possédant aucun support réel lors du développement d’une application ne peut être considérée par une entreprise comme une alternative viable, dans un environnement de production réelle.
 
Les développeurs désireux d’utiliser une technique dynamique d’injection d’aspects doivent être extrêmement compétents en matière de maîtrise des détails de la compilation pour ne pas sacrifier de performance inutilement.

Implémentation

Puisque je ne crois pas que Java soit un langage du futur, j’ai choisi C#. Le C# 3.0 natif est beaucoup plus puissant que Java et les librairies du .NET Framework 3.5 sont beaucoup plus évoluées que les librairies de Java 5 (du moins à ce que j’ai vu jusqu'à présent), [2] Why C# is different from Java (cet article ne compare que C# 2.0 à Java 5 et ne tient pas compte des nouvelles fonctionnalités de C# 3.0). Il n’existe malheureusement pas de compilateur .NET sur toutes les plates-formes, ce qui laisse encore une grande place à Java pour le déploiement d’applications « cross-plateforms ». De plus, les notes de cours de Linda Badri pour le cours de GL (UQTR), section POA, démontrent comment utiliser AspectJ, pour Java. Je n’ai donc pas à démontrer comment utiliser AspectJ. AspectJ étant un Framework très populaire, de nombreuses ressources sont probablement disponibles sur le web.
 
NOTE : AspectJ est le premier tisseur d’aspects qui fut mis sur le « marché ».

AspectJ

Comme énoncé ci-haut, AspectJ est le premier tisseur d’aspects qui fut créé, et un des plus populaires. Gregor Kiczales étant le chef de projet de AspectJ, travaillant pour Xerox, a formulé les premiers concepts de la POA. Merci Gregor Kiczales!
 
Le projet AspectJ commença en 2001 avec un tisseur « at compile-time ». En 2002, AspectJ possédait déjà un tisseur « at runtime ». Ce n’est qu’en 2005 que l’implémentation de fonctionnalités avancées « at runtime » furent ajoutées à AspectJ, lors de la fusion avec « AspectWerkz ».
 
Je ne donnerai pas plus d’information sur AspectJ dans le présent document. Si cela vous intéresse, vous pouvez visiter leur site internet ([3] AspectJ) ou encore utiliser un engin de recherche.

POA utilisant XML

J’ai également vue quelques « Weaver » utilisant le XML comme support pour les aspects. Ce n’est pas une mauvaise idée, mais selon moi, cette technologie est trop complexe pour être utilisée sans un API. Par exemple, AspectDNG transforme le MSIL (semblable au Bytecode de java, mais pour .NET) en XML et applique les transformations XML (aspects) par l’entremise de XSLT (feuille de styles XML) . Ce projet semble par contre abandonné.

Ce qui peux être intéressant avec XML, c’est le « Remote AOP ». Imaginez les aspects sur un ordinateur distant, peut être propulsé par un service web ou toute autre technologie. Je suis convaincu qu’il y a un gain potentiel à créer un processus de mise à jour de logiciel avec la POA à distance.
 
Remarque : « remote » ne veut pas simplement dire un ordinateur distant. Un processus différent est également un « remote call ». De plus, en .NET, il peut y avoir plusieurs « application domains » dans le même processus (ceci est un autre sujet non traité par le présent document).
 
Seconde remarque : Le « Remote AOP » n’est qu’une de mes élucubrations. Je n’ai aucunement vu de référence à ce sujet. Peut-être me pencherais-je sur la question ultérieurement.

PostSharp

PostSharp est le Framework que j’utiliserai dans le reste de ce document pour démontrer comment, concrètement, faire de la POA. Vu le temps limité que j’ai eu pour écrire ce document et apprendre un Framework, j’ai choisi PostSharp parmi plusieurs autres « Weaver » .NET sans trop me pencher sur chacun d’eux en détails. PostSharp me semble complet au tant « at runtime » qu’ « at compile-time ». Il y a également beaucoup de documentation disponible sur leur site internet, ce qui est extrêmement pratique.
 
PostSharp Core est la couche « low-level » du framework, la base, le lien entre le code intermédiaire et le code des aspects programmés. Son architecture permet de créer des plugins plus avancés pour faciliter la vie des développeurs. PostSharp Laos (Lightweight Aspect-Oriented System) est un des plugins « High-level » fourni par les développeurs de PostSharp. Puisque PostSharp Core offre la possibilité de dévelloper des librairies de plus hauts niveaux sans se soucier des détails de l’injection au code MSIL (géré par PostSharp Core), je pense que c’est un bon framework, tant qu’il y a possibilité d’avancement, il y a de l’espoir…

PostSharp Laos

Un des désavantages de PostSharp Laos est que le temps de compilation d’un programme est grandement augmenté. Je ne travaillais qu’avec un très petit projet, possédant uniquement 2 classes. Chaque classe n’ayant qu’un listing peu élaboré (+ un aspect extrêmement simpliste) et j’ai vu la différence. Par contre, pour des développeurs expérimentés, il est possible de construire ses propres librairies au dessus de PostSharp Core ou encore modifier les librairies existantes puisque c’est un projet « open-source ».
 
PostSharp Laos ne requiert aucun apprentissage supplémentaire autre que la structure hiérarchique des classes fournies par le framework. Les aspects sont programmés en langage OO normal supporté par le .NET Framework (C#, VB.NET, …). Il permet d’utiliser tous les concepts connus en POO comme l’héritage ainsi que les méthodes « virtual » et « asbtract ». Il offre également un grand choix d’aspects possibles comme :
 

Type d’Aspects

Gestionnaires disponibles

Cas d’utilisation typiques

Around Method

On Exit, On Entry, On Success, On Exception

Instrumentation; Exception Handling; Transactions; Security

Method Interception

On Invocation

Cache; Instrumentation of External Method

Method Implementation

On Invocation

Automatic implementation of external or abstract methods.

Field Access

On Get Value, On Set Value

Field-Level Security; Validation; Class Persistence; In-Memory Transactions

Interface Composition

Get Interface Implementation

Mix-In, Multiple Inheritance by Composition

Compound Aspect

Get Aspects

Complex Aspects

 
Je vais utiliser PostSharp Laos dans mes exemples à venir. Il me semble assez complet pour commencer mon expérimentation de la POA.
 
 
Nom :
Couriel :
URL :
Commentaire :