OLAN : un environnement de développement d'applications coopérativesRésuméSIRAC est un projet de l'IMAG (Laboratoire Logiciel, Systèmes, Réseaux), de l'INRIA (Unité de Recherche Rhône-Alpes), et de l'Université de Savoie qui développe des actions de recherche dans les deux domaines suivants : Construction d'applications réparties et Services pour le support d'objets partagés persistantsrépartis. Ce papier présente brièvement le premier de ces deux axes dont l'objectif est de fournir des outils répondant à deux besoins : a) construire des applications réparties en combinant des techniques de programmation à base d'objets et des techniques d'intégration de composants ; b) faciliter l'administration, la configuration et l'évolution de ces applications. Les applications coopératives, et notamment les collecticiels synchrones, constituent un domaine d'application privilégié pour l'expérimentation et la validation des outils.
1 Introduction1.1 Motivations et objectifsL'évolution conjuguée de la technologie des télécommunications et de la structure des entreprises et des organisations conduit vers l'émergence d'applications réparties de grande complexité. La conception, le développement et la maintenance de ces applications posent des problèmes difficiles pour lesquels les solutions actuellement disponibles sont jugées insuffisantes par les utilisateurs. Parmi les contraintes principales auxquelles sont confrontés les concepteurs d'applications, on peut citer :* la réutilisation et l'intégration du code existant (application complète ou parties d'applications), d'une part pour des raisons économiques, et d'autre part pour assurer une certaine continuité vis-à-vis des utilisateurs. La plupart du temps, ces applications ont été conçues indépendamment les unes des autres, sans objectif de communication avec l'extérieur. Par ailleurs elles peuvent être écrites dans des langages de programmation différents. * la configuration d'une application. Cette opération recouvre deux étapes du cycle de vie d'une application. Dans un premier il faut décrire les entités (composants logiciels) qui constituent le corps de l'application, puis les schémas de communication et de synchronisation entre ces entités. Le terme "configuration" s'applique également à l'opération qui consiste à déployer les éléments d'une instance de l'application dans un environnement donné. On parlera alors de "configuration à la carte". * la capacité d'administrer les divers éléments de l'application pour adapter la structure opérationnelle de l'application aux ressources disponibles sur le système hôte (compte tenu de la diversité des plates-formes sur lesquelles ces applications sont destinées à s'exécuter : mainframes, monde Unix, monde PC, etc.). Cette capacité d'adaption doit également permettre de répondre à l'évolution de l'application et de son environnement d'exécution dans le temps. Le principe directeur est que les applications distribuées doivent être conçues et réalisées comme des ensembles ouverts et évolutifs de sous-systèmes applicatifs (appelés composants) coopérants, dont certains sont constitués d'applications préexistantes. 1.2 Méthodes d'intégrationModèles et langages à objetsLes modèles à base d'objets sont pertinents pour réaliser l'encapsulation de logiciels existants, dans la mesure où ils permettent de décrire l'interface d'un composant logiciel indépendamment de sa réalisation. Il y a eu, au cours de ces dernières années, un courant de recherche très actif portant sur l'utilisation de modèles et langages à objets pour la description complète d'une application répartie . L'expérience de projets antérieurs (Guide et Comandos) a montré les bénéfices et les limites d'une approche fondée sur des modèles et langages à base d'objets [2]. Deux aspects sont particulièrement délicats. L'intégration de composants existants peut s'avérer difficile si leur modèle d'exécution est incompatible avec le modèle imposé par le langage à objets choisi pour le développement des nouveaux composants. Par ailleurs, les modèles et langages à base d'objets ne sont pas en général adaptés à la description de schémas de coordination complexes (en effet, un grand nombre de modèles et langages à objets offrent à leurs utilisateurs un modèle d'exécution fondé sur des interactions synchrones de type client-serveur).Courtiers d'objetsDeux approches complémentaires se dégagent pour réaliser l'intégration de composants logiciels : les courtiers d'objets d'une part, et les bus logiciels d'autre part. Les courtiers d'objets sont fondés sur un modèle d'interaction de type client-serveur et sur l'utilisation de langages de description d'interfaces (IDL). Ces langages représentent un premier niveau d'outils permettant de séparer la réalisation d'un composant de la spécification de son interface (identification des services rendus et de leurs paramètres). D'autre part la disponibilité d'un compilateur du langage d'interface permet d'automatiser en partie la production du code décrivant l'interaction entre les modules (génération automatique des "talons" pour le programme client et le programme serveur). Cette approche fait aujourd'hui l'objet d'un consensus industriel, caractérisé en particulier par les travaux de l'OMG autour de la norme CORBA (Common Object Request Broker Architecture) et de son langage de description d'interface [8]. Les applications développées dans le monde Windows utilisent une approche similaire, fondée sur le modèle COM (Component Object Model) et le langage de description d'interface de l'environnement DCE (Distributed Computing Model) [7]. La limitation principale de cette approche réside dans le fait que le schéma d'interaction sous-jacent est un simple modèle client-serveur qui s'avère insuffisant pour décrire des schémas de coopération plus élaborés. Des services complémentaires sont en cours d'étude pour gérer d'autres formes de relations et d'interactions entre les objets (contrôle de la concurrence, communication par événement, etc.).Bus de messagesUn autre schéma d'intégration de composants logiciels est celui du bus logiciel, initialement proposé pour l'intégration d'outils dans un environnement de développement de logiciel [10]. Un bus logiciel réalise un service de communication asynchrone à base d'événements ou d'échange de messages. L'interaction entre composants est réalisée par le service de communication qui réalise la médiation entre des composants émetteurs et des composants consommateurs. Courtiers d'objets et bus logiciels sont considérés aujourd'hui comme des technologies de base pour la description d'interactions entre composants logiciels. Elles sont utilisées dans des produits industriels disponibles sur le marché, et seront exploitées par le projet lorsque ce sera nécessaire.Courtiers et bus logiciels fournissent aux concepteurs un modèle de structuration de l'application induit par le modèle d'exécution sous-jacent (modèle de communication synchrone de type client-serveur dans un courtier, et modèle de communication asynchrone par envoi de messages dans les bus logiciels). Ces outils sont satisfaisants pour décrire des interactions élémentaires entre des groupes isolés de composants d'une application. En revanche ils ne répondent pas de façon satisfaisante au cahier des charges énoncé dans la section 1 dans la mesure où ils ne permettent pas de décrire l'organisation globale d'une application en termes de composants logiciels d'une part, et des schémas d'interaction complexes entre ces composants d'autre part. Interconnexions de modulesLa description de la structure globale d'une application repose généralement sur l'utilisation d'un langage de composition (également appelé MIL [9] - Module Interconnection Language). Comme l'IDL de CORBA, un tel langage permet de définir les interfaces des composants logiciels mais il permet surtout de spécifier la structure d'une application en termes d'interconnexion de ces interfaces. Ces aspects ont fait l'objet de recherches spécifiques, qui ont conduit à la notion de "programmation à gros grain" (en anglais programming in the large).Les différentes approches proposées se particularisent par le modèle de structuration des composants logiciels (ou modules), les différents éléments présents dans la description des interfaces et la manière de décrire les interactions entre modules. Les langages d'interconnexion de modules constituent un des points de départ des travaux de recherche du projet. Par rapport à l'existant, un effort méthodologique portera sur les points suivants, pour lesquels les solutions actuellement disponibles dans la littérature ne sont pas satisfaisantes : * utilisation d'un modèle unique pour les différentes étapes du cycle de vie d'une application (spécification, construction, déploiement, administration, ...). L'intérêt d'un modèle unique est justifié par le fait que les étapes du cycle de vie d'une application correspondent à diverses facettes de l'opération de configuration, qui consistent dans un premier temps à décrire la structure d'une application, puis à déployer les éléments de cette application sur un environnement d'accueil, et enfin à procéder à des opérations de reconfiguration en cours d'exécution. Ces aspects sont précisés dans la section suivante. * séparation entre la description des composants et la description des interactions entre eux. * expression et contrôle de la dynamicité de la structure des applications. 2 Modèle d'assemblage et langage de configurationLa classe des langages d'interconnexion de modules (MIL) constitue le point de départ de notre étude. L'objectif de ces langages est de séparer clairement la phase de programmation des composants pris individuellement, de la phase de configuration d'une application qui consiste à assembler des composants selon un schéma d'interaction propre à l'application. Le bénéfice attendu de cette séparation est double : une meilleure modularité et la capacité de réaliser une configuration "à la carte", c'est-à-dire de déployer une instance de l'application adaptée à son environnement d'exécution en limitant l'effort de développement nécessaire.L'élément central du modèle d'assemblage est le composant. Une application est construite comme une hiérarchie de composants. Les feuilles de l'arbre de composition sont constituées par les composants primitifs qui encapsulent une unité logicielle élémentaire. Les noeuds sont des composants complexes construits à partir de composants de niveau inférieur interconnectés par des objets de communication appelés connecteurs. La structure des composants et des connecteurs est brièvement introduite ci-après. Une description plus complète du modèle et du langage est disponible dans [3][4]. 2.1 ComposantsComme dans les modèles à base d'objets, les composants sont des instances d'une classe. Une classe de composant est définie par une interface et une réalisation.L'interface comporte les éléments suivants : des services, des notification, des réactions, et des attributs. * Les services sont des fonctions ou procédures qui sont, soit fournies par le composant lui-même, soit requises par le composant pour assurer son fonctionnement. Les services fournis correspondent au concept traditionnel de méthode dans les modèles à objets. Les services requis sont fournis par des composants extérieurs. * Les notifications sont des événements émis par le composant vers l'extérieur. Selon le contexte d'exécution, l'occurrence d'un événement peut déclencher un certain nombre de traitements (appelés réactions) dans d'autres composants. Une notification d'événement peut déclencher ou non une (ou plusieurs) réaction(s). * Les attributs sont des variables typées publiques. Les attributs définissent un ensemble de propriétés, associées au composant, et accessibles depuis les autres composants. La réalisation d'un composant primitif comprend le code des entités (classes, modules, bibliothèques) qu'il encapsule. La granularité d'un composant primitif est variable. Ce peut être un seul objet (défini par une classe) [6]. Néanmoins, nous voulons aussi offrir l'encapsulation d'un ensemble de classes distinctes, ou d'une bibliothèque, ou de n'importe quelle portion de code fournissant une interface de programmation. La réalisation d'un composant complexe définit la représentation structurelle du composant en termes des composants qu'il contient (appelés aussi sous-composants) et des interactions entre ces composants. Un composant complexe ne contient pas à proprement parler de code, mais les éléments (sous-composants et connecteurs) qui permettent de mettre en oeuvre son interface. Le concept de collection de composants est introduit pour décrire la dynamicité de la structure interne d'un composant. Une collection est un ensemble nommé d'instances d'un même composant. A l'exécution, l'évolution de la structure interne d'un composant est associée à la création/destruction d'instances de composants dans une collection, ainsi qu'à l'ajout/retrait d'interactions entre ces instances. La figure 1 est une représentation graphique simplifiée d'un composant complexe formé de deux sous-composants interconnectés. Les ronds noirs désignent des services et réactions fournis par un composant; les ronds blancs désignent des services requis ou des notifications émises par le composant; enfin, les lignes horizontales représentent les liens de communication entre composants, décrits à l'aide des connecteurs présentés dans la section suivante.
Fig. 1 : Exemple de composant complexe L'exemple suivant présente la description de l'interface et la mise en oeuvre du composant UserSession schématiser dans la figure 1 à l'aide de deux composants existant Control et SharedApplication : component class UserSession { interface UserSessionItf; implementation UserSessionImp; } interface UserSessionItf { provide ReceiveOp (in int RemoteUserId, in string encodedAction); require SendLocalOp (in int UserId, in string encodedAction); attribute Role in [Chairman, Participant]; } implementation UserSessionImp: UserSessionItf { theCoopControler= inst Control; theSharedApplicationSet = inst SharedApplication; /*** mapping with the interface ***/ theCoopControler.SendOp => SendOp; ReceiveOp => theCoopController.ReceiveOp; /*** interactions ***/ theSharedApplicationSet.SendOperation => theCoopControler.ReceiveOp using methodCall; theCoopController.SendOp => theSharedApplicationSet.ReceiveOperation using methodCall; }; 2.2 ConnecteursLes connecteurs sont les entités qui décrivent les interactions entre composants en établissant un lien de communication entre des composants et en spécifiant le devant être mis en oeuvre. La description d'un connecteur inclue la mise en conformité des interfaces interconnectées (respect des signatures ou mise en oeuvre d'un protocole d'adaptation), la définition du protocole utilisé pour mettre en oeuvre la communication (communication asynchrone vs. Synchrone, diffusion d'événements vs. appel de procédure à distance) et la spécification du comportement exprimé sous la forme d'un ensemble de contraintes décrivant la qualité de service attendue (description du comportement temporel du connecteur pour les canaux de communication multimédia). Plus formellement, la description d'un connecteur comprend les éléments suivants :* le type du connecteur qui permet de distinguer les connecteurs utilisés pour réaliser des connexions entre composants et ceux utilisés pour lier une interface à une implémentation. * un ensemble de sources : l'identification d'un ensemble de services requis ou de notifications décrites dans l'interface d'autres composants, * un ensemble de destinations possibles : les identifications d'un ensemble de services ou de réactions fournis par des composants, * la spécification du comportement du connecteur, c'est-à-dire le protocole de communication, assorti d'éventuelles conditions de mise en oeuvre telles que des conditions de synchronisation et/ou des contraintes de qualité de service. Le concept de connecteur n'est pas nouveau. Dans Allen [1], la spécification du comportement des connecteurs et des contraintes associées sont spécifiés en utilisant un sous-ensemble de l'algèbre de processus CSP. La plate-forme OLAN supporte actuellement différents types de connecteurs. Les connecteurs sont construits manuellement sans l'aide d'un langage de spécification. Incluent dans le support d'exécution de la plate-forme OLAN, ils sont rendus disponibles aux écrivains d'application sous la forme d'une bibliothèque. Les deux tableaux suivants présentent brièvement quelques connecteurs disponibles en faisant la distinction entre les connecteurs permettant l'interconnexion de composants et ceux permettant de lier une interface à une implémentation. Nom du connecteur Source(s) Destination(s) Spécification methodCall 1 service [1..n] service un seul appel de méthode requis fournis (synchrone) choisi de manière non déterministe, conformité des paramètres broadcastMethodCa 1 service [1..n] service appel de méthode (synchrone), ll requis fournis mise en oeuvre séquentielle broadcastEvent 1 [1..n] réactions diffusion d'un événement notification (asynchrone) createInCollectio 1 service 1 service création d'un composant dans une n requis requis dans une collection puis appel de méthode collection (synchrone) sur ce composantUne interaction est la communication effective qui a lieu entre un ensemble de composants. Elles sont décrites par la liaison entre les services fournis et requis ou les notifications et les réactions des sous-composants, par le choix d'un protocole de communication. Par exemple dans la figure 1 ci-dessus le code suivant décrit la connexion du port SendOperation d'une instance du composant SharedApplication au port ReceiveOp d'une instance du composant Control en utilisant une instance du connecteur methodCall. theSharedApplicationSet.SendOperation => theCoopControler.ReceiveOp using methodCall; Nom du connecteur Source(s) Destination(s) Spécification methodCall 1 service [1..n] service un seul appel de méthode fourni dans fournis dans (synchrone) choisi de manière une interface un non déterministe, conformité sous-composant des paramètres methodCall 1 service 1 service appel de méthode (synchrone) requis dans requis dans conformité des paramètres un une interface sous-composant broadcastEvent 1 1 notification émission d'un événement notification dans un (asynchrone) dans une sous-composant interface broadcastEvent 1 réaction [1..n] diffusion d'un événement émis dans un réactions dans (asynchrone) sous-composant une interface 3 ConclusionLa mise en oeuvre de ce langage, démontrée lors du congrès AFCET à Toulouse en novembre 1995, repose actuellement sur la plate-forme à objets Oode [5]. Pour valider l'intérêt de notre approche nous avons défini une architecture générique et une méthodologie pour la construction de collecticiels. Les aspects de réutilisation de composants existants et de configuration dynamique d'une application à partir d'un squelette d'application constituent un aspect central de cette étude qui constitue également un banc d'essai plus large pour l'évaluation de l'environnement de développement. Une description complète de cette plate-forme est disponible à l'adresse suivante : "http://sirac.imag.fr/".Bibliographie[1] Allen R., Garlan D., Formal Connectors, (CMU-CS-94-115), School of Computer Science, Carnegie Mellon University, Pittsburgh, PA 15213, March 1994.[2] Balter R., Bernadat J., Decouchant D., Duda A., Freyssinet A., Krakowiak S., Meysembourg M., Le Dot P., Nguyen Van H., Paire E., Riveill M., Roisin C., Rousset de Pina X., Scioville R., Vandôme G., "Architecture and Implementation of Guide, an Object-Oriented Distributed System", Computing Systems, Vol.4 (No.1), pp. 31-67, 91. [3] Bellissard L., Boyer F., Riveill M., "Construction and Management of Cooperative Distributed Applications", International Worshop on Object Orientation in Operating Systems (IWOOOS 95), pp. 149-152, IEEE, University of Lund - Sweeden, August 1995. [4] Bellissard L., Ben Atallah S., Kerbrat A., Riveill M., "Component-based Programming and Application Management with OLAN", Proceedings of the Workshop on Object-Based Parallel and Distributed Computation, to appear in LNCS Springer Verlag, Tokyo Japan, June 21-23 1995. [5] Bull Open Software Systems, "OODE: Une plate-forme Objets pour les Applications Coopératives", AFCET, AFCET, ed., Paris - France, Novembre 1994. [6] Magee J., Dulay N., Kramer J., "A Constructive Development Environment for Parallel and Distributed Programs", Proceedings of the International Workshop on Configurable Distributed Systems, Pittsburgh, March 1994. [7] Microsoft, The Component Object Model: Technical Overview, October 1994. [8] Object Management Group, "The Common Object Request Broker: Architecture and specification", (91.12.1), December 1991. [9] Purtilo J.M., "The POLYLITH Software Bus", ACM TOPLAS, Vol.16 (No.1), pp. 151-174, Jan. 1994. [10] Reiss S., "Connecting Tools Using Message Passing in the FIELD Environment", IEEE Software,pp. 57-66, July 1990. |
Michel RIVEILL
Laboratoire I3S
|