• Aucun résultat trouvé

Chapitre 3 Applications dynamiques

3. Caractérisation des approches

La précédente section a présenté les applications dynamiques et les concepts relatifs à cette classe d’application. De nombreux travaux proposent des classifications abordant le dynamisme [48, 53, 72]. Cependant, nous nous intéresserons plus particulièrement aux variations du gestionnaire d’adaptation c'est-à-dire :

 La description des adaptations

 La gestion des adaptations à l’exécution

Le reste de ce chapitre a pour objectif de définir une caractérisation permettant de classifier les approches pour implémenter et exécuter des applications dynamiques. Les critères définis dans cette caractérisation nous permettrons de positionner différents travaux sur la description et l’exécution d’applications dynamiques.

3.1. Critères

Depuis les années 70, de nombreux travaux se sont intéressés à créer des applications dynamiques. Cependant, les solutions proposées sont très hétérogènes. Afin de classifier ces approches, nous définissons six critères permettant de caractériser les approches permettant de créer des applications dynamiques. Ces critères sont répartis en deux sous catégories : ceux s’intéressant à la logique d’adaptation mise en place pour supporter le dynamisme et ceux se focalisant sur l’infrastructure gérant les adaptations.

Les applications dynamiques subissent des adaptations. Cependant, ces adaptations sont généralement régies par une politique d’adaptation décrivant quand et comment l’application est adaptée. Un point important discriminant les approches permettant d’exécuter des applications dynamiques concerne la description et la gestion de cette politique. Nous distinguerons trois critères concernant les logiques d’adaptations :

37  Les déclencheurs des adaptations : Ce critère s’intéresse aux évènements déclenchant les adaptations. En effet, celles-ci peuvent être déclenchées par administrateur ou un utilisateur, par une modification de l’environnement d’exécution ou par un évènement interne à l’application.

 La localisation de la logique d’adaptation : Afin de piloter l’adaptation, plusieurs alternatives sont possibles. Tout d’abord, il peut ne pas y avoir de politique lorsqu’un administrateur (humain) gère l’adaptation. D’un autre coté, lorsqu’elle existe, cette politique peut être noyée dans le code, décrite et externalisée, ou bien infusée dans la description de l’architecture.  La gestion des politiques d’adaptation : Ce dernier critère s’intéresse aux capacités du système

à supporter la modification de la politique d’adaptation.

A l’exécution, le gestionnaire d’adaptation supervise et modifie l’application en fonction d’une politique d’adaptation. La seconde catégorie de critère se focalise sur l’exécution de cette adaptation. Nous distinguons trois critères concernant ce processus :

 Le positionnement du gestionnaire d’adaptation par rapport à l’application : Le gestionnaire d’adaptation peut être dans l’application, ou externalisée.

 Les mécanismes utilisés pour l’adaptation : Aujourd’hui, il existe de nombreux mécanismes permettant l’adaptation. Ce critère liste les différentes approches (protocoles méta-objet, aspects …) utilisées afin d’adapter l’application.

 La gestion des interruptions : L’adaptation d’une application dynamique peut entrainer une interruption de service. Cette interruption doit être minimisée afin de limiter l’impact de l’adaptation sur les utilisateurs. Ce critère distingue les différents niveaux d’interruption.

3.2. Qu'est-ce qui initialise l’adaptation ?

Le but de ce critère est de définir quand est adaptée une application. En fonction des approches, il n’est pas possible d’adapter au même moment. Ce premier critère concerne donc les stimuli (c'est-à-dire les événements) qui vont déclencher des adaptations. Ces adaptations peuvent être initialisées soit de manière externe et consciente (administrateur, configuration de l’utilisateur), soit suite à un événement externe issu de l’environnement d’exécution ou du contexte, soit suite à une décision de l’application elle-même.

La première catégorie de déclencheurs concerne les adaptations initialisées à l’extérieur de l’application de manière consciente (Figure 14). L’adaptation est initiée par un administrateur (humain ou virtuel) ou par un utilisateur voulant reconfigurer l’application. Ce type de déclencheur est très commun. De nombreuses applications permettent d’être reconfigurées. Cette reconfiguration peut être exprimée à divers niveaux comme la liste des options à déployer ou la liste des composants à ajouter … Un élément important de ce déclencheur est que la reconfiguration est effectuée de manière consciente ; c'est-à-dire par un administrateur / utilisateur sachant qu’il est en train de reconfigurer son logiciel. Ceci est important, car cela simplifie beaucoup la vérification de la reconfiguration. Le gestionnaire d’adaptation n’a pas à vérifier l’intégrité de l’application.

La deuxième catégorie d’événement pouvant déclencher une adaptation contient les événements externes issus de l’environnement d’exécution et des changements de contexte (Figure 15). Les événements provenant de l’environnement d’exécution sont utiles pour traquer la disponibilité des services utilisés par l’application. Cependant, quand un service utilisé s’en va ou réapparaît, l’application doit réagir. Cette catégorie contient également les événements provenant du contexte surveillé par l’application. Par exemple, un utilisateur peut se déplacer. De ce changement peut résulter une adaptation afin de s’adapter au nouveau contexte de l’utilisateur. Deux différences majeures distinguent cette catégorie de la précédente. Bien que ces événements proviennent également de l’extérieur de l’application, l’application doit réagir seule sans la

Clement Escoffier 38 supervision d’un administrateur. Ceci rend beaucoup plus complexe la vérification de l’intégrité de l’application après l’adaptation.

Figure 14. Acteur externe déclenchant l'adaptation de l'application

Figure 15. Adaptation déclenchée par un changement de l'environnement d'exécution ou par un changement de contexte

L’application peut elle-même décider de s’adapter (Figure 16). Dans ce cas, l’application se supervise elle-même afin de décider quand s’adapter et comment s’adapter. Ce genre d’adaptation est souvent utilisé dans les applications auto-adaptables où l’application s’optimise en fonction de son état ou d’un changement de contexte interne. Par exemple, une application dotée d’un détecteur de panne pourra se reconfigurer lorsqu’une panne ou un dysfonctionnement est détecté. L’événement à l’origine de la reconfiguration est interne puisque l’application elle-même a détecté sa panne. Ce type d’adaptation est plus rare, car l’application doit avoir la capacité de s’analyser elle-même et d’agir sur son architecture.

39 Figure 16. Adaptation d'une application provenant d'un stimulus interne

Les approches pour la création d’application dynamique peuvent supporter une ou plusieurs de ces catégories (Tableau 2). En fonction des catégories supportées, le dynamisme sera plus ou moins difficile à mettre en place.

Source des évènements

déclenchant des adaptations Exemples d’événements Exemples typiques d’application

Événements externes supervisés par un administrateur ou un

utilisateur

Administrateur ou utilisateur reconfigurant l’application

Applications configurables

Événements externes provenant de la modification de l’environnement d’exécution ou d’un changement de

contexte

Arrivée ou départ d’un dispositif physique, disponibilité d’un service

tiers, changement du contexte de l’utilisateur

Applications sensibles au contexte, Applications

ubiquitaires Événements internes Panne, Disfonctionnement,

Changement de contexte interne

Systèmes autoréparables, systèmes auto-optimisables Tableau 2. Exemples d'applications en fonction des évènements initialisant l'adaptation

3.3. Où est décrite la logique d’adaptation ?

La logique d’adaptation doit répondre aux deux questions suivantes : quand et comment est adaptée l’application. Ce critère s’intéresse à la deuxième question et plus particulièrement la localisation de l’information décrivant les adaptations, c'est-à-dire à la localisation de la politique d’adaptation. Il existe plusieurs variations. Celle-ci peut ne pas exister (système adaptable) ou être codée, chargée voir exprimée dans l’architecture de l’application (Figure 17).

Clement Escoffier 40 L’option la plus souvent utilisée consiste à ne pas supporter de reconfiguration automatique. Toutes les adaptations sont effectuées par un administrateur ou un utilisateur de manière ad hoc en utilisant l’interface de contrôle fourni par le gestionnaire d’adaptation (a). En fonction des systèmes, cette adaptation peut se faire de manière interactive ou via l’exécution d’un script. La plupart des applications à plug-in choisissent cette option. L’utilisateur choisit les plug-ins à installer. Il a donc un contrôle complet sur les adaptations et offre une solution flexible. Cependant, elle est inapplicable pour les applications devant réagir rapidement à des événements provenant de l’environnement d’exécution.

Les autres alternatives ont pour but de rendre une application auto-adaptable, c'est-à-dire s’adaptant toute seule sans «humain dans la boucle» [83] et donc leur gestionnaire d’adaptation contient une partie reconfiguration. Une technique pour créer des applications auto-adaptables consiste à coder la politique d’adaptation dans le gestionnaire d’adaptation (b). Cette politique est donc fixée et difficilement changeable dynamiquement. De plus, l’utilisateur ou l’administrateur n’a plus aucun contrôle sur les adaptations. Cependant, cette option permet de réagir à des évènements de l’environnement ambiant. De nombreuses applications sensibles au contexte utilisent cette option. Cependant, elle ne permet pas de prendre en compte d’événements nouveaux non prévus initialement et peut devenir obsolète lorsque le contexte dépasse le cadre défini à la conception. De plus, la modification de la politique demande de redévelopper le code contenant celle-ci.

Afin d’éviter les problèmes de cette seconde alternative, il est possible d’externaliser la politique du code en effectuant l’adaptation en fonction de cette politique. Le gestionnaire d’adaptation chargera cette politique et l’exécutera (c). Bien que généralement plus générique que les politiques codées, cette approche permet une réelle séparation entre le gestionnaire d’adaptation et la politique elle-même. De plus, il est généralement possible de faire évoluer cette politique sans faire évoluer le code l’exécutant. La politique peut prendre plusieurs formes telles qu’un fichier XML ou un fichier dans un langage spécialisé et est généralement exprimé par des règles d’adaptation (type règle Évènement – Condition – Action) comme dans [76]. Cette approche est donc plus flexible que l’approche précédente. Il s’agit de l’approche généralement utilisée dans les applications autonomiques où un gestionnaire administre un système en fonction d’une politique d’administration [22, 84, 85]. Un aspect intéressant est que les gestionnaires d’adaptation des applications

autonomiques transforment une application adaptable en une application auto-adaptable.

Bien que l’externalisation de la politique d’adaptation soit plus avantageuse que le codage « en dur », elle ne fait pas forcément partie de l’application. Cela pourrait permettre de rendre une application « standard » dynamique, mais il est très difficile de rendre dynamique une application qui n’a pas été développée pour. De plus, les politiques doivent être développées en fonction des architectures des applications gérées. Pour combler ces lacunes, la dernière alternative propose d’exprimer la politique de gestion du dynamisme dans l’architecture de l’application elle-même. En effet, il parait sensé d’exprimer cette politique dans la description de l’architecture puisque le dynamisme modifie cette architecture. Cette politique peut être exprimée de différente manière soit en considérant l’architecture de l’application comme un style qui doit être respecté en permanence [86] comme par exemple en utilisant des grammaires de graphes, soit en décrivant les opérations à effectuer en fonction des événements, soit en annotant l’architecture avec des contraintes à respecter [66]. L’avantage d’exprimer le dynamisme dans une architecture offre également la possibilité de vérifier que l’adaptation laisse l’application dans un état cohérent soit en vérifiant les contraintes de style, soit en effectuant diverses vérifications ou simulations. De nombreux travaux se sont intéressés à supporter le dynamisme dans l’architecture de l’application en utilisant différents moyens tels que les grammaires de graphes [87-89], l’algèbre de processus [90], des langages spécialisés [64, 83] ou bien un système d’évènements[91].

En fonction de l’endroit où est décrite la politique d’adaptation, la gestion du dynamisme peut être plus ou moins flexible (Tableau 3). Bien que l’absence de politique offre une gestion très flexible, elle n’est pas

41 applicable à tous les cas. L’expression de la politique dans le code du gestionnaire d’adaptation est très utilisée, mais n’est pas assez flexible dans de nombreux cas. La solution la plus utilisée est la description de la politique de manière séparée. Cependant, cette solution peut être difficile à mettre en place sur des applications dont l’architecture ne permet pas le dynamisme. De plus, la politique doit être exprimée en fonction de l’architecture de l’application. La dernière alternative est l’expression du dynamisme dans l’architecture de l’application. Cette solution apporte l’avantage de prendre en compte le dynamisme comme une propriété fondamentale au moment du design de l’application.

Localisation de la politique d’adaptation

Pas de politique Politique code Politique externalisée

Politique exprimée dans l’architecture de l’application

Tableau 3. Récapitulatif des critères concernant la localisation de la politique

3.4. Gestion des politiques d’adaptation

Un troisième point important concernant la logique d’adaptation est sa gestion durant l’exécution. En effet, dans le cadre d’applications auto-adaptables (donc régies par une politique d’adaptation) une question importante est : est-ce que le comportement du système et la politique d’adaptation peuvent évoluer dynamiquement? Pour répondre à cette question nous distinguerons deux types de systèmes [83]:

- Les systèmes fermés où il n’est pas possible de changer la politique d’adaptation

- Les systèmes ouverts où il est possible de changer de politique d’adaptation à l’exécution

Dans les systèmes fermés, le comportement du système et les adaptations sont fixés au déploiement de l’application. Dans les systèmes ouverts, le comportement du système peut évoluer lors de l’exécution ainsi que la logique d’adaptation. Changer la politique d’adaptation sert généralement à pouvoir prendre en compte des événements non prévus lors de la conception de l’application et de la politique d’adaptation. La mise en place d’un système ouvert est généralement délicate. Elle fait souvent appel à des technologies complexes comme le chargement dynamique de code. Plus particulièrement, le changement de la politique d’adaptation est extrêmement complexe comme le souligne [65]. Cette difficulté vient à la fois du fait que le changement de politique peut perturber le système (voir le laisser dans un état incohérent), mais également du fait qu’il faut généralement compléter le système avec des événements supplémentaires ou de nouveaux actionneurs utilisés par la nouvelle politique.

Une troisième alternative est envisageable. Il est possible de créer des applications mi-ouvertes : la politique d’adaptation ne peut pas être changée complètement, mais propose néanmoins des points de variations5. Un exemple simple serait un système où la politique d’adaptation s’exprime en fonction de variables dont les valeurs sont modifiables dynamiquement.

Gestion des politiques d’adaptations Fixe (système fermé)

Variable (système semi-ouvert) Changeable (système ouvert) Tableau 4. Récapitulatif des options concernant

la gestion des politiques d'adaptations

5 Cette approche découle des principes des lignes de produits. Dans les lignes de produits les valeurs de ces variables seraient généralement choisies avant l’exécution.

Clement Escoffier 42

3.5. Positionnement du gestionnaire d’adaptation

Le gestionnaire d’adaptation a pour but d’adapter l’application dynamiquement. Cependant, le gestionnaire d’adaptation peut être placé différemment par rapport à l’application. Quatre positions sont envisageables :

 Dans le code de l’application

 Dans un code fusionné avec celui de l’application  Dans le support d’exécution de l’application  De manière externe par rapport à l’application

3.5.1. Implantation du gestionnaire d’adaptation dans le code de l’application

Lorsque le gestionnaire d’adaptation est implanté directement dans l’application, le dynamisme est géré directement dans le code de l’application. Celui-ci contient alors toute la gestion de l’architecture de l’application et donc effectue sa propre reconfiguration. Cette approche est l’une des plus utilisées aujourd'hui, car elle permet une gestion très spécialisée du dynamisme. Par exemple, lorsque le contexte n’est plus favorable, une application peut décider de fonctionner en mode dégradé, c'est-à-dire d’offrir moins de fonctionnalités ou peut décider de s’arrêter.

Afin de gérer le dynamisme dans le code, il faut que l’application puisse être notifiée des changements de son contexte ou de son environnement d’exécution. Suite à cette notification, l’application peut réagir et adapter son comportement. Nous citerons ici deux approches généralement suivies lors de la mise en place de gestionnaires d’adaptation dans l’application.

La première approche consiste simplement à reconfigurer des paramètres pour modifier le comportement en fonction des événements du contexte. Par exemple, l’algorithme de TCP (protocole de contrôle de transmission utilisé sur Internet) ajuste son comportement en modifiant la taille de son historique et son délai de retransmission lorsqu’il suspecte une congestion du réseau. Dans ce cas, le gestionnaire d’adaptation détecte le problème et ajuste les paramètres.

Une deuxième approche pour gérer le dynamisme dans le code consiste à utiliser un patron de conception appelé « stratégie » [92]. Ce patron de conception est généralement utilisé pour changer d’algorithme, nommé stratégie, en fonction du contexte. Lorsque le contexte change, le gestionnaire d’adaptation détecte ce changement et choisit l’algorithme le plus adéquat en fonction du nouveau contexte (Figure 18). Cette approche est utilisée dans [93].

Figure 18. Schéma de principe du patron de conception "Stratégie"

Bien que gérer le dynamisme dans le code soit la méthode la plus employée, elle possède de nombreux défauts. Tout d’abord, elle est difficile à mettre correctement en place lorsque l’application s’exécute dans un environnement très dynamique. Ensuite, le code du gestionnaire d’adaptation est souvent dispersé dans le

43 code de l’application, ce qui ne facilite pas la maintenance de l’application. Et enfin, toutes les sources de dynamisme ne peuvent pas être gérées ainsi. En effet, l’évolution de l’application est difficilement gérable à partir de l’intérieur même du code de cette application.

3.5.2. Fusion du gestionnaire d’adaptation et du code de l’application

Afin de séparer le code gérant les adaptations du code de l’application, il est possible d’intégrer le code du gestionnaire d’adaptation et le code de l’application en utilisant la composition de filtre ou la programmation par aspect. Comme cette jonction n’est effectuée qu’à la compilation, le code de l’application n’est pas « pollué » par le code du gestionnaire d’adaptation.

La composition de filtre6 est apparue au début des années 90 et avait pour objectif d’intercepter les interactions entre objets. Chaque filtre intercepte les messages reçus et envoyés entre les objets de l’application [94, 95]. Le filtre peut sélectionner les messages à intercepter et effectuer un traitement lorsqu’un message est capturé. Le filtre peut alors choisir l’objet à appeler en fonction du contexte, bloquer l’appel si l’objet visé n’est plus accessible… Des séquences de filtres peuvent également être mises en place, mais requièrent que l’ordre soit spécifié lorsqu’un filtre transforme les données du message. Les filtres sont développés séparément du code de l’application et sont ensuite compilés avec l’application. La composition de filtre est notamment utilisée dans les servlets Java [96].

L’approche la plus couramment utilisée pour ajouter du code non-fonctionnel au code d’une application consiste à utiliser la programmation par aspect (AOP) [97]. Cette approche est plus générique que les filtres qui se focalisent sur l’échange de messages entre deux composants. Les aspects permettent également d’intercepter des appels de méthodes à l’intérieur d’un même objet ou bien l’accès aux membres d’une classe (combinés avec le mécanisme de superimposition [98], les filtres permettent d’exprimer des aspects[95]). Aujourd’hui la programmation par aspect est devenue très populaire comme l’illustre le succès d’AspectJ, permettant d’appliquer les principes de l’AOP sur Java. Le principal intérêt de l’AOP est qu’il permet de séparer le code des aspects et le code métier de l’application. Ce n’est qu’à la compilation que ceux-ci seront réunis (tissage). Tout comme les filtres, les aspects peuvent contenir la gestion du dynamisme [99].

Les deux approches présentées ici peuvent être utilisées pour implémenter des gestionnaires d’adaptation [100, 101]. Plus particulièrement, elles permettent de contrôler les interactions ayant lieu dans l’application ce qui permet d’administrer le dynamisme provenant de l’environnement ou le changement de contexte. Cependant, tout comme l’implantation du gestionnaire d’adaptation dans le code, il est très difficile d’appliquer ces techniques pour contrôler l’évolution de l’application.

3.5.3. Gestionnaire d’adaptation au sein des modèles à composant

Bien que l’approche précédente permette de séparer le code de l’application du code du gestionnaire d’adaptation, ceux-ci sont réunis à la compilation et sont donc liés à l’exécution. Une autre approche consiste à séparer réellement le gestionnaire d’adaptation et l’application. Dans cette approche, l’application peut être supervisée par le canevas d’exécution. Nous allons voir comment les modèles à composant permettent de mettre en place cette approche.

La programmation par composants (Component-Based Software Engineering (CBSE)) propose la décomposition d’un système en entités fonctionnelles nommées composants [102]. Un composant possède des interfaces utilisées pour les interactions avec les autres composants. Une application est ensuite assemblée en