Etat de l`art sur les Langages de Description d`Architecture (ADLs)

Transcription

Etat de l`art sur les Langages de Description d`Architecture (ADLs)
Etat de l’art sur les Langages de Description
d’Architecture (ADLs)
Auteur : Projet ACCORD (Assemblage de composants par contrats en environnement
ouvert et réparti)*
Référence : Livrable 1.1-2
Date : Juin 2002
•
: Les partenaires du projet ACCORD sont CNAM, EDF R&D, ENST, ENSTBretagne, France Telecom R&D, INRIA, LIFL et Softeam. Le projet est
conjointement financé par les partenaires et par le RNTL (Réseau National des
Techniques Logicielles).
© Projet ACCORD
Page 1 sur 62
Sommaire
1
INTRODUCTION........................................................................................................................................5
2. LES CONCEPTS DE BASE DES LANGAGES DE DESCRIPTION D’ARCHITECTURE (ADLS) ......6
2.1 LE COMPOSANT ..............................................................................................................................................6
2.2 LE CONNECTEUR ............................................................................................................................................8
2.3 LA CONFIGURATION D’ARCHITECTURE ..........................................................................................................9
3. DESCRIPTION DES PRINCIPAUX ADLS .................................................................................................11
3.1 UNICON .......................................................................................................................................................12
3.1.1 Présentation de UniCon ......................................................................................................................12
3.1.2 Avantages ............................................................................................................................................13
3.1.3 Inconvénients.......................................................................................................................................14
3.2 AESOP ..........................................................................................................................................................14
3.2.1 Présentation de Aesop .........................................................................................................................14
3.2.2 Avantages ............................................................................................................................................17
3.2.3 Inconvénients.......................................................................................................................................17
3.3 DARWIN .......................................................................................................................................................17
3.3.1 Présentation de Darwin.......................................................................................................................17
3.3.2 Avantages de Darwin ..........................................................................................................................21
3.3.3 Inconvénients de Darwin.....................................................................................................................22
3.4 RAPIDE ........................................................................................................................................................22
3.4.1 Présentation de Rapide .......................................................................................................................22
3.4.2 Avantages ............................................................................................................................................24
3.4.3 Inconvénients.......................................................................................................................................24
3.5 WRIGHT .......................................................................................................................................................25
3.5.1 PRÉSENTATION DE WRIGHT ......................................................................................................................25
3.5.2 Avantages ............................................................................................................................................30
3.5.3 Inconvénients.......................................................................................................................................31
3.5 C2................................................................................................................................................................32
3.5.1. Présentation de C2 .............................................................................................................................32
3.5.2 Avantages ............................................................................................................................................40
3.5.3 Inconvénients.......................................................................................................................................40
3.6 OLAN ...........................................................................................................................................................41
3.6.1. Présentation de Olan..........................................................................................................................41
3.6.2 Avantages ............................................................................................................................................50
3.6.3 Inconvénients.......................................................................................................................................51
3.7 ACME .........................................................................................................................................................51
3.7.1 Présentation d’ACME .........................................................................................................................51
3.7.2 Avantages ............................................................................................................................................56
3.7.3 Inconvénients.......................................................................................................................................56
4. COMPARAISON DES DIFFÉRENTS ADLS PRÉSENTÉS ......................................................................56
5. CONCLUSION VIS À VIS DU PROJET ACCORD ...................................................................................62
6. BIBLIOGRAPHIE...........................................................................................................................................63
© Projet ACCORD
Page 2 sur 62
1 Introduction
Les principales difficultés rencontrées lors de la conception de logiciel telles que la gestion de
complexité, de la conformité ou encore de l’interopérabilité ne trouvent que des réponses
partielles dans la programmation orientée objet ou encore dans les environnements de type
middleware. Face à ces difficultés, les réactions sont de natures différentes. Certaines
entreprises préfèrent maintenant acheter des logiciels ou des composants plutôt que
développer. Certains concepteurs favorisent le prototypage rapide et la notion de raffinement.
D’autres utilisent des méthodes incrémentales de développement.
Pour mieux contrôler la complexité du logiciel, il est nécessaire d’avoir un niveau
d’abstraction élevé et de disposer de modèles qui s’approchent du modèle mental du
développeur. Une réponse possible est la définition d’une architecture du système. Une
architecture logicielle à base de composants décrit l’ensemble des composants qui la
composent, donne la définition de leur assemblage et prend en compte les structures d’accueil
nécessaires pour le déploiement et l’exploitation du système résultant. On peut dire que la
définition de l’architecture d’un système correspond à l’établissement du plan de construction
du logiciel. Elle permet la conception d’applications en se détachant de détails techniques
propres à l’environnement et en respectant les conditions fixées par les futurs utilisateurs. En
maîtrisant l’architecture conceptuelle, il est alors plus facile de gérer ses éventuelles
évolutions. En effet la modification d’un plan est plus simple que la modification d’un
système complet.
Les architectures logicielles dites explicites ont pour origine, à la fois les difficultés
rencontrées par les concepteurs de gros logiciels, les caractéristiques de la programmation à
grande échelle et également les besoins de réutilisation de logiciel. La plupart du temps,
l’architecture logicielle d’un système est spécifiée de manière informelle et intuitive par un
diagramme de type Box-and-line sans sémantique associée. Ce manque de définition
rigoureuse vient essentiellement du fait que peu de démarches de conception intègrent cette
étape, soit parce que la structure du logiciel est simple, soit parce qu’au travers de l’analyse,
les différentes structures du logiciel ont été appréhendées. Cependant, avec l’apparition de
systèmes répartis, cette étape de définition d’architecture devient incontournable.
Par cette notion de plan de logiciel, la complexité est prise en compte, les possibilités de
réutilisation sont augmentées, et il est possible d’utiliser des outils formels sur certaines
parties précises de l’architecture et de générer des parties de code automatiquement.
Des langages de description d’architecture (ou ADL pour Architecture Description Language)
répondent en partie à cette problématique en permettant la définition d’un vocabulaire précis
et commun pour les acteurs devant travailler autour la spécification liée à l’architecture
(architectes, concepteurs, développeurs, intégrateurs et testeurs). Ils spécifient les composants
de l’architecture de manière abstraite sans entrer dans des détails d’implantation, définissent
de manière explicite les interactions entre composants d’un système et fournissent un support
de modélisation pour aider les concepteurs à structurer et composer les différents éléments.
En fait, les ADLs sont un support pour la description de la structure de l’application. Ils
offrent des facilités de réutilisation des composants et des moyens de description de la
composition par description des dépendances entre composants et des règles de
communication à respecter.
© Projet ACCORD
Page 3 sur 62
Dans ce document, dans la partie 2, nous allons décrire les concepts de base proposés par les
langages de description d’architecture. Dans la partie 3, nous décrirons succinctement
différents langages de description d’architectures. Dans la partie 4 nous donnerons des
éléments de comparaison entre ces langages. Finalement nous conclurons ce travail en
donnant les éléments à retenir pour le projet ACCORD.
2. Les concepts de base des Langages de Description
d’architecture (ADLs)
Dans cette partie, nous définissons l’ensemble des concepts que nous retrouvons dans les
différents langages de description d’architecture. Ces concepts sont au nombre de trois. Le
premier est le composant, le second le connecteur, et finalement le dernier la configuration ou
encore la topologie.
Medvidovic et Taylor [1] on défini un gabarit de comparaison pour la plupart des langages de
description d’architecture existants dans les milieux académique et industriel. Leur étude
consiste, d’une part à définir les éléments communs d’un grand nombre d’ADLs (composant,
connecteur, configuration) et, d’autre part, à proposer un ensemble de caractéristiques
globales pour chaque élément fournissant ainsi un cadre commun favorisant la comparaison
entre plusieurs ADLs. Ces caractéristiques sont également un moyen d’évaluer un langage de
description d’architecture et sont considérées comme un ensemble de critères que doit prendre
en compte un langage pour être considéré comme étant un langage de description
d’architecture.
Nous reprenons leurs définitions et les caractéristiques dans la suite de la section. D’autres
définitions et classifications peuvent exister dans la communauté scientifique. Cependant,
nous considérons que l’étude de Medvidovic et Taylor est un point de vue représentant de
manière pertinente l’état de l’art sur les ADLs existants. Il faut noter que bien que les termes
utilisés dans ce qui suit ressemblent à ceux utilisés dans le modèle orienté objet, ils ne doivent
pourtant pas être confondus. En effet, les définitions proposées n’ont pas été établies dans le
but de les intégrer dans le modèle orienté objet.
2.1 Le composant
Un composant est une unité de calcul ou de stockage à laquelle est associée une unité
d’implantation. Le composant est un lieu de calcul et possède un état. Il peut être simple ou
composé ; on parle alors dans ce dernier cas de composite. Sa taille peut aller de la fonction
mathématique à une application complète. On définit deux parties dans un composant. Une
première partie, dite extérieure, correspond à son interface. Elle comprend la description des
interfaces fournies et requises par le composant. Elle définit les interactions du composant
avec son environnement. La seconde partie correspond à son implantation et permet la
description du fonctionnement interne du composant.
Les caractéristiques globales d’un composant définies par Medvidovic et Taylor sont les
suivantes :
-
l’interface,
le type,
la sémantique,
les contraintes,
© Projet ACCORD
Page 4 sur 62
-
la maintenance évolutive d’un composant,
les propriétés non fonctionnelles.
L’interface d’un composant
L’interface d’un composant est la description de l’ensemble des services offerts et requis par
le composant sous la forme de signature de méthodes, de type d’objets envoyés et retournés,
d’exceptions et de contexte d’exécution. L’interface est un moyen d’expression des liens du
composant ainsi que ses contraintes avec l’extérieur.
Le type d’un composant
Le type d’un composant est un concept représentant l’implantation des fonctionnalités
fournies par le composant. Il s’apparente à la notion de classe que l’on trouve dans le modèle
orienté objet. Ainsi, un type de composant permet la réutilisation d’instances de même
fonctionnalité soit dans un même architecture, soit dans des architectures différentes.
En fournissant un moyen de décrire, de manière explicite, les propriétés communes à un
ensemble d’instances d’un même composant, la notion de type de composant introduit un
classificateur qui favorise la compréhension d’une architecture et sa conception.
La sémantique d’un composant
La sémantique du composant est exprimée en partie par son interface. Cependant, l’interface
telle que décrite ci-dessus ne permet pas de préciser complètement le comportement du
composant. La sémantique doit être enrichie par un modèle plus complet et plus abstrait
permettant de spécifier les aspects dynamiques ainsi que les contraintes liées à l’architecture.
Ce modèle doit garantir une projection cohérente de la spécification abstraite de l’architecture
vers la description de son implantation avec différents niveaux de raffinements. La
sémantique d’un composant s’apparente à la notion de type dans le modèle orienté objet.
Les contraintes d’un composant
Les contraintes définissent les limites d’utilisation d’un composant et ses dépendances intra
composants. Une contrainte est une propriété devant être obligatoirement vérifiée sur un
système ou une de ces parties. Si celle-ci est violée, le système est considéré comme un
système incohérent et inacceptable. Elles permettent ainsi de décrire de manière explicite les
dépendances des parties internes d’un composant comme la spécification de la
synchronisation entre composants d’une même application (dépendance intra composant).
L’évolution d’un composant
Les composants sont conçus pour être des éléments de conception qui évoluent. Un ADL doit
favoriser la modification de ses propriétés (interface, comportement, implantation) sans
perturber son intégration dans les applications déjà existantes. L’évolution doit donc être
simple et s’effectuer par le biais de techniques comme le sous typage ou le raffinement.
Les propriétés non fonctionnelles d’un composant
Les propriétés non fonctionnelles (propriétés liées à la sécurité, la performance, la portabilité)
doivent être exprimées à part, permettant ainsi une séparation dans la spécification du
composant des aspects fonctionnels (aspects métiers de l’application) et des aspects non
fonctionnels ou techniques (aspects transactionnel, de cryptographie, de qualité de service).
Cette séparation permet la simulation du comportement d’un composant à l’exécution dès la
phase de conception, et de la vérification de la validité de l’architecture logicielle par rapport
à l’architecture matérielle et l’environnement d’exécution.
© Projet ACCORD
Page 5 sur 62
2.2 Le connecteur
Le connecteur correspond à un élément d’architecture qui modélise de manière explicite les
interactions entre un ou plusieurs composants en définissant les règles qui gouvernent ces
interactions. Par exemple, un connecteur peut décrire des interactions simples de type appel
de procédure ou accès à une variable partagée, mais aussi des interactions complexes telles
que des protocoles d’accès à des bases de données avec gestion des transactions, la diffusion
d’événements asynchrones ou encore l’échange de données sous forme de flux.
Un connecteur comprend également deux parties. La première correspond à la partie visible
du connecteur, c’est-à-dire son interface, qui permet la description des rôles des participants à
une interaction. La seconde partie correspond à la description de son implantation. Il s’agit là
de la définition du protocole permettant la mise en œuvre du protocole associé à l’interaction.
Le connecteur ne correspond pas nécessairement à une seule unité d’implantation,
contrairement au composant, mais peut être associé à plusieurs éléments. Par exemple, dans le
cas d’une communication de type RPC, le connecteur correspond à la fois au talon côté client,
au squelette côté serveur et au réseau de transport. A contrario, elle peut ne pas représenter
l’unité d’implantation. Elle peut aussi se traduire par une requête SQL entre une application et
une base de données, par une variable partagée, par le partage d’une file de messages, ou toute
autre forme d’implantation.
Le connecteur permet également de vérifier l’intégrité de la communication, c’est-à-dire de
vérifier que les composants peuvent être connectés. Ainsi, il permet la réutilisation et
l’adaptation des interfaces de composants déjà existants que l’on cherche à relier.
Six caractéristiques importantes définies par Medvidovic et Taylor sont à prendre en compte
pour spécifier de manière exhaustive un connecteur. Ces caractéristiques sont les suivantes :
-
l’interface,
le type,
la sémantique,
les contraintes,
la maintenance évolutive d’un connecteur,
les propriétés non fonctionnelles.
L’interface
L’interface d’un connecteur définit les points d’interactions entre connecteurs et composants.
L’interface ne décrit pas des services fonctionnels comme ceux du composant mais s’attache à
définir des mécanismes de connexion entre composants. Certains ADLs nomment ces points
d’interactions comme étant des rôles.
Le type
Le type d’un connecteur correspond à sa définition abstraction qui reprend les mécanismes de
communication entre composants ou les mécanismes de décision de coordination et de
médiation. Il permet la description d’interactions simples ou complexes de manière générique
et offre ainsi des possibilités de réutilisation de protocoles. Par exemple, la spécification d’un
connecteur de type RPC qui relie deux composants définit les règles du protocole RPC.
La sémantique
© Projet ACCORD
Page 6 sur 62
Comme pour les composants, la sémantique des connecteurs est définie par un modèle de haut
niveau spécifiant le comportement du connecteur. A l’opposé de la sémantique du composant
qui doit exprimer les fonctionnalités déduites des buts ou des besoins de l’application, la
sémantique du connecteur doit spécifier le protocole d’interaction. De plus, celui-ci doit
pouvoir être modélisé et raffiné lors du passage d’un niveau de description abstraite à un
niveau d’implantation.
Les contraintes
Les contraintes permettent de définir les limites d’utilisation d’un connecteur, c’est-à-dire les
limites d’utilisation du protocole de communication associé. Une contrainte est une propriété
devant être vérifiée sur un système ou sur l’une de ses parties. Si celle-ci est violée, le système
est considéré comme un système incohérent et inacceptable. Par exemple, le nombre
maximum de composants interconnectés à travers le connecteur peut être fixé et correspond
alors à une contrainte.
La maintenance évolutive d’un connecteur
Le changement des propriétés (interface, comportement) d’un connecteur doit pouvoir évoluer
sans perturber son utilisation et son intégration dans les applications existantes. Il s’agit de
maximiser la réutilisation par modification ou raffinement des connecteurs existants. Un ADL
donnant la possibilité de définir un connecteur doit donc permettre de le faire évoluer de
manière simple et indépendante en utilisant le sous typage ou des techniques de raffinement.
Les propriétés non fonctionnelles
Les propriétés non fonctionnelles d’un connecteur concernent tout ce qui ne découle pas
directement de la sémantique du connecteur. Elles spécifient des besoins qui viennent
s’ajouter à ceux déjà existants et qui favorisent une implantation correcte du connecteur.
La spécification de ces propriétés est importante puisqu’elle permet de simuler le
comportement à l’exécution, l’analyse, la définition de contraintes et la sélection des
connecteurs
2.3 La configuration d’architecture
Les configurations d’architecture d’application, encore appelées topologies, définissent les
propriétés architecturales de connectivité et de conformité aux heuristiques de conception,
ainsi que des propriétés de concurrence et de répartition (dans certains ADLs).
Une configuration définit la structure et le comportement d’une application formée de
composants et de connecteurs. Une composition de composants, appelée dans certains
contextes composite, est une configuration. La configuration structurelle de l’application
correspond à un graphe connexe des composants et des connecteurs formant l’application.
Elle détermine les composants et les connecteurs appropriés à l’application et vérifie la
correspondance entre les interfaces des composants et des connecteurs. La configuration
comportementale, quant à elle, modélise le comportement en décrivant l’évolution des liens
entre composants et connecteurs, ainsi que l’évolution des propriétés non fonctionnelles
comme les propriétés spatio-temporelles ou la qualité de service. Elle définit également le
schéma d’instanciation des composants au moment de l’initialisation de l’application, ainsi
que le placement des composants sur les sites au moment du démarrage du système et leur
évolution pendant la vie de l’application.
Neuf caractéristiques sont précisées par Medvidovic et Taylor pour évaluer la configuration
d’un ADL. Ces caractéristiques sont les suivantes :
© Projet ACCORD
Page 7 sur 62
-
un formalisme commun,
la composition,
le raffinement et la traçabilité,
l’hétérogénéité,
le passage à l’échelle,
l’évolution de la configuration,
l’aspect dynamique de l’application,
les contraintes,
les propriétés non-fonctionnelles.
Un formalisme commun
Une configuration doit permettre de fournir une syntaxe simple et une sémantique permettant
de
- faciliter la communication entre les différents partenaires d’un projet (concepteurs,
développeurs, testeurs, architectes),
- rendre compréhensible la structure d’une application à partir de la configuration sans
entrer dans le détail de chaque composant et de chaque connecteur,
- spécifier la dynamique d’un système, c’est-à-dire l’évolution de celui-ci au cours de son
exécution.
La composition
La définition de la configuration d’une application doit permettre la modélisation et la
représentation de la composition à différents niveaux de détail. La notion de configuration
spécifie une application par composition hiérarchique. Ainsi un composant peut être composé
de composants, chaque composant étant spécifié lui-même de la même manière, jusqu’au
composant dit primitif, c’est-à-dire non décomposable. L’intérêt de ce concept est qu’il
permet la spécification de l’application par une approche descendante par raffinement, allant
du niveau le plus général formé par les composants et les connecteurs principaux, définis euxmêmes par des groupes de composants et de connecteurs, jusqu’aux détails de chaque
composant et de chaque connecteur primitifs.
Le raffinement et la traçabilité
La configuration est également un moyen de permettre le raffinement de l’application d’un
niveau abstrait de description général vers un niveau de description de plus en plus détaillé, et,
ceci, à chaque étape du processus de développement (conception, implantation, déploiement).
Ainsi il est possible, par la définition de la configuration, de garder trace de ce qui a été fait en
amont, et de créer des liens entre les différents niveaux de description de l’application. Cette
caractéristique permet le rapprochement entre les modèles de haut niveau et le code.
L’hétérogénéité
La configuration d’un ADL doit permettre le développement de grands systèmes avec des
éléments préexistants de caractéristiques différentes. L’ADL doit être capable de spécifier une
application indépendamment du langage de programmation, du système d’exploitation et du
langage de modélisation.
Le passage à l’échelle
Les ADLs se doivent de proposer une modélisation de systèmes qui peuvent grossir en taille.
Il s’agit de prévoir le nombre d’instances et leur placement dans un environnement ainsi que
la dynamique de l’application.
© Projet ACCORD
Page 8 sur 62
L’évolution de la configuration
La configuration doit être capable d’évoluer pour prendre des nouvelles fonctionnalités
impliquant une modification ou une évolution de la structure de l’application. Elle doit
permettre de faire évoluer l’architecture d’une application de manière incrémentale, c’est-àdire par ajout ou retrait de composants et des connecteurs.
L’aspect dynamique de l’application
La configuration d’une application doit permettre la modification à l’exécution de systèmes
demandant des temps d’exécution longs ou pouvant difficilement être stoppés. Elle doit
spécifier le comportement dynamique de l’application, c’est-à-dire les changements de
l’application qui peuvent arriver pendant son exécution comme la création, ou la suppression
d’instances de composants.
Les contraintes
Les contraintes liées à la configuration viennent en complément des contraintes définies pour
chaque composant et chaque connecteur. Elles décrivent les dépendances entre les
composants et les connecteurs et concernent des caractéristiques liées à l’assemblage de
composants que l’on qualifie de contraintes inter composants. La spécification de ces
contraintes permet de définir des contraintes dites globales, s’appliquant à tous les éléments
de l’application.
Les propriétés non fonctionnelles
Certaines propriétés non fonctionnelles ne concernant ni les connecteurs et ni les composants
doivent être exprimées au niveau de la configuration. Ces contraintes sont liées à
l’environnement d’exécution. Un ADL doit donc être capable de spécifier ces contraintes au
niveau de la configuration.
3. Description des principaux ADLs
Les langages de description d’architecture sont des langages dits déclaratifs. Ils peuvent être
classés en deux grandes familles. La première correspond aux langages qui privilégient la
description des éléments de l’architecture et leur assemblage structurel, la seconde définit les
langages qui se centrent sur la description de la configuration d’une architecture et sur la
dynamique du système.
La première famille de langages correspond à une famille de langages qui est accompagnée
d’outils de modélisation, d’analyseur syntaxique et de générateur de code. La deuxième
famille de langages regroupe des langages accompagnés d’outils de modélisation et de
génération de code mais aussi d’une plate-forme d’exécution ou de simulation d’un système,
voire de modification dynamique pendant l’exécution. La particularité de ces langages est de
définir un élément d’une architecture (composant ou connecteur) comme une instance. Il
devient alors facile et simple de spécifier l’évolution dynamique d’une application au cours de
son exécution.
Nous allons dans cette section présenter les ADLs les plus connus, c’est-à-dire UniCon,
Aesop, Darwin, C2, Wright, Rapide, OLAN et ACME. Nous donnerons leurs avantages et
leurs inconvénients.
© Projet ACCORD
Page 9 sur 62
3.1 UniCon
3.1.1 Présentation de UniCon
UniCon (Universal Connector Support) est un langage de description d’architecture crée par
l’université de Carnegie Mellon en Pennsylvanie, USA dont le concepteur principal est G.
Zelesnik [2] [3].
Comme la plupart des langages, il est fondé sur trois concepts principaux qui sont le
composant, le connecteur et l’architecture.
Le composant dans ce langage est une entité d’encapsulation des fonctions d’un module
logiciel ou des données. Un composant est caractérisé par une interface qui définit les services
requis et fournis par le composant, une implantation qui permet d’établir le lien entre
l’interface du composant et sa mise en œuvre physique (code source, ou binaire) et le type
dont il dérive et qui correspond au mécanisme ou au mode de mise en œuvre du composant.
Par exemple, un composant peut être du type Process si celui-ci s’exécute dans un processus
particulier ; il peut être de type SeqFile s’il représente un fichier ; de plus, le type du
composant impose un ensemble d’opérations possibles pour ce type de composant ; ces
opérations sont définies par des types de Players ; par exemple, le type SeqFile représentant
un fichier à accès séquentiel n’est associé qu’au type de Player ReadNext et WriteNext
correspondant respectivement à la récupération d’une lecture ou à l’écriture dans un fichier ;
ainsi un type de Player permet de spécifier un mécanisme d’accès à un service fourni ou
requis du composant. Les types de composant sont prédéfinis par le langage UniCon.
L’implantation d’un composant peut être primitive ou composite.
La déclaration syntaxique d’un composant se fait de la manière suivante :
COMPONENT Name
INTERFACE IS
TYPE ComponentType
< Liste des propriétés du composantType >
< Liste des Players du composant>
END INTERFACE
IMPLEMENTATION IS
< Liste de Propriétés >
Implementation Primitive | Implémentation Composite
END IMPLEMENTATION
END Name
Le connecteur permet de spécifier les règles d’interconnexion de composants. Un connecteur
est caractérisé par un protocole défini par un type de connecteur et une implantation.
Le protocole est défini par le type du connecteur choisi dans la liste fournie par UniCon. Par
exemple, le type de connecteur RemoteProcCall permet de relier des composants de type
Process. Ce protocole spécifie également des points de branchements autorisés pour les
composants; ces points d’entrées ou de sorties sont définis par des Rôles auxquels les players
d’un composant peuvent être interconnectés. Un type de connecteur possède un ensemble de
Rôles prédéfinis pour ce connecteur. Par exemple, le type de connecteur RemoteProcCall
possède deux rôles, le rôle Definer (l’appelé) et le rôle Caller (l’appelant) qui permettent
l’interconnexion des Players RPCDef et RPCCall. Un Rôle est décrit par un nom, un type et
© Projet ACCORD
Page 10 sur 62
d’autres attributs tels qu’une spécification fonctionnelle ou des contraintes d’utilisation. De
plus, un type de Rôle n’autorise que le branchement d’un type de Player. Par exemple, le rôle
Definer du connecteur RemoteProcCall n’autorise que le branchement du player RPCDef.
L’implantation fait le lien entre un connecteur et son implantation. La version actuelle de
UniCon ne permet pas la définition de l’implantation de connecteur formé de plusieurs
connecteurs (connecteur composite). De plus, les éléments faisant partie de l’implantation
d’un connecteur primitif sont tous définis et générés par UniCon (mot clé BUILTIN). Ainsi, il
n’est pas possible, pour l’instant, d’associer au connecteur UniCon une implantation créée
sans l’aide de cet ADL.
La déclaration syntaxique d’un connecteur se fait de la manière suivante :
CONNECTOR Name
PROTOCOL IS
TYPE ConnectorType
< Liste des propriétés du connecteurType >
< Liste des rôles du composant> :
ROLE NomRole IS RoleType
< Liste des propriétés de définition du rôle tel que le nombre
composants connectés >
END ROLE
END PROTOCOLE
IMPLEMENTATION IS
BUILTIN
END IMPLEMENTATION
END Name
Une architecture est la représentation d’une architecture d’une application définie par un
composant composite dont l’implantation spécifie les interfaces des composants utilisés dans
l’architecture, les connecteurs utilisés et les interactions entre les composants de
l’architecture.
L’interface du composant composite existe mais ne spécifie rien. C’est une interface de type
général (General) utilisée lors de la définition d’une architecture pour se caler au modèle de
description de composants que Ceux-ci soient composants primitifs ou composites. Toutefois,
elle permet de définir un nouveau composant correspondant au système.
3.1.2 Avantages
UniCon est à la fois un modèle de type et un langage clairement défini et délimité permettant
la spécification de différents types de composants et de connecteurs. A partir de ce langage,
des spécifications permettent la génération de code et la vérification de la cohérence entre
l’implantation et la spécification, que ce soit au niveau composant, connecteurs ou
architecture. Cela accroît les possibilités de raffinement, et par conséquent de réutilisation.
De plus, UniCon permet de caractériser de manière explicite les interactions entre
composants. En effet, une interaction peut être un appel RPC ou une lecture d’un fichier
séquentiel. Une interaction possède des règles précises (protocole de communication) et des
contraintes explicites notamment grâce aux players et aux rôles. Par exemple, on ne peut pas
spécifier des incohérences la suivante : la définition d’une procédure d’un composant
processus (Process) appelée par un composant de type Fichier séquentiel (SeqFile).
© Projet ACCORD
Page 11 sur 62
Les composants et les connecteurs peuvent être décrits de manière indépendante.
L’architecture les regroupera et validera la pertinence de leur mise en commun. Cette
indépendance facilite également leurs réutilisations pour définir une nouvelle architecture.
UniCon facilite l’intégration de logiciels existants (exécutables, source, objets). Enfin, le
langage est associé à un environnement complet, fourni et développé par l’université de
Carnegie Mellon qui possède :un éditeur graphique permettant de définir des composants et
des connecteurs UniCon et de décrire la structure d’une architecture sous forme de graphe de
connexion entre composants et connecteurs ainsi que l’assemblage, un analyseur syntaxique
et un compilateur permettant de vérifier la bonne utilisation des éléments du modèle, et
finalement un générateur de code en langage C.
3.1.3 Inconvénients
Le langage UniCon n’est pas un langage homogène pour la description des interfaces, comme
l’est par exemple l’IDL. En effet, la signature des services est en partie dépendante du langage
de programmation, notamment pour la description des paramètres en entrée et en sortie d’un
service de composant. De plus, ce langage est semi formel et reste donc limité pour
l’expression de la sémantique.
Le modèle de type proposé est défini sans extension possible ; il n’est donc pas possible
d’ajouter un nouveau type de connecteur ou de composant au modèle. De plus, ce modèle
n’est pas suffisamment abstrait et reste dépendant de l’implantation. En effet un composant
ne peut dériver que d’un type représentant un mécanisme ou un moyen de mise en œuvre
parmi ceux fixés par l’ADL. Comme le modèle n’est pas extensible, il n’est donc pas possible
de créer un type indépendant d’un quelconque artefact d’implantation. Cette lacune est
quelque fois gênante dans le processus de développement puisqu’elle ne permet pas de
s’affranchir, lors de la spécification d’un système, des détails de l’architecture technique et
physique.
La spécification de la dynamique de l‘application, c’est-à-dire le schéma de création
/suppression des composants n’est pas possible. Il n’existe pas d’abstraction permettant de la
décrire. Le cycle de vie d’une application ne peut donc pas être spécifié.
Les moyens pour spécifier des propriétés non fonctionnelles des composants ou des
connecteurs ne sont pas nombreux et ne concernent que certains aspects comme le scheduling
de l’application qui peut être décrit au moyen d’attributs. La qualité de service, les aspects
sécurité et d’autres aspects sont omis.
3.2 Aesop
3.2.1 Présentation de Aesop
Aesop [4] est un outil permettant de fédérer une famille d’environnements pour la conception
et l’analyse d’architectures logicielles. La particularité de Aesop est de permettre la définition
de plusieurs styles d’architectures, chacun étant propre à un domaine comme par exemple le
domaine du temps réel.
Les styles d’architecture regroupent des patrons de conception d’architecture. Il existe
plusieurs styles tels que le Pipe and Filter. Ainsi un style permet de définir un vocabulaire
permettant d’identifier les éléments d’une architecture, un ensemble de règles de
© Projet ACCORD
Page 12 sur 62
configuration appliquées, une sémantique particulière et un cadre d’analyse spécifique à
chaque architecture. Chaque style créé dérive d’un style générique qui est composé des
éléments suivants : le composant, le port, le connecteur, le rôle, la configuration, la
représentation et la liaison.
Le composant représente une unité de logique fonctionnelle. Il possède une interface
définissant un ensemble de ports. Chaque port détermine un point d’interaction du composant
avec son environnement.
Le connecteur représente une abstraction définissant l’interaction entre des composants.
L’interface de celui-ci définit un ensemble de rôles. Chaque rôle caractérise les rôles joués
par un composant participant à l’interaction; cette notion est similaire à celle de UniCon ou
Wright.
La configuration est la description d’une composition de composants et de connecteurs. Les
composants sont liés aux connecteurs. Cette liaison s’établit en reliant le port du composant
au rôle du connecteur.
La représentation est un moyen d’associer n’importe quel type d’élément à une représentation
(code source, fichier). Il est à noter qu'une configuration est un cas particulier d'une
représentation (type configuration dérivé du type représentation). En effet, une configuration
décrit un composant ou un connecteur par sa représentation sous forme de l'ensemble de ses
sous-composants ou de ses sous-connecteurs.
Un composant peut être formé d’autres composants et un connecteur peut être composé
d’autres connecteurs. L’interface d’un composant composite (respectivement d’un
connecteur) est alors liée aux interfaces de ses sous-composants (respectivement de ses sous
connecteurs) par un lien appelé la liaison (ou binding) qui lie le port de l’un avec les ports des
autres (respectivement le rôle de l’un avec les rôles des autres).
Configuration
Rôle
Liaison
Composant
Port
Connecteur
Figure 1 : Eléments génériques d’une description d’architecture
Avec Aesop, chaque type du style générique est représenté par une classe au sens orienté
objet. Chaque élément est créé, suivant son type, en dérivant l’une des classes.
Objets de conception sous forme de
classe OO
Composant
Connecteur
Port
Rôle
Représentation
Liaison
Figure 2 : Classes orientées objet représentant les types des éléments composant un style
d’architecture
© Projet ACCORD
Page 13 sur 62
La figure 3 présente la spécification du style d’architecture décrivant le filtre Pipe and
Filter :
Objets de conception sous forme de classe
OO
Composant
Connecteur
Filter
Pipe
Port
Input
Rôle
Output
Source
Représentation
Sink
Binding
Configuration
PfConfiguration
Pipeline
Figure 3 : Description du style d’architecture du filtre Pipe and Filter
Ainsi l’environnement supportant le langage Aesop fournit un cadre formé de classes
implémentant les types décrits ci-dessus. Le canevas permet alors de créer des styles
d’architecture. Il fournit également un moyen d’intégrer d’autres environnements permettant
de décrire une architecture logicielle grâce à sa structure décrite par la figure 4. Un
environnement peut correspondre à une interface graphique ou un ADL comme UniCon.
Chaque environnement correspond à un ensemble d’outils qui accèdent à la base d’objets
commune à tous les environnements au moyen de l’interface « gestionnaire de conception
Aesop ». Celle ci définit les opérations pour créer et manipuler les éléments de l’architecture
comme le composant ou le connecteur. La base d’objet correspond à une base de données et
stocke les éléments de l’architecture sous forme de classes orientées objet (OO). Chaque
classe OO dérive d’une classe abstraite qui décrit un type d’élément en définissant un
ensemble de méthodes et de données pour ce type.
© Projet ACCORD
Page 14 sur 62
Environnement 2
Environnement 1
Environnement 3
Gestionnaire de conception
Aesop
Base d’objet
Figure 4 : la structure d’un environnement Aesop
3.2.2 Avantages
Le premier avantage de Aesop est qu’il permet de créer des nouveaux types de connecteurs ou
de composants en définissant des styles d’architecture. De plus, il fournit un cadre logiciel
orienté objet pouvant être utilisé avec d’autres ADLs. Par exemple, les concepts utilisés et
définis par Wright peuvent être réutilisés tels quel en créant un style propre à cet ADL, c’està-dire en définissant des sous-classes orientées objet dérivées des classes de base.
3.2.3 Inconvénients
Aesop fournit très peu de moyens pour décrire la sémantique des éléments tels que le
composant ou le connecteur. La classe abstraite est le seul moyen de décrire un type. Celle-ci
ne fournit pas un moyen formel et précis pour décrire la sémantique associée à un type.
De plus, il n’est pas possible d’exprimer la dynamique de l’application dans la configuration
(schéma d’instanciation des composants, création ou suppression des instances lors de
l’exécution).
Finalement, Aesop offre un outil fédérateur d’environnements et ne propose donc pas un
langage homogène pour la spécification de l’architecture. Cependant, cette lacune peut être
cachée par le fait qu’il permet d’intégrer les techniques de spécifications d’autres ADLs ou de
méthodes formelles.
3.3 Darwin
3.3.1 Présentation de Darwin
Le langage Darwin [5] [6] [7] est considéré comme un langage de description d’architecture,
bien que celui-ci soit souvent appelé langage de configuration. Un langage de configuration
favorise la description de la configuration d’une application, c’est-à-dire la description des
interactions entre composants. La particularité de ces langages est qu’un composant est une
entité instanciable. La description d’un composant au niveau du langage permet de créer de
multiples instances d’un composant lors de l’exécution. Ainsi, ce type de langage se centre
sur la description de la configuration et sur l’expression du comportement d’une application
plutôt que sur la description structurelle de l’architecture d’un système comme le font
© Projet ACCORD
Page 15 sur 62
beaucoup d’ADLs (UniCon, …). La particularité de Darwin est donc de permettre la
spécification d’une partie de la dynamique de l’application en terme de schéma de création de
composants logiciels avant, après ou en cours d’exécution.
Description du langage Darwin
Le concept principal de Darwin est le composant. Un composant est décrit par une interface
qui contient les services fournis et requis. Ces services s’apparentent plus aux entrées et
sorties de flots de communication qu’à la notion de fonction. Deux types de composants
existent. Le premier correspond aux composants primitifs qui intègrent du code logiciel, le
second aux composites qui sont des entités de configuration décrivant les interconnexions
entre composants.
La sémantique associée à un composant est celle du processus. Ainsi, une instance de
composant correspond à un processus créé. Il est possible d’associer au composant un
ensemble de paramètres typés d’initialisation et d’utiliser les valeurs de ceux-ci à l’intérieur
de la configuration du composite de façon à décrire la configuration de manière dynamique.
Par exemple, Darwin permet de fixer le nombre d’instances d’un composant lors de son
initialisation.
Les services requis ou fournis (require et provide) correspondent à des types d’objets de
communication que le composant utilise pour respectivement communiquer avec un autre
composant ou recevoir une communication d’un autre composant. Ainsi, les services n’ont
pas de connotation fonctionnelle. Ils décrivent les types d’objets de communication utilisés ou
autorisés à venir appeler une fonction du composant. Ces types d’objets sont définis par le
support d’exécution réparti appelé Regis et sont limités. Ainsi, à l’exécution, un composant
Darwin est un processus qui communique avec d’autres composants grâce à des objets de
communication créés et gérés par le système d’exécution Regis.
Parmi les types d’objet, le port est le plus courant : il s’agit d’un objet envoyant des requêtes
de manière synchrone ou asynchrone entre composants répartis ou non.
La syntaxe d’un composant est la suivante :
Component nom (liste de paramètres)
Provide nomPort <port, signature>
Require nomPort <port, signature>
Type de l’objet de communication
(ici le type de l’objet est le port)
Signature de la fonction du composant
Les composites sont des entités de configuration. Ils contiennent les descriptions des
interconnexions de l’application. Une application est décrite comme un composant composite.
Deux constructions syntaxiques permettent de définir des schémas d’instanciation :
- l’opérateur inst qui déclare une instance de composant sur un site particulier : cet
opérateur permet de décrire la phase d’initialisation,
- l’opérateur bind qui relie un port requis d’un composant à un port fourni d’un autre
composant : cet opérateur permet de décrire les liens entre composants au moment de
© Projet ACCORD
Page 16 sur 62
l’exécution ; cet opérateur peut servir à lier un port d’un composant composite avec un
port d’un composant primitif faisant parti du composite.
Darwin permet de décrire un schéma d’instanciation de composants très évolué. Par exemple,
il est possible de définir des variables tels que des compteurs. Il existe également des
constructions syntaxiques telles que l’itérateur forall et l’opérateur de test when. Ainsi, il est
possible de spécifier le comportement de l’application au niveau comportement global en
spécifiant la coopération des instances de composants.
Exemple
Prenons l'exemple suivant tiré de [6]. Cet exemple décrit un composant Pipeline comme une
composition d’un nombre paramétrable de filtres. Chaque filtre est rattaché au suivant, le tout
formant une « chaîne » de filtres comme le montre la figure suivante :
Pipeline
Filtre A
Filtre B
Filtre C
Filtre D
Figure 5 : Un composant de type Pipeline
Ainsi, un composant Pipeline est composé d’un ensemble de composants Filtre. De plus le
nombre de filtres n’est pas figé pour le type de composant Pipeline : un pipeline A peut être
composé de trois filtres et un pipeline B peut posséder 4 filtres; ceci pouvant se traduire de la
manière suivante: une instance de composant Pipeline A peut être composée de 3 instances de
composant Filtre et une autre instance de composant Pipeline B peut posséder 4 instances du
composant Filtre.
Le nombre de Filtres est donc un paramètre du composant Pipeline et exprime alors le nombre
d’instances du composant Filtre dans une instance de composant Pipeline.
Le composant Filtre sous Darwin s’exprime de la manière suivante :
component filtre {
provide gauche <port, int>;
require droite <port, int>,
sortie <port, int>;
}
Ce composant a un port d’entrée gauche qui récupère un entier. Si cet entier correspond au
critère de filtre du composant alors le composant le transmet par le port de sortie sortie,
sinon il est transmis via le port droite.
Le composant Pipeline sous Darwin s’exprime de la manière suivante :
component pipeline (int n) {
// Interface
provide entrée;
require sortie;
// Implantation
© Projet ACCORD
Page 17 sur 62
array F[n] : filtre;
// définition d'un ensemble d'instances de filtre
forall k: 0..n-1 {
inst F[k]; // création d'une instance de filtre
bind F[k].sortie -- sortie;
// lien avec le composant pipeline
when k<n-1
bind F[k].droite -- F[k+1].gauche;
// lien des composants
// entre eux
}
bind entrée -- F[0].gauche;
F[n-1].entrée -- sortie;
}
F[k].gauche
entrée
F[k].droite
Filtre A
Filtre B
Filtre C
Filtre D
F[k].sortie
Figure 6 : Exemple de Pipe
Darwin peut spécifier deux types d’instanciation de composants. La première, l’instanciation
dynamique, permet de spécifier la création d’une instance de composant en lui fournissant
des paramètres d’initialisation. La seconde, l’instanciation paresseuse, est une pré-déclaration
des instances effectivement créées, non pas lors de l’initialisation du composite, mais lors
d’un premier appel vers l’instance. Néanmoins, cette forme d’instanciation n’est pas
paramétrable comme l’instanciation dynamique. Elle permet, par exemple, de décrire des
structures dont la taille ne peut être déterminée que dynamiquement.
Le langage Darwin permet de décrire la répartition des composants sur des sites différents.
Celle-ci est décrite au moment de la déclaration d’instances de composants en y ajoutant un
numéro de site de création.
L’environnement Regis
Darwin fournit une syntaxe permettant de décrire une architecture sous forme de composants.
Cette architecture est implantée et exécutée dans l’environnement Regis[6].
Regis fournit un cadre écrit en C++ pour construire et exécuter des programmes distribués et
spécifiés par Darwin. Chaque composant primitif est implanté sous forme d’objet actif et
communique avec les autres composants grâce à des objets de communication qui
correspondent aux services fournis et requis de Darwin; le code C++ implantant les liens entre
ceux-ci est généré à partir des descriptions faites par le langage de description.
L’environnement Regis permet aux programmeurs d’utiliser plusieurs types d’objets de
communication tel que le port ou la diffusion multiple d’événements et autorise la création de
© Projet ACCORD
Page 18 sur 62
sortie
nouveaux styles d’interaction. Aussi, il permet de projeter la répartition des composants sur
des sites différents définis par Darwin en gérant des tables d’administration gérant les
numéros de sites.
La première version de Regis implantait chaque style d’interaction par deux patrons de classes
C++ (Template classe) dont l’un servait pour la réalisation de classe souche pour le côté
client et l’autre de classe skeleton pour le service. Les patrons favorisaient l’implantation de
services d’interaction simple (services synchrone et asynchrone). Les interactions un peu plus
sophistiquées étaient alors créées en utilisant un mixage de la délégation et de l’héritage et
l’implantation d’objets de communication typés par de nouveaux styles d’interaction
semblaient complexes. De plus, Regis ne supportait qu’un protocole de transport et ne
permettait pas d’attribuer à un lien un niveau de qualité de service approprié.
Une seconde version de Regis a été conçue pour pallier à une partie de ces lacunes. Le
canevas a été repensé et refait pour favoriser son utilisation et pour rendre simple la création
de nouveau type d’interaction. Le protocole de communication a été dissocié des classes
d’interaction permettant ainsi aux programmeurs de choisir celui qui est le plus adéquat. Les
composants propres aux protocoles de communication peuvent donc être chargés
dynamiquement et permettent aux processus clients et serveurs d’évoluer indépendamment de
ceux-ci.
Darwin possède un moyen de décrire la sémantique de manière formelle en utilisant le Picalcul. Ce dernier permet la définition précise d’algorithmes concurrents utilisés par Darwin
pour élaborer les configurations de composants, ainsi que la définition du comportement des
composants primitifs.
3.3.2 Avantages de Darwin
L’originalité de Darwin par rapport à certains langages de description d’architecture tels que
Aesop et UniCon est de fournir un moyen unique pour décrire de manière explicite les
communications entre composants et les schémas d’instanciations dynamiques des
composants.
Ce langage considère un élément de l’architecture (le composant) comme une entité pouvant
être instanciée. Ceci a pour conséquence de spécifier de manière plus précise les interactions
entre composants. En effet, il est, par exemple, utile de décrire qu’une instance de composant
est connectée à plusieurs instances d’un autre composant pendant l’exécution ou de définir un
paramètre dont la valeur sera déterminée pendant l’exécution et qui exprime la cardinalité des
liens entre composants.
Le langage de Darwin fournit une syntaxe riche permettant de décrire plus finement les
interactions entre composants en détaillant la collaboration. En effet, les instructions forall
(instruction itérative) et when (condition) sont des moyens de décrire la coopération de
plusieurs instances de composant au sein d’une application spécifiée par un composant
composite.
Darwin permet également de décrire de manière explicite la répartition des composants d’une
application en spécifiant pour chaque instance le site sur lequel elle s’exécute. Et finalement,
la séparation entre le code fonctionnel et les codes de communication et de prise en charge de
la répartition semble être complète et configurable. En effet, la séparation est totale puisque le
code de communication correspond au code des objets de communication définis par les types
© Projet ACCORD
Page 19 sur 62
d’objets de communication et elle est configurable puisque la répartition est prise en charge
par le code de communication.
3.3.3 Inconvénients de Darwin
Parmi les inconvénients de Darwin, on peut citer le fait qu’un composant n’est associé qu’à
une seule sémantique qui est le processus. Ainsi, un composant ne permet pas d’exprimer un
autre élément comme un fichier ou une mémoire partagée.
Le code d’utilisation de l’environnement Darwin/Regis n’est pas transparent pour le
programmeur. Le programmeur doit explicitement utiliser les objets de type port pour réaliser
ses communications et effectuer les créations de composants lorsqu’ils les sollicitent.
L’utilisation de divers modes de communication n’est pas configurable. Le support
d’exécution (Regis ou CORBA par exemple) doit supporter différents types de port. Par
exemple, la distinction entre des communications synchrones ou asynchrones n’est pas faite
au niveau du langage de configuration ; elle peut être faite par le programmeur de composant
qui utilise les ports de Regis pour communiquer, mais rien ne transparaît au niveau de
Darwin.
Enfin, la description de la dynamique de l’application est limitée. Par exemple, il n’est pas
possible de supprimer des composants dynamiquement ni de permettre à un composant
primitif de communiquer avec des composants dynamiquement créés.
3.4 Rapide
3.4.1 Présentation de Rapide
Rapide [8] est un langage de description d’architecture dont le but est de vérifier, par la
simulation, la validité d’une architecture logicielle donnée. Il fut proposé à l’origine au projet
ARPA (Advanced Research Projects Agency) en 1990 par l’université de Stanford, USA et la
société TRW inc.
Avec le langage Rapide, une application est construite à partir de modules ou de composants
communiquant par échange de messages ou d’événements. Rapide fournit également un
environnement composé d’un simulateur permettant de vérifier la validité de l’architecture.
Les concepts de base du langage Rapide sont les suivants: la notion d’événement, de
composant, et d’architecture.
L’événement est une information transmise, c’est-à-dire une demande de service, soit une
valeur particulière d’un attribut. Il permet de construire des expressions appelées event
patterns qui caractérisent les événements circulant entre composants. La construction de ces
expressions se fait avec l’utilisation d’opérateurs qui définissent les dépendances entre
événements. Parmi ces opérateurs on trouve l’opérateur de dépendance causal (A B),
l’opérateur d’indépendance (A
, l’opérateur de différence (A~B) et l’opérateur de
simultanéité (A and B). Ainsi, l’événement correspond à une information permettant de
spécifier le comportement d’une application.
© Projet ACCORD
Page 20 sur 62
Le composant ou le module est défini par une interface. Cette dernière est constituée d’un
ensemble de services fournis et d’un ensemble de services requis. Les services sont de trois
types :
- les services Provides fournis par le composant appelés de manière synchrone par d’autres
composants,
- les services Requires demandés par le composant appelés de manière synchrone,
- les « Actions » qui correspondent à des appels asynchrones entre composants ; deux types
d’actions existent : les actions in et out qui sont des événements acceptés et envoyés par
un composant.
L’interface contient également une section de description du comportement (clause behavior)
du composant. Cette dernière correspond au fonctionnement observable du composant
comme, par exemple, l’ordonnancement des événements ou des appels aux services. Ainsi,
l’environnement Rapide peut simuler le fonctionnement de l’application.
De plus, Rapide permet également de spécifier des contraintes (clause constraint) qui sont des
patrons d’événements qui doivent ou non se produire pour un composant lors de son
exécution. Par exemple, une contrainte peut fixer un ordre obligatoire pour une séquence
d’événements d’un composant. En général, ces contraintes permettent de spécifier des
restrictions sur le comportement des composants.
L’architecture contient la déclaration des instances de composants et les règles de connexions
entre ces instances. Toutes les instances sont déclarées sous forme de variables. La règle
d’interconnexion est composée de deux parties. La première est la partie gauche qui contient
une expression d’événements qui doit être vérifiée, la seconde est la partie droite qui contient
également une expression d’événements qui doivent être déclenchés après la vérification de
l’expression de la partie de gauche. Les contraintes (clause constraint) peuvent être utilisées
pour décrire l’architecture. Elles permettent de restreindre le comportement de l’architecture
en définissant des patrons d’événements à appliquer pour certaines connexions entre
composants.
Exemple de définition d’une architecture
with Client, Serveur;
...
-- déclaration des instances de composants de l'application susceptible
d'exister
?s : Client; -- fait référence à une instance de Client
!r : Serveur; -- fait référence à toutes les instances de serveur
?d : Data; -- fait référence à un bloc de paramètre d'un certain type Data
...
-- Une règle d'interconnexion
?s.Send(?d) => !r.Receive(?d);;
-- Si un client transmet un événement de type Send avec ce type de
paramètres,alors, l'événement est transmis à tous les serveurs de
l'application avec ces paramètres.
Figure 7 : Exemple d'expression d'événement Rapide avec un client et un serveur
Les parties gauches et droites peuvent être connectées par trois types d’opérateurs :
- l’opérateur «To» connecte deux expressions d’événements simples. Il ne peut y avoir
qu’un événement possible vers un composant. Si la partie gauche est vérifiée alors
l’expression de la partie droite permet le déclenchement de l’événement vers l’unique
© Projet ACCORD
Page 21 sur 62
composant désigné par cette expression. Cet opérateur permet de spécifier un appel de
type RPC.
-
l’opérateur « connecte deux expressions quelconques. Dès que la partie gauche est
vérifiée, tous les événements contenus dans la partie droite sont déclenchés. Ils sont
envoyés vers l’ensemble des destinataires désignés dans cette expression. L’ordre
d’évaluation de cette règle de connexion est quelconque. Un déclenchement de cette règle
de connexion est indépendant des autres déclenchements antérieurs ou postérieurs.
L’opérateur est appelé opérateur de diffusion.
-
l ‘opérateur « =>» est identique au précédent mais l’ordre d’évaluation des règles est
contrôlé. Un déclenchement de cette règle est causalement dépendant des déclenchements
antérieurs de cette même règle. Cet opérateur de connexion est appelé opérateur pipe-line.
3.4.2 Avantages
L’environnement de Rapide développé par l’université de Stanford est formé :
- d’un environnement textuel et graphique pour décrire la structure de l’architecture d’un
système,
- d’un analyseur syntaxique, d’un compilateur et d’un analyseur permettant de valider le
comportement des composants et de l’architecture décrite sous forme d’event pattern en
les simulant par la création d’événements causaux et grâce à l’environnement d’exécution
intégré.
L’avantage de Rapide est de permettre une expression forte de la dynamicité d’une
application avec par exemple la création, la suppression, la description plus fine du schéma
d’instanciation du composant.
3.4.3 Inconvénients
Même si les interactions entre composants peuvent être spécifiées de manière statique et
dynamique, le langage ne fournit pas un moyen de typer un connecteur. En effet, un
composant est décrit par une interface ; il est donc typé et son interface peut être réutilisée.
Par contre, un connecteur n’est pas décrit de manière explicite. Ceci ne favorise pas la
réutilisation des connecteurs, comme pour UniCon ou d’autres ADLs. Il n’existe donc pas de
modèle de typage explicite pour décrire les interactions. Celles-ci sont décrites à travers la
description de l’architecture.
De plus, les propriétés non fonctionnelles ne peuvent pas être décrites par l’interface d’un
composant. La spécification des propriétés non fonctionnelles se limite à la modélisation du
temps (définie par le langage de contrainte).
© Projet ACCORD
Page 22 sur 62
3.5 Wright
3.5.1 Présentation de Wright
Wright est un langage d’architecture logicielle [9] qui se centre sur la spécification de
l’architecture et de ses éléments. Il n’y a pas de générateur de code, ni de plate-forme
permettant de simuler l’application comme pour Rapide.
Il repose sur quatre concepts qui sont le composant, le connecteur, la configuration et le style.
La notion de composant
Un composant en Wright est une unité abstraite localisée et indépendante. La description d’un
composant contient deux parties importantes qui sont l’interface (interface) et la partie calcul
(computation). L’interface consiste à décrire les ports, c’est-à-dire les interactions auxquelles
le composant peut participer. Par exemple, un composant représentant un serveur de base de
données peut avoir deux ports, un pour les requêtes du client et un autre pour l’administrateur
pour ses propres tâches. Un port peut également être perçu comme une facette d’un
composant. A chaque port est associée une description formelle par le langage CSP spécifiant
son comportement par rapport à l’environnement. La partie calcul, quant à elle, consiste à
décrire le comportement du composant en indiquant comment celui-ci utilise les ports. Ainsi,
les ports qui sont décrits indépendamment dans l’interface, sont utilisés pour décrire le
comportement du composant dans le calcul.
Exemple de description de composant
L’exemple proposé concerne un système filtre de type pipe-filter permettant de lire un flot de
caractère pour le transformer en un flot contenant les mêmes caractères en lettre capitale et les
caractères tels qu’ils étaient en entrée du système. Le schéma représente ce système sous
forme de diagramme de type « Box-Line » :
Filtre
Majuscule
Flot de caractères Filtre
Eclateur
Filtre
Assembleur
Figure 8 : Exemple de filtres
Le système comprend trois composants :
- le composant Eclateur permettant de récupérer le flot de caractères en entrée et de créer
deux flots :
- un flot identique à celui en entrée pour le composant Majuscule pour la conversion
en lettres capitales,
- un flot identique à celui en entrée pour le composant Assembleur,
- le composant Majuscule permettant de transformer un flot de caractères en flot contenant
les mêmes caractères en lettres capitales,
© Projet ACCORD
Page 23 sur 62
-
le composant Assembleur permettant de fusionner les deux flots.
Le composant Eclateur va être décrit sous Wright de la manière suivante :
Component Eclateur
Port Input (lire les données jusqu’à la fin des données)
Port Left (sortir les données de manière permanente)
Port Right (sortir les données de manière permanente)
Computation (lire continuellement les données à partir du port Input
puis les sortir à la fois dans le port Left et le port Right)
L’interface du composant Eclateur est formé de trois ports qui sont le port Input, Left et Right.
La partie calcul (computation) du composant permet de mettre en rapport les trois ports. Les
spécifications du comportement des ports et de la partie calcul sont écrites ici de manière
informelle pour plus de compréhension. Elles sont normalement écrites avec le langage CSP.
La notion de connecteur
Un connecteur représente une interaction entre une collection de composants. Il possède un
type. Il spécifie le patron d’une interaction de manière explicite et abstraite. Ce patron peut
être réutilisé dans différentes architectures. Par exemple, un protocole de base de données
comme le protocole de validation à deux phases (two-phase commit) peut être un connecteur.
Il contient deux parties importantes qui sont un ensemble de rôles et la glue. Chaque rôle
indique comment se comporte un composant qui participe à l’interaction. Le comportement
du rôle est décrit par une spécification CSP. La glue décrit comment les participants (c’est-àdire les rôles) interagissent entre eux pour former une interaction. Par exemple, la glue d’un
connecteur appel de procédure indiquera que l’appelant doit initialiser l’appel et que l’appelé
doit envoyer une réponse en retour.
Exemple
Si on reprend l’exemple du système de filtre de type pipe-filter, les composants filtres sont
liés entre eux par des tubes. Ces tubes fonctionnent de la même façon et obéissent aux mêmes
règles. On peut donc définir le connecteur suivant définissant un tube :
Connector Pipe
Rôle Source (délivrer les données continuellement, signaler la fin et
fermer)
Rôle Sink (lire les données continuellement, fermer avant ou au
moment de la signalisation de la fin des données)
Glue (le rôle Sink reçoit les données dans le même ordre que celui
utilisé par le rôle Source pour fournir ces données).
La notion de configuration
La configuration permet de décrire l’architecture d’un système en regroupant des instances de
composants et des instances de connecteurs. La description d’une configuration est composée
de trois parties qui sont la déclaration des composants et des connecteurs utilisés dans
l’architecture, la déclaration des instances de composants et de connecteurs, les descriptions
des liens entre les instances de composants par les connecteurs.
© Projet ACCORD
Page 24 sur 62
Exemple
Si on reprend l’exemple du système de filtre de type pipe-filter, la configuration correspond à
l’architecture du système Capitale:
Configuration Capitale
Component Majuscule
…
Connector Pipe
…
1.1.1.1.1
Instances
Split :Dispatcher
Upper :Majuscule
Merge :Assembleur
P1,P2,P3 : Pipe
{
{
déclaration des composants et connecteurs
déclaration des instances de connecteur et composant
1.1.1.1.2
Attachments
Split.Left as P1.Source
Upper.Input as P1.Sink
Split.Right as P2.Source
Merge.Right as P2.Sink
Upper.Output as P3.Source
Merge.LeftasP3.Sink
End Capitalize
{
définition des liens entre les instances (mot clé
Attachments)
Wright supporte la composition hiérarchique. Ainsi, un composant peut être composé d’un
ensemble de composants. Il en va de même pour un connecteur. Lorsqu’un composant
représente un sous-ensemble de l’architecture, ce sous-ensemble est décrit sous forme de
configuration dans la partie calcul du composant.
Exemple
Dans un système client-serveur, un serveur peut être composé de plusieurs composants
comme un coordinateur fournissant une interface de services, un gestionnaire de sécurité et
une base de données.
© Projet ACCORD
Page 25 sur 62
Client
Serveur
Gestionnaire de
Sécurité
coordinateur
Base de
données
Figure 9 : un serveur composé de plusieurs composants
La configuration de l’application client- serveur est la suivante :
Configuration ArchServer
Connector …
Component …
Component ServeurType
Port Service …
Computation
Configuration SecuritéDonnée
Component Coordinateur
Component GestionSecurité
Component Base-Donnée
Connector CSConn
…
Instances
C : Coordinateur
Sec : GestionSecurité
BD : Base-Donnée
S1 : CSConn
Attachments
C.Secure as S1.Client
Sec.Service as S1.Service
…
End SecuritéDonnée
Bindings
C.combine = Service
End Bindings
Instances
…
Attachments
…
End ArchServer
© Projet ACCORD
Page 26 sur 62
Le mot-clé Bindings permet de spécifier les liens entre les ports du composant composite et
ceux des composants faisant partie du sous-système. Dans notre exemple, le port Combine du
composant Coordinateur est lié au port Service du composant ServeurType.
Le principe est le même pour les connecteurs. L’architecture du sous-système est décrit par
une configuration dans la glue du connecteur.
La notion de style
Le style d’une architecture permet de décrire un ensemble de propriétés communes à une
famille de systèmes comme, par exemple, les systèmes temps- réel ou les systèmes de gestion
de paye. Il permet de décrire un vocabulaire commun en définissant un ensemble de types de
connecteurs et de composants et un ensemble de propriétés et de contraintes partagées par
toutes les configurations appartenant à ce style.
Ainsi, Wright permet de définir des types de connecteurs et de composants pour une famille
d’architectures à la condition que ceux-ci respectent les propriétés de cette famille. Les
propriétés et les contraintes communes à une architecture peuvent être définies selon trois
caractéristiques qui sont les types d’interfaces, les paramètres et les contraintes. Les types
d’interface permettent de typer le rôle d’un connecteur ou le port d’un composant pour un
système donné. Les paramètres comprennent les informations de style pour définir des
composants ou des connecteurs avec des parties de leurs descriptions qui peuvent être en
paramètre comme par exemple la partie calcul. Finalement, les contraintes sont des prédicats
logiques de premier ordre qui doivent être satisfaits pour tous les éléments appartenant au
style.
Chaque partie d’un élément de l’architecture sous Wright (glue du connecteur, rôles du
connecteur, calcul ou ports d’un composant, configuration de l’architecture du système,
interface de type) a une spécification décrivant le comportement de celle-ci. Le modèle utilisé
pour la spécification est le modèle CSP. Ainsi, à chaque comportement, est associé un process
CSP. Le process est un patron de comportement formé d’événements observables et
déclenchés par ce process (events). Les événements déclenchés par le process possèdent une
barre au dessus (notation énements observables n’en possèdent pas ; de plus, les
événements peuvent fournir (x!e) ou recevoir des données (x?e). Il est possible de définir
d’autres process tels qu’une séquence de process ou un ensemble de process exclusifs.
Exemple
L’exemple donnée ici est celui de l’architecture client /serveur repris dans [17]:
Client
Serveur
Lien
Style Client-Serveur
Component Client
Port p = request
reply
Computation =internalCompute
p.request
Component Server
Port p = request
© Projet ACCORD
reply
p.reply
Computation
§
Page 27 sur 62
Computation = p.request
internalCompute
p.reply
Computation
§
Connector Link
!"$#!%
&(')
Role c = request
*!+,$-!.
/10 §
Role S = request
Glue = c.request
s.request
Glue
2 s.reply c.reply Glue
3 §
Constrains
∃! S∈ Component, ∀C ∈ Component : TypeServer(S) ∧ TypeClient(C)
⇒ Connected(C,S)
EndStyle
Les signes 4 et 5 indiquent que deux process s’exécutent de manière exclusive.
Le signe 6 indique que le process choisi est déclenché par l’environnement extérieur (on parle
de choix déterministe).
Le signe 798;:$<!8=>$?@=>$?BA? process choisi est déclenché par le process qui l’englobe (on parle
de choix non-déterministe).
Le signe § indique un process de fin normale.
L’architecture du système Client/serveur peut être décrite avec un style.
Le composant Client contient :
- le port P dont le comportement, traduit par un process, indique qu’il est à l’origine de la
requête (événement request) et à l’écoute de la réponse (événement reply)après avoir
envoyé une requête puisqu’il se termine correctement ( process §),
- une computation mettant en lien le comportement du port P et celui du composant
indiqué par l’événement internalCompute.
Le composant Server contient :
- un port P dont le comportement indique qu’il est déclencheur de l’envoi de la
réponse (événement reply) et à l’écoute de la requête (événement request) puis
qu’il se termine correctement,
- une computation mettant en lien le comportement du port et celui du composant
indiqué par l’événement internalCompute.
Le connecteur Link est composé de deux rôles :
- le rôle client (c) dont le comportement est de déclencher une requête puis d’attendre une
réponse,
- le rôle serveur (s) dont le comportement est d’attendre une requête et de déclencher une
réponse.
Il est également composé de la glue qui lie les deux rôles.
Il existe également une contrainte (mot clé constraints) spécifiant une propriété de la famille
de système client/serveur. Cette contrainte indique qu’un client est rattaché obligatoirement à
un serveur et qu’un serveur peut avoir plusieurs clients.
3.5.2 Avantages
© Projet ACCORD
Page 28 sur 62
Le premier avantage de Wright est de fournir un langage formel (CSP) pour la spécification
des composants et des connecteurs. Ainsi, les différents acteurs (concepteur, architecte,
développeur) d’un projet peuvent communiquer sans ambiguïté leurs points de vue sur
l’architecture d’une application.
Un autre point essentiel de cet ADL est qu’il sépare la notion de composant et de connecteur
en proposant un modèle de type de composant et de type de connecteur. Ainsi, un composant
peut être spécifié de manière indépendante des connecteurs, ce qui le rend nécessairement
plus indépendant par rapport à son contexte d’exécution. Le type de connecteur est considéré
comme un patron d’interconnexion et peut alors être réutilisé plusieurs fois dans une même
architecture ou dans des architectures différentes. De plus, un modèle de type de connecteur,
tel que celui de Wright permet de définir des nouveaux modes d’interconnexion. Les règles
d’assemblage entre connecteurs et composants sont faciles à vérifier grâce à la notion de rôles
pour les connecteurs et de ports pour les composants. En effet, on peut facilement vérifier par
exemple que tel composant s’assemble avec tel connecteur.
Wright permet de spécifier de manière abstraite et formelle le comportement (sémantique liée
à la dynamique) des composants, des connecteurs et de l’architecture. Pour les composants, il
définit le comportement de chaque port d’une part et, d’autre part, le comportement global du
composant avec ses ports (computation). Il permet également la spécification des connecteurs,
c’est-à-dire le comportement de chaque rôle du connecteur d’une part et, d’autre part, le
comportement global entre tous les rôles du connecteur (glue). Pour l’architecture, le
comportement des instances de composants et de connecteurs est défini ainsi que leur
assemblage de manière dynamique; en effet, Wright offre la possibilité de créer et détruire de
nouvelles instances.
Finalement, le langage permet de créer des familles de systèmes en caractérisant ceux-ci par
des contraintes et des propriétés.
3.5.3 Inconvénients
Le premier inconvénient de Wright est qu’il est difficile à assimiler. En effet, l’outil de
spécification (CSP couplé à Wright) n’est pas facile à comprendre pour un programmeur
débutant. Il peut donc s’avérer inefficace lorsque les délais d’un projet sont courts ou lorsque
les compétences font défaut.
De plus, Wright ne possède pas d’environnement d’utilisation ou d’exécution comme certains
ADLs. Il ne possède pas, par exemple, de générateur de code. Il ne propose pas non plus un
moyen de raffiner l’architecture d’une application en proposant plusieurs niveaux de
description et en sauvegardant les traces de passage de l’une à l’autre. Il ne possède pas
d’outil permettant de simuler la dynamique de l’architecture comme l’ADL Rapide.
Finalement, le langage Wright ne permet pas de spécifier les contraintes non fonctionnelles
séparément de la spécification fonctionnelle de l’architecture. Ainsi, les contraintes
fonctionnelles et non fonctionnelles sont exprimées de la même manière et sans distinction.
© Projet ACCORD
Page 29 sur 62
3.5 C2
3.5.1. Présentation de C2
C2 est un langage de description d’architecture conçu par l’université UCI en Californie [10]
[11], [12], [13]. Il fut conçu, à l’origine pour la conception des interfaces graphiques et
s’étend aujourd’hui à la conception d’autres applications.
Il propose une manière de spécifier une architecture similaire à la plupart des ADLs. En effet,
il possède trois abstractions principales qui sont le composant, le connecteur et la
configuration d’une architecture.
Au début de sa création, les buts principaux de C2 étaient les suivants :
- permettre la conception d’interfaces graphiques sous forme de composants et de
connecteurs pour pouvoir réutiliser certains composants comme les dialogues dans
plusieurs applications différentes,
- composer des systèmes graphiques indépendamment du langage de programmation et
dans un environnement distribué et hétérogène.
Aujourd’hui, l’idée de cet ADL est de définir une application sous forme de réseau de
composants s’exécutant de manière concurrente, liés par des connecteurs et communiquant de
manière asynchrone par envoi de messages. Un composant défini dans une architecture C2 est
à l’écoute des composants qui sont situés au-dessus de lui et produit des événements pour les
composants situés en-dessous de lui. Chaque composant et chaque connecteur possèdent un
haut (« top ») et un bas (« bottom »). Le haut d’un composant doit être connecté au bas d’un
seul connecteur et le bas d’un composant est connecté au haut d’un connecteur unique. Ainsi,
un composant est rattaché à l’architecture d’un système grâce à deux connecteurs dont l’un lui
permet d’envoyer à travers sa partie « bottom » des événements à d’autres composants et dont
l’autre lui permet d’en recevoir à travers sa partie « top » (cf Figure 10). Un connecteur peut
accepter plusieurs composants. Il n’y a pas de limites du nombre de composants liés à un
connecteur.
Le composant Comp3 est
à l’écoute du composant
Comp 1 via le connecteur
Conn 1. Il produit des
événements qu’il diffuse
aux
autres
composants
situés en-dessous de lui par
Figure 10 : Architecture définie parleC2connecteur Conn 2.
La notion de composant
Chaque composant C2 a son propre état et son propre fil de contrôle. Il est composé :
© Projet ACCORD
Page 30 sur 62
-
-
d’une partie appelée haut (top) qui spécifie l’ensemble des événements que le composant
reçoit par le connecteur situé au-dessus de lui et pour lesquels il exécute des actions et
l’ensemble de services requis par celui-ci. Elle correspond, d’une part, à la spécification
des services requis et, d’autre part, aux notifications provoquées par des changements
d’états des composants situés au dessus du composant C2.
d’une partie appelée bas (bottom) qui spécifie un ensemble d’événements que le
composant émet à travers l’architecture pour les composants situés en dessous de lui et un
ensemble de services fournis. Elle correspond à la spécification des services fournis et à
celle des notifications émises par le composant suite à un changement d’état.
La structure interne d’un composant C2 est formée (cf Figure 11) :
- d’un objet au sens orienté objet plus ou moins complexe (Internal object),
- d’un encapsuleur (wrapper) qui, à chaque fois qu’une routine de l’interface de l’objet est
appelée, réifie cette invocation et transforme les valeurs retournées sous forme
d’événements destinés aux composants placés sous celui-ci et véhiculés par le connecteur,
- d’un sous-composant appelé ‘traducteur de domaine’ qui transforme, d’une part les
requêtes du composant en requêtes compréhensibles par le domaine de l’architecture et
d’autre part, les événements reçus en événements compréhensibles par le composant
(Domain translator),
- d’une partie, possédant son propre fil de contrôle et permettant de dialoguer et de fixer des
contraintes avec le composant pour les situations suivantes (Dialog and Constraints):
- en réaction à un événement reçu par un connecteur placé au dessus du composant,
- pour répondre à une demande de requête reçue du connecteur situé en dessous du
composant ; par exemple, elle peut choisir d’exécuter la requête immédiatement ou
la différer, pour fixer des contraintes de traitement comme par exemple le redimensionnement obligatoire de certains champs.
Figure 11 : Structure interne d’un composant
Cette architecture permet d’intégrer des composants existants. Un composant existant est
considéré alors comme un objet interne à qui on associe un traducteur de domaine, un
encapsuleur et une partie «dialogue et contrainte». L’architecture permet également de créer
© Projet ACCORD
Page 31 sur 62
des sous-types de composants et donc de créer une composition de composant. En effet, un
composant C2 peut être formé d’un objet interne qui est un autre composant C2. On peut donc
créer une hiérarchie de composants.
L’interface d’un composant est décrite par un langage prototype C2 SADL dont la partie IDN
(Interface Définition Notation) est dédiée à la spécification des composants. La syntaxe
principale de description du composant est présentée ci-dessous. Elle utilise la notation BNF
Component : :=
component component_name is
Interface component_message_interface
Parameters component_parameters
Methodes component_methodes
Behavior component_behavior
Context component_context
end component_name
La partie Interface est composée de deux parties :
component_message_interface : : =
top_domain_interface
bottom_domain_interface
/* représente le haut d’un composant
/* représente la bas d’un composant
Chaque partie est décrite comme suit :
top_domain_interface : :=
top_domain is
out interface_requests
/* représente les services requis
/* du composant
in interface_notifications /* représente les événements
/*reçus
bottom_domain_interface : :=
bottom_domain is
out interface_notifications /* représente les événements
/* fournis par le composant
in interface_requests /* représente les services fournis
/* du composant
La partie Paramètres spécifie la liste des paramètres du composant. La partie Methodes
spécifie la liste complète des signatures de méthodes (procédures ou fonctions) de l’objet
associé au composant. La partie Behavior spécifie le comportement que doit avoir le
composant, au début de son exécution (initialisation), à la fin de son exécution, à chaque
changement d’état du composant (dans ce cas, le changement d’état est associé à une méthode
à exécuter et à un ensemble d’événements à déclencher par le composant), et lors de la
réception d’événements (dans ce cas, l’événement est associé à une méthode de l’objet à
exécuter et à d’autres événements que le composant doit générer après exécution de la
méthode).
La notion de connecteur
Les connecteurs permettent de lier plusieurs composants. Ils permettent, d’une part de diffuser
les messages (demandes de requêtes ou événements) envoyés et destinés aux composants et
© Projet ACCORD
Page 32 sur 62
d’autre part de filtrer certains messages. Un connecteur a une politique de filtrage parmi celles
énoncées ci-dessous :
- aucun filtrage (no filtering) : chaque message est envoyé à tous les composants reliés aux
connecteurs,
- filtrage notifié (notification filtering) : chaque événement est envoyé à tous les
composants qui se sont abonnés à cet événement,
- filtrage conditionnel (conditional) : chaque événement est envoyé aux composants suivant
certaines conditions associées au connecteur ; par exemple, cette politique est utilisée
lorsque l’on a plusieurs composants connectés du même côté du connecteur qui ont des
fonctions identiques implémentées de manière différente. Ainsi, lorsque le connecteur
reçoit l’événement associé à cette fonction, celui-ci décide, après avoir vérifier les
conditions, de le diffuser au composant le plus adéquate.
On peut spécifier un connecteur grâce à la partie ADN (Architecture Description Notation) du
langage C2 SADL permettant de décrire la configuration d’une architecture (cf paragraphe
suivant).
La notion de configuration d’une architecture
C2 permet de définir la configuration d’une architecture en spécifiant :
- la structure de l’application, c’est-à-dire les composants utilisés et les connecteurs qui
assurent les interactions entre ces composants,
- la dynamique de l’application, c’est-à-dire les changements de l’architecture au cours de
l’exécution comme par exemple l’ajout ou la suppression de composant.
La structure d’une application est spécifiée grâce à la partie ADN du langage C2 SADL.
La spécification de l’application est composée de deux parties :
- la spécification de l’architecture logicielle (a),
- la spécification de l’implantation (b).
(a) architecture ::=
architecture architecture_name is
conceptual_components conceptual_component_list
[connectors connector_list]
[architectural_topology topology]
end architecture_name;
(b) system ::=
system system_name is
architecture architecture_name with
component_instance_list
end system_name;
La description de l’architecture logicielle (a) est formée :
d’une
partie
décrivant
les
composants
utilisés
dans
l’architecture
(conceptual_components)d’une partie facultative, les connecteurs utilisés
(connectors).
d’une partie décrivant la topologie de l’application (architectural_topology), c’est-àdire l’assemblage statique des connecteurs avec les composants.
-
Les connecteurs sont décrits avec la syntaxe suivante :
connector ::=
© Projet ACCORD
Page 33 sur 62
connector connector_name is
/* déclaration d’un connecteur
message_filter message_filter_type;
/* déclaration d’une politique par défaut
end connector_name;
message_filter_type ::=
no_filtering | notification_filtering | prioritized | message_sink;
La topologie de l’application décrit l’assemblage statique des connecteurs avec les
composants. Elle offre aussi la possibilité d’exprimer une partie de la dynamique d’une
architecture grâce aux contraintes de connexion (clause ‘where’) dont les valeurs déterminent
si une instance de composant doit faire partie de l’architecture ; la syntaxe d’une topologie est
la suivante :
topology ::=
/* déclaration d’une topologie
{connector connector_name connections
top_ports
/* connexions au dessus d’un connecteur
connection_sequence
bottom_ports
/* connexions en dessous d’un connecteur
connection_sequence}
connection_sequence ::=
connection; {connection;} | null;
connection ::=
architecture_element_name /*déclaration d’une connex. dans une architec.
[where [not] connection_constraint]
/* déclaration facultative des contraintes dynamiques
[message_filter port_message_filter_type]
/* déclaration d’une politique de filtrage
[domain_translation {domain_translation_tuples}]
/* déclaration de la traduction de domaine entre deux
/* composants
architecture_element_name ::= conceptual_component_name | connector_name
port_message_filter_type
::=
no_filtering
|
notification_filtering
|
message_sink.
domain_translation_tuples
::=
(component_name.request
to
component_name.request);
|
(component_name.notification
to
component_name.notification);
La description de l’implantation (b) est formée de la liste des composants associés chacun à
une seule implantation. La syntaxe est la suivante :
component_instance_list ::=
conceptual_component_name is_bound_to
concrete_component_expression
{concrete_component_expression}
{conceptual_component_name is_bound_to
concrete_component_expression
{concrete_component_expression}}
concrete_component_expression ::= /* déclaration d’une implantation
concrete_component_name [with (parameter_instanciation)];
parameter_instanciation ::= identifier <= value {; identifier <= value}
Il est à noter que la spécification de l’architecture logicielle ne fait pas référence à des
instances de composants ou de connecteurs. La spécification de l’implantation associe un
© Projet ACCORD
Page 34 sur 62
composant à une implantation de composant. Cette association 1-1 caractérise alors une
instance de composant. De plus, Il n’y a pas de déclaration d’instances de connecteurs.
La dynamique d’une application est spécifiée grâce à la partie ACN (Architecture
Construction Notation) du langage C2 SADL. Elle permet :
- d’ajouter ou de retirer un élément (composant ou connecteur) à une architecture de
manière dynamique (a),
- de lier un composant à une implantation de composant dynamiquement (b),
- de relier ou délier un composant à un connecteur dynamiquement (c),
- d’associer une politique de filtrage à un connecteur pour un composant défini (d).
(a) architecture_modification ::=
architecture_name.modification_operator
(architecture_element_name);
modification_operator ::= add | remove
(b) system_modification ::=
system_name.bind
(architecture_element_name, architecture_element_name);
(c) architecture_welding ::=
architecture_name.welding_operator
welding_pair;
/* paire formé d’un composant et d’un connecteur
welding_operator ::= weld | unweld
/* associer ou délier un composant à un connecteur
(d) connector_filtering ::=
architecture_element_name.set_port_filter_operator
(architecture_element_name, message_filter_type);
set_port_filter_operator ::= SetTopPortFilter | SetBottomPortFilter
/* associer une politique de filtrage à un composant au haut d’un
connecteur ou au bas d’un connecteur.
Exemple
L’exemple suivant spécifie un système proposant une interface graphique permettant de
manipuler une pile. L’utilisateur peut, grâce à cette interface, empiler ou dépiler un élément
dans la pile. Le schéma de l’architecture logicielle en C2 de cette application est représenté
par la figure suivante.
© Projet ACCORD
Page 35 sur 62
StackADT
TopConnector
StackVisualization1
StackVisualization2
BottomConnector
GraphicsServer
Figure 12 : Exemple d’architecture C2
Il y a quatre composants :
le composant StackADT qui représente la pile en tant que type de donnée abstraite et qui
gère les fonctionnalités de celle-ci,
- le composant StackVisualization1 et le composant StackVisualization2 qui gèrent
deux représentations graphiques différentes de la pile,
le composant GraphicsServer qui affiche la pile sur la station de travail (serveur
identique au serveur X11),
et deux connecteurs :
-
TopConnector
BottomConnector.
Le composant StackADT avec le langage C2 SADL est défini comme ci-dessous :
component StackADT is
interface
top_domain
in
null;
out
null;
bottom_domain
in
PushElement (value : stack_type);
PopElement ();
GetTopElement ();
out
ElementPushed (value : stack_type);
ElementPopped (value : stack_type);
TopStackElement (value : stack_type);
StackEmpty ();
parameters
null;
methods
procedure Push (value : stack_type);
function Pop () return stack_type;
function Top () return stack_type;
© Projet ACCORD
Page 36 sur 62
function IsEmpty () return boolean;
behavior
received_messages PushElement;
invoke_methods Push;
always_generate ElementPushed;
received_messages PopElement;
invoke_methods IsEmpty, Pop;
always_generate StackEmpty xor ElementPopped;
received_messages GetTopElement;
invoke_methods IsEmpty, Top;
always_generate StackEmpty xor TopStackElement;
context
top_most ADT
end StackADT;
L’architecture logicielle de l’application est la suivante :
architecture StackVisualizationArchitecture is
components
top_most StackADT;
internal StackVisualization1;
StackVisualization2;
bottom_most GraphicsServer;
connectors
connector TopConnector is
message_filter no_filtering
end TopConnector;
connector BottomConnector is
message_filter no_filtering
end BottomConnector;
architectural_topology
connector TopConnector connections
top_ports StackADT;
bottom_ports
StackVisualization1;
StackVisualization2;
connector BottomConnector connections
top_ports
StackVisualization1;
StackVisualization2;
bottom_ports
GraphicsServer;
end StackVisualizationArchitecture;
Le système ou l’implantation est décrite de la manière suivante :
system StackVisualizationSystem is
architecture StackVisualizationArchitecture with
StackADT is_bound_to IntegerStack;
StackVisualization1 is_bound_to StackArtist1;
StackVisualization2 is_bound_to StackArtist2;
GraphicsServer is_bound_to C2GraphicsBinding;
end StackVisualizationSystem;
La description de la dynamique de l’architecture logicielle se fait de la manière suivante pour
l’ajout d’une nouvelle représentation, c’est-à-dire d’un nouveau composant.
NewStackVisualization à l’architecture :
StackVisualizationArchitecture.add(NewStackVisualization) ;
© Projet ACCORD
Page 37 sur 62
La connexion du nouveau composant au « bas » du connecteur TopConnector et au « haut »
du connecteur BottomConnector se fait ainsi:
StackVisualizationArchitecture.weld(TopConnector,
NewStackVisualization);
StackVisualizationArchitecture.weld(NewStackVisualization,
BottomConnector);
Et finalement, l’association du composant NewStackVisualization à l’implantation
StackArtist3 :
StackVisualizationSystem.bind(NewStackVisualization, StackArtist3);
3.5.2 Avantages
L’un des avantages de C2 est de favoriser l’intégration de composants existants et
hétérogènes:
- en rendant les composants partiellement indépendants de l’architecture ; en effet, un
composant n’est dépendant que du « haut » de l’architecture qui lui fournit les services
requis ; il est totalement indépendant du « bas » de l’architecture et de son évolution ;
- grâce à l’architecture interne d’un composant qui permet d’intégrer un composant existant
en tant qu’objet interne ;
- en interdisant le partage d’espace d’adressage entre les composants pour éliminer les
problèmes complexes de dépendance ;
- en obligeant les composants à fonctionner dans leur propre fil de contrôle.
La description de la configuration présente l’avantage de séparer la description statique et
dynamique du système et celle de l’architecture logicielle. Ainsi, la spécification de la
conception dédiée aux concepteurs peut être élaborée indépendamment de la spécification de
l’implantation dédiée aux développeurs et aux administrateurs de systèmes. Les
préoccupations de l’implantation, comme par exemple l’association entre des composants et
des programmes informatiques peuvent être mises de côté mais ne sont jamais oubliées.
Le langage C2-SADL fournit également un moyen d’exprimer la dynamique d’une
application, c’est-à-dire
- l’ajout ou la suppression d’un composant dans l’architecture logicielle,
- la création d’un lien d’un composant avec son implantation ou la substitution d’une
implantation avec une autre.
Finalement, C2 fournit une palette d’outils d’aide à la conception et à la fabrication
d’applications comme :
- deux cadres orientée objet, l’un en C++, l’autre en Java facilitant le développement, la
réutilisation, la distribution et l’hétérogénéité,
- un outil prototype de design graphique ArchStudio permettant de décrire et d’analyser une
architecture et permettant de la faire évoluer pendant son exécution.
3.5.3 Inconvénients
Parmi les inconvénients de C2, il n’y a pas de moyen de spécifications des propriétés non
fonctionnelles comme la qualité de service ou les performances d’une application.
De plus, la notion de connecteur, bien que celle-ci soit définie de manière explicite,
s’apparente plus à un filtre d’événements asynchrones et donc à une notion d’implantation
© Projet ACCORD
Page 38 sur 62
(médiateur ou bus) qu’à un patron de connexion réutilisable et donc qu’à une notion de
conception. La sémantique d’un connecteur n’est pas définie de manière précise ; en effet on
ne peut pas spécifier des rôles spécifiques joués par les composants connectés comme par
exemple les rôles dans le cas d’un appel RPC entre deux composants. Il n’y a que deux rôles
possibles : celui qui envoie des messages de manière asynchrone et celui qui en reçoit de la
même manière. Ainsi, si un appel synchrone RPC doit exister entre deux composants, celui-ci
ne pourra pas apparaître dans la spécification et apparaîtra alors lors de l’implantation.
C2 ne propose pas de moyen précis de définir un style d’architecture comme le fait l’ADL
Wright. Cette notion est pourtant nécessaire si ce langage dédié, à l’origine, à la conception
d’interface graphique veut s’étendre à d’autres types de système comme par exemple les
applications temps- réel. Ainsi, il est difficile avec C2 de créer et de réutiliser des patrons de
conception récurrents à des applications de même style. Néanmoins, ce problème est
actuellement au stade de recherche et il existe des propositions [11].
3.6 Olan
3.6.1. Présentation de Olan
Olan [14] est un langage de configuration élaboré par l’INRIA Rhône-Alpes dans le cadre du
projet SIRAC. Son but principal est de fournir un environnement complet pour la
construction, la configuration et le déploiement d’applications réparties. Plus précisément, les
fonctions sont les suivantes :
- intégrer du logiciel existant dans une application en l’encapsulant dans un composant
Olan,
- prendre en charge, de façon quasi-automatique, des mécanismes de communication
propres aux applications réparties grâce à des objets spécifiques appelés des connecteurs,
- fournir un moyen de définir une architecture de manière abstraite grâce au langage OCL
(Olan Configuration Langage) et en établissant une hiérarchie de composants connectés
entre eux,
- permettre la spécification et le déploiement d’un système réparti en décrivant et en
automatisant le placement des composants logiciels sur des nœuds physiques et en gérant,
pendant l’exécution, les canaux de communication entre ceux-ci, en fonction de propriétés
d’interconnexion définies dans la description de l’architecture logicielle du système.
Le langage OCL fournit plusieurs concepts abstraits qui sont :
- le composant primitif,
- le composant composite,
- le connecteur.
Le composant primitif est l’unité de base d’une application et l’entité d’intégration de logiciel
existant. Il est défini par une interface et une implantation.
L’interface décrit les services qu’un composant fournit et ceux qui lui sont requis. Les
services sont décrits par le langage OIL (Olan Interface Langage) qui est une extension du
langage IDL de l’OMG (il s’agit ici des spécifications Corba 2.3). Ce langage permet de
décrire les services grâce à un système de type mis en œuvre par une syntaxe décrivant les
contraintes liées aux flots de données et celles liées aux flots de contrôle. Les contraintes de
typage sur les flots de données sont exprimées par une syntaxe IDL classique. Celle-ci permet
de traduire les données paramètres des services en un format standard. Le typage des données
permet alors de générer du code en plusieurs langages (C++,C , Java, Phyton).
© Projet ACCORD
Page 39 sur 62
Les contraintes de typage sur les flots de contrôles constituent l’apport de OIL à l’IDL et sont
exprimées par les types suivants :
- un type permettant d’exprimer un service appelé ou fourni de manière synchrone (services
classiques RPC);
- un type permettant d’exprimer un service appelé ou fourni de manière asynchrone
(services d’événements).
Le tableau suivant décrit les services possibles dans Olan :
Syntaxe OIL pour le typage de Contraintes liées aux paramètres
Contraintes liées au comportement
contrôle
Provide
Le service a des paramètres en Le service fournit est un service
entrée et en sortie
synchrone (exemple : RPC)
React
Le service a des paramètres en Le service fourni est un service
entrée uniquement
asynchrone
(exemple :
service
d’événement)
Require
Le service a des paramètres en Le service requis est un service
entrée et en sortie
synchrone
Notify
Le service a des paramètres en Le service requis est un service
entrée uniquement
asynchrone
L’exemple suivant est tiré de [14] et décrit une application d’annuaires répartis dans laquelle
un client a un annuaire par pays qui fournit les services suivants :
- un service permettant de récupérer l’adresse d’une personne dans le pays en question,
- un service qui envoie de manière asynchrone un rapport des statistiques d’utilisation de
l’annuaire.
L’interface du composant Annuaire dans Olan est décrite comme suit :
Typedef sequence <*,char> statStruct;
Interface AnnuaireItf {
Readonly attribute string Pays ;
provide init() ;
// service pour rechercher une adresse à partir d’une clé
provide Lookup (in string cle, out string email) ;
// notification générée lorsqu’un rapport est envoyé
notify SendStats (in statStruct statReport) ;
} ;
L’implantation d’un composant primitif se fait par la mise en œuvre d’un composant qui
correspond à un ensemble d’entités logicielles de divers types. Le langage OCL permet la
description de cet ensemble d’entités, chacune d’entre elle correspond à un module. La section
implémentation d’un composant primitif contient la liste des modules utilisés ainsi que la
liaison explicite entre les services déclarés dans l’interface et ceux définis dans les modules.
Le module est une abstraction OCL qui décrit une entité logicielle. Il est défini par une
interface, un type de l’entité encapsulé qui caractérise par exemple le langage utilisé (C, C++)
et des informations sur la localisation et les paramètres d’utilisation des fichiers constituants
le module.
© Projet ACCORD
Page 40 sur 62
L’intégration de logiciels existants est alors facile à effectuer. L’idée est d’encapsuler le
logiciel par un composant primitif qui, associé à un ensemble d’éléments propres à
l’environnement Olan, véhiculent
- d’une part les appels de fonction ou de procédure venant de l’extérieur vers les procédures
et les fonctions des modules du logiciel existant,
- et d’autre part, les appels requis par Ceux-ci vers l’extérieur.
Les éléments de Olan sont décrits dans la figure suivante :
Figure 13 : Les éléments d’OLAN
Le composant primitif est associé pendant son exécution à :
- un seul objet au sens orienté objet qui véhicule les appels entrants et sortants,
- un talon qui homogénéise le format des paramètres passés et retournés,
- un encapsuleur, généré automatiquement par le compilateur Olan qui établit le lien entre
les procédures ou fonctions de l’objet et celles des modules.
Dans l’exemple précédent, l’implantation du composant Agenda est décrite par OCL de la
manière suivante :
primitive implementation AnnuaireImpl : AnnuaireItf
use AnnuaireMod // liste des modules utilisés
{
// liste de la projection de l’interface vers les modules
Pays -> AnnuaireMod.Pays ;
// l’attribut Pays existe dans les modules
Init -> AnnuaireMode.Init()
Lookup() -> AnnuaireMod.Lookup() ;
AnnuaireMod.Stat () -> SendStats () ;
}
L’implantation ne contient qu’un seul module, leur nombre n’étant pourtant pas limité. La
clause use contient le nom des modules intégrés qui doivent donc avoir été antérieurement
définis. Les clauses de projection matérialisées par l’opérateur « -> » fournissent un moyen de
© Projet ACCORD
Page 41 sur 62
lier un élément défini dans l’interface AnnuaireItf avec un élément du module
AnnuaireMod. Il ne s’agit pas d’une interconnexion mais d’une simple association entre les
services de l’interface et des modules sans aucune transformation de paramètres.
La définition du module rattaché à l’implantation du composant Annuaire est décrite en OCL
de la manière suivante :
module « python » AnnuaireMod : AnnuaireItf {
path : /$ {OLAN-SRC} « + » « exemples/annuaire » ;
sourceFile : « AnnuaireMod.py » ;
Le module dans l’exemple est un programme écrit en python dont le source est
situé dans le chemin définit par le mot clé path.
AnnuaireMod.py
La définition d’un composant par OCL permet de lier l’interface et l’implantation d’un
composant. Elle sert de glue.
Dans notre exemple, le composant Annuaire est défini comme suit :
Component Annuaire {
interface AnnuaireItf ;
implementation AnnuaireImpl ; }
La notion de composant composite
Un composant composite est une entité de description de la configuration et une entité de
structuration d’une application en composants coopérants. Les composites permettent de
former une hiérarchie de composants, hiérarchie partiellement ou totalement réutilisable dans
diverses applications. Le concept d’application de OCL est un composite particulier qui
correspond au sommet de la hiérarchie.
Chaque composite est formé d’une interface identique à celles des primitifs décrites
précédemment. Ils sont aussi formés d’une mise en œuvre ou « implémentation » qui contient
la déclaration des « sous-composants » nécessaires ainsi que les interconnexions entre eux. La
description d’une implantation de composite a pour buts :
-
de définir le schéma d’instanciation des sous composants ; ce schéma est statique ;
de définir la projection des services et attributs de l’interface du composite vers les sous
composants susceptibles de les réaliser ou d’en avoir besoin ; cette projection se fait de la
même manière que pour les composants primitifs en utilisant l’opérateur d’interconnexion
« -> ».
Dans l’exemple de l’application des annuaires réparties, un composant composite
correspondant à l’application est défini comme ci-dessous :
Component Appli {
// définition du composant : glue entre l’interface et l’implantation
interface AppliItf ; // interface du composant
implementation AppliImp { // implantation du composant
AnnuaireItf is Annuaire ;
//description des sous composants utilisés
AdminItf is Admin ;
ClientItf is Client ;
}
}
© Projet ACCORD
Page 42 sur 62
Implementation AppliImp : AppliItf
use AnnuaireItf, ClientItf, AdminItf
// Inclusion des interfaces des sous composants nécessaires
// Définition des instances des sous composants utilisés
// dans la configuration
client = instance ClientItf ;
annuaireFr = instance AnnuaireItf(« France »)
annuaireUk = instance AnnuaireItf (« UK ») ;
admin = instance AdminItf ;
// Projection des services de l’interface vers les services
// des sous composants
LanceClient () -> client.Init() ;
LanceAdmin() -> admin.Init() ;
…
La notion de connecteur
Le connecteur est un concept permettant de décrire une interconnexion ; celle-ci exprime
l’action de spécifier avec qui et comment les composants communiquent pendant l’exécution.
Chaque interconnexion avec l’environnement Olan contient l’initiateur de la communication
et le ou les destinataires. Elle a pour rôle de dire que, dès lors que l’initiateur effectue une
demande de communication, celle ci se passera en utilisant tel mécanisme ou protocole pour
envoyer une requête vers le ou les services des destinataires. De plus, une interconnexion met
en jeu deux parties : la partie gauche contient le service du composant initiateur d’une
communication, la partie droite les services des composants destinataires.
La validité d’une interconnexion est vérifiée par les caractéristiques de chaque connecteur qui
imposent les services que l’on peut relier ainsi que les signatures compatibles de ces services.
Le tableau suivant indique les différents connecteurs que l’on peut avoir dans Olan :
Nom
OCL
connecteur
SynCall
AsynCall
du Appelant
Appelé
Protocole
1
Service 1
Service Communication
synchrone
synchrone
synchrone
requis
fourni
1 Service
Asynchrone
Requis
© Projet ACCORD
1
Service Communication
asynchrone
asynchrone
Fourni
Implantation
dans
l’environnement Olan
Communication locale :
Appel de fonction ou de
méthode
Communication
interprocessus :
Utilisation de l’ORB
Corba ILU
Communication distante :
Utilisation de l’ORB
Corba ILU
Communication locale :
Appel de fonction dans un
thread séparé
Communication
interprocessus :
Utilisation de l’ORB
Corba ILU en asynchrone
Communication distante :
Utilisation de l’ORB
Corba ILU en asynchrone
Page 43 sur 62
RandSyncCall
1
Service 1 à N services Communication Idem que syncCall
synchrone
fournis
synchrone entre
requis
un appelant et
plusieurs
appelés.
Un des appelés
est choisi de
manière aléatoire
pour traiter le
service
Ce tableau n’est pas exhaustif. Nous verrons les autres connecteurs ultérieurement.
Dans notre exemple d’annuaires répartis, les connecteurs du composant composite
correspondant à l’application sont décrits comme suit :
Implementation AppliImp : AppliItf
use AnnuaireItf, ClientItf, AdminItf
// Inclusion des interfaces des sous composants nécessaires
// Définition des instances des sous composants utilisés dans la
// configuration
client = instance ClientItf ;
annuaireFr = instance AnnuaireItf(« France »)
annuaireUk = instance AnnuaireItf (« UK ») ;
admin = instance AdminItf ;
// Projection des services de l’interface vers les services des sous
// composants
LanceClient () -> client.Init() ;
LanceAdmin() -> admin.Init() ;
//connecteur exprimant une communication synchrone
Client.Lookup_Annuaire (cle,adresse) -> annuaireFr.Lookup(cle,adresse)
using SyncCall() ;
// connecteur exprimant une communication asynchrone
Annuaire.SendStats (statReport) -> admin.GetReport (report)
using asyncCall ()
…
L’implantation des connecteurs, une fois définie par le langage OCL dans la section
du composant composite est générée par l’environnement Olan en
plusieurs objets Phyton détaillés ci-dessous :
- deux objets adaptateurs représentant les points d’entrée et de sortie du connecteur; du
côté de l’émetteur de la requête, l’objet adaptateur fournit une fonction qui permet au
composant d’initialiser une communication en respectant les règles caractérisant le
connecteur et définies par OCL ; du côté du récepteur, l’objet adaptateur permet d’appeler
le service demandé ;
- l’objet émetteur qui correspond à une souche et qui assure l’envoi de la requête du service
demandé à travers un réseau ; dans Olan l’objet émetteur correspond à un objet de l’ORB
Corba ILU (SCConsender); cet objet n’est pas généré dans le cas où les composants qui
communiquent sont situés sur la même machine ;
- l’objet récepteur qui réceptionne la requête et l’envoie à l’objet adaptateur du composant
récepteur ; dans l’environnement Olan, cet objet correspond à un objet de l’ORB Corba
ILU (SCConnRec); il n’est pas généré dans le cas où les composants sont situés dans le
même contexte.
implementation
© Projet ACCORD
Page 44 sur 62
Les figures suivantes montrent l’implantation d’un connecteur de type synCall :
-
La première figure présente l’implantation dans l’environnement Olan d’un connecteur
dans le cas où les deux composants sont sur la même machine (même contexte).
La seconde figure présente l’implantation dans l’environnement Olan d’un connecteur
dans le cas où les deux composants sont sur des machines différentes (contextes
différents).
Figure 14 : connecteur Olan synCall dans un même contexte
Figure 15 : connecteur OLAN dans des contextes différents
Les concepts abstraits décrits ci-dessus ne permettent pas de décrire l’aspect dynamique du
comportement d’une application répartie. Il y a pourtant la notion de composant composite
© Projet ACCORD
Page 45 sur 62
qui permet de spécifier la configuration d’une application en décrivant le schéma
d’instanciation des sous-composants. Cependant, celui-ci est statique.
Le langage OCL fournit trois fonctions qui permettent d’exprimer la dynamique d’un
système l’instanciation dynamique, l’instanciation paresseuse et la notion de collection.
L’instanciation dynamique est la possibilité pour un composant client de créer, par un service
particulier défini par une syntaxe OCL, des instances d’un composant à tout moment.
L’instanciation paresseuse est la possibilité de déclarer une instance d’un composant en
retardant l’instant de sa création au premier accès. Une collection est un ensemble borné ou
non de composants ayant la même interface. La cardinalité de l’ensemble est contrôlable par
l’architecte de l’application, car une collection permet d’ajouter ou de supprimer des
composants en cours d’exécution. La demande de création ou de destruction d’une instance
par un composant client est explicite et est spécifiée par un ensemble de connecteurs présentés
dans le tableau suivant :
Nom OCL du connecteur Appelant
Appelé
Protocole
Implantation dans
l’environnement Olan
CreateInCollection
1 service fourni
au sein d’une
collection
Création d’une
instance dans une
collection puis appel
synchrone du service
appelé.
Communication locale : Appel
de fonction ou de méthode
Communication interprocessus :Utilisation de l’ORB
Corba ILU
1 service requis
Communication distante :
Utilisation de l’ORB Corba
ILU
DeleteInCollection
1 service requis
1 service fourni
Appel du service
appelé synchrone
puis suppression du
composant de la
collection
Communication locale : Appel
de fonction ou de méthode
Communication inter-processus
Utilisation de l’ORB Corba ILU
Communication distante :
Utilisation de l’ORB Corba ILU
De plus, une fois l’instance d’un composant créée, le langage OCL permet de spécifier qu’une
demande de service requis d’un composant client soit pris en charge explicitement par cette
instance. En effet, OCL propose une clause appelée clause de désignation associative
représentée par la syntaxe where qui permet de désigner un ou plusieurs composants en
fonction de la valeur de leurs attributs. Cette clause est particulièrement adaptée à l’utilisation
de composants à l’intérieur de collection.
Dans notre exemple, l’application annuaire créée un objet client lors de sa première utilisation
et inclut les annuaires dans une collection non bornée en fonction des demandes des
utilisateurs. La définition de ces exigences est exprimée par OCL comme suit :
Interface ClientItf {
provide init() ;
require Lookup_Annuaire
(in string pays, in string cle, out string adresse);
require Create_Annuaire (in string pays) ;
} ;
Implementation AppliImp : AppliItf
use AnnuaireItf, ClientItf, AdminItf
© Projet ACCORD
Page 46 sur 62
// instanciation paresseuse pour la création d’un objet client
client = dyn instance ClientItf ;
// annuaires est une collection de composants ayant l’interface AnnuaireItf
annuaires = collection [0..n]of AnnuaireItf
admin = instance AdminItf ;
…
// la création d’une instance d’annuaire dans la collection et à partir
// d’un ensemble de paramètres p se fait de manière explicite en utilisant
// un connecteur particulier défini dans la
// syntaxe OCL; puis le service Init de cet instance est appelé.
client.Create_Annuaire(p) -> annuaires.Init()
using createIncollection(p) ;
Dans notre application, un client envoie une requête vers un annuaire de la collection en
fonction du paramètre pays. La description de cette fonctionnalité est décrite par OCL
comme suit :
…
//désignation associative utilisée dans une collection
Client.Lookup_Annuaire (pays,cle,adresse) -> annuaires.Lookup(cle,adresse)
using randSyncCall()
where {
annuaires.Pays == pays ; // comparaison entre l’attribut
// pays des composants annuaires et celui du client
…
Olan et le langage OCL permettent de spécifier le placement des composants d’une
application en fonction d’un certain nombre de contraintes et de les déployer de manière
automatique en respectant les règles spécifiées.
La spécification de la répartition s’effectue par :
- les attributs d’administrations :
Un composant Olan est placé sur un nœud et est dédié à un utilisateur. Ainsi, chaque
composant possède deux attributs dont l’un (attribut Node) sert à décrire les caractéristiques
du nœud comme le nom du nœud, l’adresse IP, le type de machine, le système d’exploitation
utilisé, le numéro de version du système d’exploitation, la charge CPU moyenne du site au
moment du déploiement, la charge utilisateur moyenne du site au moment du déploiement et
l’autre (attribut User) fournit les propriétés de l’utilisateur habilité à utiliser le composant
comme le nom, l’identificateur de l’utilisateur et la liste des identificateurs des groupes de
l’utilisateur. Ces caractéristiques forment alors un espace d’exécution appelé le contexte ;
- les critères de répartition :
Associés à chaque composant, les critères de répartition correspondent à des expressions
associées à chaque champ de l’attribut d’administration choisi. Elles permettent de prendre la
décision lors du déploiement de l’application. Ces expressions indiquent une valeur ou un
ensemble de valeurs que doivent vérifier les champs des attributs dans le contexte choisi.
Les attributs et les critères de répartition sont spécifiés dans une section différente de la
section implémentation et de la section interface. Celle-ci est appelée la section management.
La définition d’un composant permet d’établir la glue entre l’interface qui définit les services
fonctionnels, l’implantation de ces services et l’administration du composant, c’est-à-dire les
règles de déploiement.
© Projet ACCORD
Page 47 sur 62
Le composant Annuaire de notre exemple a une section d’administration décrite par OCL
comme ci-dessous :
management AnnuaireMgmt : AnnuaireImpl {
Node.name == "db?.inrialpes.fr";
// un site dont le nom commence par
// db, puis un caractère dans le domaine inrialpes.fr
Node.CPULoad <= 10; // La charge moyenne constatée lors de
//l'installation doit être inférieure à 10
//(echelle de 0 à l'infini, la charge 100
// étant une utilisation standard.
Node.UserLoad <= 10;
// Nombre d'utilisateurs moyen inférieur à 10
User.name == "admin"; // appartient à l'utilisateur privilégié
}
Le composant définissant l’application Annuaire a la section management suivante :
management AppliMgmt : AppliImpl{
client.Node != annuaires.Node ;
//
//
//
//
//
Le client est sur un site différent
de la collection d'annuaires.
la collection des annuaires peut être
localisée sur plusieurs sites en
fonction des créations d'annuaires.
}
La définition du composant de l’application Annuaire sert de glue entre l’interface,
l’implantation et l’administration du composant.
component Appli {
interface AppliItf;
implementation AppliImpl {
ClientItf is Client;
AnnuaireItf is Annuaire;
};
management AppliMgmt;
}
3.6.2 Avantages
L’un des points forts de l’environnement Olan et de son langage OCL est de décrire un
composant en séparant la description de son interface de celle de son implantation et de son
administration. Ainsi lorsqu’une des parties évolue, les autres parties ne sont pas modifiées.
Par exemple lorsque l’on remplace un module utilisé par le composant, il ne faut modifier que
la partie implémentation du composant. Les différentes parties semblent être indépendantes.
De plus, la projection entre la description abstraite d’un composant et sa description concrète,
c’est-à-dire son implantation et son administration, est visible grâce à la description d’un
composant qui joue alors le rôle de glue.
OCL permet d’exprimer la description de la dynamique d’un système de manière plus précise
que certains ADLs grâce à la notion d’instanciation dynamique et paresseuse et à la notion de
collection et de désignation associative. Aussi, l’originalité de cet ADL est de proposer un
moyen de décrire l’administration d’un composant en lui associant d’une part des attributs
caractérisant, par leurs valeurs, l’utilisateur habilité à utiliser le composant et le nœud
d’accueil et en proposant d’autre part un moyen de décrire des conditions de placement sous
forme de prédicats entre les composants.
© Projet ACCORD
Page 48 sur 62
Olan fournit également un moyen de décrire des aspects non fonctionnels comme par exemple
la sécurité grâce aux valeurs de l’attribut spécifiant l’utilisateur habilité, la gestion de charge
grâce à la notion de collection et de désignation associative qui permet de contrôler le nombre
d’instances d’un composant, ou encore le déploiement en fonction de contraintes liées au
système d’exploitation et à la machine comme par exemple la charge CPU d’un site.
Cependant, la description des aspects non fonctionnels est noyée avec celle des aspects
fonctionnels.
3.6.3 Inconvénients
L’inconvénient de Olan est de proposer un modèle de connecteur qui est très lié au protocole
de communication. Par exemple, bien que les adaptateurs et les proxies soient séparés dans
l’implantation des connecteurs pour des raisons d’efficacité, cette séparation n’est pas visible
et explicite au niveau de la spécification faite à partir d’Ocl. Ainsi un type de connecteur n’est
pas instanciable avec différents protocoles de communication.
De plus, la notion de connecteur n’est pas détachée de la notion de composant. Par exemple,
la spécification d’un composant composite intègre les descriptions des traitements
fonctionnels et ceux des mécanismes de communications entre les sous composants. Le
formalisme « -> » n’est pas précis. Il représente à la fois une projection entre un élément
d’une interface d’un composite avec un élément de l’interface d’un de ces sous composants et
un mécanisme de communication.
Le modèle Olan est fortement lié à son environnement. Ainsi, on ne peut pas parler de modèle
abstrait se détachant des plates-formes gérant des applications à base de composants. De plus
la génération des objets en Phyton et l’exécution de Ceux-ci dans un environnement
développé en Phyton sont à l’origine de problèmes de performances.
Enfin, même si Olan permet de spécifier une petite partie des aspects non fonctionnels comme
nous l’avons vu dans les avantages, il ne sépare pas clairement les aspects fonctionnels et non
fonctionnels.
3.7 ACME
3.7.1 Présentation d’ACME
ACME [15] [16] est un langage de description d’architecture établi par la communauté
scientifique dans le domaine des architectures logicielles. Il a pour buts principaux de fournir
un langage pivot qui prend en compte les caractéristiques communes de l’ensemble des
ADLs, qui soit compatible avec leurs terminologies et qui propose un langage permettant
d’intégrer facilement de nouveaux ADLs.
Il a été créé sur le fait que beaucoup d’ADLs ont des points communs dans leur manière
d’analyser une architecture. En effet, la plupart des langages fournissent des notions similaires
comme le composant ou le connecteur. ACME apparaît alors plus comme un langage
fédérateur de ce qui existe que comme un langage réellement novateur.
Les fonctions principales de ACME sont les suivantes :
© Projet ACCORD
Page 49 sur 62
-
-
-
le langage fournit un ensemble de sept concepts permettant de spécifier la structure d’une
architecture (architecture ontology); il s’agit du composant, du connecteur, du système, du
port, du rôle, de la représentation et de la carte de représentation (rep-map),
le langage fournit un mécanisme d’annotation favorisant l’intégration d’informations
spécifiques ne concernant pas la structure et apportées par certains ADLs comme la
spécification comportementale de Wright (annotation mechanism),
un mécanisme permettant de créer et de réutiliser des gabarits de conception comme le
style d’une architecture,
un canevas favorisant l’intégration d’outils facilitant la spécification formelle de la
sémantique d’une architecture (open semantic framework).
Les éléments (cf figure suivante) pour la description de la structure de l’architecture sont les
suivants.
Le composant représente l’unité de traitement ou de donnée d’une application. Par exemple,
un client ou un serveur est un composant. Il est spécifié par une interface composée de
plusieurs types de ports. Chaque type de port identifie un point d’interaction entre le
composant et son environnement. Il peut s’agir, par exemple, d’une simple signature d’une
méthode ou d’un ensemble de procédures qui doivent être invoqués dans un ordre défini.
Le connecteur représente l’interaction entre composants. Il s’agit d’un médiateur de
communication qui coordonne les connexions entre composants. Par exemple, un appel RPC,
un protocole client-serveur, une diffusion d’événements sont des connecteurs. Il est spécifié
par une interface composée d’un ensemble de type de rôles. Chaque type de rôle d’un
connecteur définit un participant à une interaction.
Le système représente la configuration d’une application, c’est-à-dire l’assemblage
structurelle entre les composants et les connecteurs.
La représentation et la carte de représentation (cf figure H.b) permettent à ACME de
supporter la description hiérarchique d’une architecture. Ainsi, un composant ou un
connecteur peut être décrit d’un niveau général à un niveau plus détaillé et peut donc être
raffiné. Chaque nouvelle description (sous élément) d’un élément est appelée une
représentation. La correspondance entre l’élément et ses représentations est spécifiée grâce à
la carte de représentation. Ainsi, la carte de représentation permet d’établir la correspondance
entre les ports de l’interface d’un composant et ceux définis dans les interfaces de ses sous
composants.
L’exemple suivant décrit l’architecture client-serveur en ACME :
Figure 16 : Exemple d’architecture ACME
System simple_cs = {
© Projet ACCORD
Page 50 sur 62
Component client = { Port send-request }
Component server = { Port receive-request }
Connector rpc = { Roles {caller,callee}}
Attachments : {
client.send-request to rpc.caller ;
server.receive-request to rpc.callee}
Cette description décrit un système System composé de deux composants, le composant client
client et le composant serveur server ainsi qu’un connecteur Rpc .
L’assemblage statique est décrit par la partie Attachments.
Figure 17 : Éléments d’une description ACME
Figure 18 : Représentation et propriétés sous ACME
Les sept concepts décrits précédemment sont suffisants pour décrire la structure d’une
architecture mais sont inadéquates pour spécifier des informations plus précises liées au
© Projet ACCORD
Page 51 sur 62
domaine d’application comme par exemple le temps réel, ou liées au comportement du
système pendant son exécution.
Certains ADLs prennent en compte ces caractéristiques. ACME propose un moyen d’intégrer
Celles-ci à travers la notion de propriété (cf. Figure 18). Une propriété a un nom qui
l’identifie, un type optionnel et une valeur. Chaque élément du design décrit ci-dessus
(composant, connecteur) peut avoir une ou plusieurs propriétés.
Le type optionnel de la propriété ACME peut indiquer :
- un type simple comme un entier, une chaîne de caractère, ou un booléen,
- un type indiquant une propriété d’un sous-langage ADL comme Wright, UniCon, Rapide;
dans ce cas, le nom de la propriété indique le nom du langage,
- un type indiquant un lien externe (type « external ») avec une implantation comme par
exemple un programme.
L’architecture d’un système client/serveur est décrite avec des propriétés comme suit :
System simple_cs = {
Component client = {
Port send-request;
Properties {
Aesop-style : style-id = client-server;
propriété permettant
/* d’indiquer que le composant client dans ACME est
/* défini comme un style dans Aesop
UniCon-style : style-id = cs;
source-code : external = "CODE-LIB/client.c" }}
Component server = {
Port receive-request;
Properties {
idempotence : boolean = true;
max-concurrent-clients : integer = 1;
source-code : external = "CODE-LIB/server.c" }}
Connector rpc = {
Roles {caller, callee}
Properties {
synchronous : boolean = true;
max-roles : integer = 2;
protocol : Wright = "..." }}
Attachments {
client.send-request to rpc.caller ;
server.receive-request to rpc.callee }
}
/*
ACME fournit un moyen de décrire des gabarits de conception (templates). Cette notion est
équivalente à la notion de style d’architecture que l’on peut trouver dans la plupart des ADLs.
Le langage permet de créer des gabarits de conception paramétrables et réutilisables
permettant de spécifier des patrons de conception.
Le style d’architecture client/serveur est décrit comme suit :
Style client-server = {
Component Template client(rpc-call-ports : Ports) = {
/* un gabarit composant client
/* est spécifié avec un port /*en entrée
Ports rpc-call-ports;
Properties {
Aesop-style : style-id = client-server;
Unicon-style : style-id = cs;
source-code : external = "CODE-LIB/client.c" }}
© Projet ACCORD
Page 52 sur 62
Component Template server(rpc-receive-ports : Ports) = {
Ports rpc-receive-ports;
Properties {
Aesop-style : style-id = client-server;
Unicon-style : style-id = cs; ... }}
Template rpc(caller_port, callee_port : Port) defining (conn : Connector) =
/* un connecteur est spécifié avec un gabarit et deux
/* ports en entrée. La clause « defining »
/* signifie qu’un identifiant unique « conn » doit
/* être généré lorsque ce gabarit est utilisé
{ conn = Connector {
Roles {caller, callee}
Properties {
synchronous : boolean = true;
max-roles : integer = 2; }
protocol : Wright = "..." }}
Attachments { conn.caller to caller_port;
conn.callee to callee_port; }}
}
System complex_cs : client-server = {
/* description de la configuration d’un système
/* typé par le sytle client/serveur : c’est à
/* dire de l’assemblage statique des composants
/* au moyen des connecteurs.
c1 = client(send-request); c2 = client(send-request);
c3 = client(send-request); s1 = server(receive-request);
s2 = server(receive-request);
rpc(c1.send-request, s1.receive-request);
rpc(c2.send-request, s1.receive-request);
rpc(c3.send-request, s2.receive-request);
}
Le langage ACME a été conçu pour spécifier une architecture de manière syntaxique et ne se
focalise pas sur la sémantique. Néanmoins, il propose un cadre ( Open Semantic Framework )
fournissant une base pour décrire la sémantique d’un système de manière formelle en donnant
ainsi une manière d’imiter certains ADLs qui permettent de spécifier le comportement des
architectures.
Ainsi, le cadre fournit un moyen de projeter les aspects structurels du langage (composant,
connecteur) sur un formalisme logique basé sur des relations et des contraintes. Une
spécification est alors exprimée par un prédicat appelé une prescription.
La prescription du système client/serveur présenté dans cette section est la suivante :
exists client, server, rpc |
component(client) ^
/* le client est une variable Component
component(server) ^
/* le serveur est une variable Server
connector(rpc) ^
attached(client.send-request,
rpc.caller) ^
attached(server.receive-request,
rpc.callee) ^
client != server ^
server != rpc ^
client != rpc ^
(for all y:component (y) =>
© Projet ACCORD
Page 53 sur 62
/* il ne peut y avoir que deux composants : client et serveur
y = client | y = server) ^
(for all y:connector(y) => y = rpc) ^
(for all p,q: attached(p,q) =>
(p=client.send-request ^
q=rpc.caller)
|
(p=server.receive-request ^
q=rpc.callee))
3.7.2 Avantages
ACME se rapproche plus d’un outil que d’un langage. En effet, il ne propose pas de nouveau
formalisme ou de nouveau concept. Cependant, il sert d’intégrateur et de pivot à d’autres
ADLs. Il fournit ainsi un moyen simple et efficace :
- d’unifier les concepts proposés par les ADLs existants ; ces concepts sont essentiellement
liés à la spécification structurelle; il s’agit des éléments suivants : le composant, le
connecteur, le système, le port le rôle, la représentation et la carte de représentation ;
- de fournir une base d’artefacts standards pour de nouveaux ADLs,
- d’intégrer des notions d’ADLs existants plus spécifiques à un domaine ou à la
spécification du comportement d’un composant,
- d’intégrer des outils permettant de décrire la sémantique comme par exemple la logique de
premier ordre, grâce au canevas sémantique,
- de réutiliser ou de stocker des éléments définis antérieurement comme par exemple les
gabarits de conception ou les styles d’architecture.
3.7.3 Inconvénients
ACME ne fournit aucun moyen de spécifier de manière simple et claire la dynamique d’un
système; en effet, le système est décrit comme un ensemble d’instances de composants liées
entre eux par des connecteurs. Cependant cette description de l’assemblage reste statique.
Aucun moyen n’est fourni pour spécifier les changements de l’application au cours de son
exécution.
De plus, même si ACME est plus proche d’un outil que d’un langage, il ne fournit pas de
moyen automatique pour raffiner la spécification d’application et n’encourage pas une
description de l’application par une approche modulaire. Pourtant, la notion de représentation
aurait pu servir de base à l’automatisation de cet aspect. La génération de code n’est pas non
plus proposée par l’environnement du langage.
Enfin, les propriétés fonctionnelles et non fonctionnelles ne sont pas clairement séparées.
Cette lacune peut se justifier par le fait que la plupart des ADLs ne font pas la distinction
entre ces deux types de propriétés. Il faut toutefois noter qu’ACME autorise la spécification
des propriétés non fonctionnelles par le biais de propriétés.
4. Comparaison des différents ADLs présentés
Les avantages et les inconvénients des ADLs sont résumés dans le tableau suivant :
ADL
Principaux avantages
© Projet ACCORD
Principaux inconvénients
Page 54 sur 62
UniCon
-
-
-
Aesop
-
-
Darwin
-
-
-
UniCon est simple à utiliser car il fournit
un modèle de types de composant et de
types de connecteur prédéfinis
Il caractérise les interactions entre
composants
de
manière
explicite
(existence d’un modèle de connecteur)
Il facilite l’intégration de logiciels
existants (exécutables, sources, objets)
Il fournit un environnement de conception
complet :
- Un éditeur graphique pour décrire les
composants et les connecteurs et
l’architecture
statique
d’une
application
- Un analyseur syntaxique et un
compilateur
- Un générateur de code C.
La création de nouveaux types de
connecteur et de composant est possible
grâce au framework orienté objet associé,
L’intégration de concepts fournis par
d’autres ADLs est facilitée grâce au
framework orienté objet (ex: Wright).
Possibilité de décrire des schémas d’
instanciation dynamique,
Darwin propose une syntaxe riche pour
décrire les interactions entre composants,
Darwin permet de décrire de manière
explicite la répartition des composants
d’une application en spécifiant pour
chaque instance le site sur lequel elle
s’exécute,
Darwin/Regis sépare totalement lors de
sa génération, le code fonctionnel
(composant) et le code de communication
(connecteur)
La sémantique de la dynamique d’une
architecture (algorithmes concurrents,
comportement des composants) peut être
décrite de manière formelle grâce au Picalcul.
-
-
-
-
-
-
-
-
-
Rapide
-
-
Rapide permet d’exprimer la dynamique d’une application de manière précise et
détaillée,
Possibilité de simuler une application
grâce à la création d’événements causals
et grâce à l’environnement d’exécution
© Projet ACCORD
Langage semi-formel
La description des interfaces se fait
par le langage UniCon + un langage
de programmation
Les modèles de type de composant
et de connecteur sont des modèles
qui ne sont pas extensibles et qui
sont trop proches de l’implantation
La spécification de l’architecture
est une spécification statique
uniquement
Il y a peu de moyens pour spécifier
les propriétés non fonctionnelles.
Pas de moyen de décrire la
sémantique des éléments,
Pas de moyens d’exprimer la
dynamique de l’application,
Aesop n’est pas un langage
homogène et s’apparente plus à un
outil fédérateur.
Le composant n’est associé qu’à
une seule sémantique, le processus
(au sens système)
Lors de l’implantation du système,
l’environnement Régis n’est pas
transparent : le programmeur doit
intégrer manuellement dans son
code fonctionnel les classes
générées
par
l’environnement
Darwin/Regis correspondant aux
connecteurs appelés « objets de
communication »
dans
l’environnement Regis,
L’utilisation de divers modes de
communication
(synchrone,
asynchrone) n’est pas configurable
La description de la dynamique est
limitée
Impossibilité de décrire les
propriétés non fonctionnelles.
Pas de représentation explicite de
connecteur.
Page 55 sur 62
intégré à l’ADL.
Wright
-
-
Permet de spécifier une architecture logicielle de manière formelle et totalement
abstraite
(composant,
connecteur, configuration),
Présence d’un modèle abstrait de
composant et d’un modèle abstrait de connecteur. Les deux modèles sont
indépendants.
-
C2
-
-
-
-
Olan
-
-
ACME
-
-
C2 et son environnement favorise l’intégration de composants existants et hétérogènes
Séparation de la spécification du système
et de son architecture logicielle en fournissant des moyens pour les
rapprocher
Possibilité de décrire le schéma
d’instanciation liée à l’architecture
logicielle
Environnement complet : outils de
conception, générateur de code, outils
permettant de modifier l’architecture
pendant son exécution
Séparation nette de la description de
l’interface, de l’implantation et de
l’administration
d’une
architecture
logicielle
Possibilité de décrire le schéma
d’instanciation d’une application de
manière précise
Langage pivot et fédérateur de
l’ensemble des concepts utilisés par les
ADLs
Langage d’intégration des ADLs
existants
-
-
-
-
© Projet ACCORD
Difficile à assimiler,
Wright
ne
possède
pas
d’environnement d’utilisation ou
d’exécution (outils de modél.,
génération de code),
Wright ne possède pas de moyen de
projeter l’architecture logicielle vers
un système concret (le passage de
l'abstrait au concret est difficile),
Peu de moyens pour séparer les
spécifications fonctionnelles et non
fonctionnelles.
Langage peu formel,
Connecteur assimilé à un filtre
d’événements asynchrones et donc à
une notion d’implantation
Langage fortement orienté vers la
conception d’interfaces graphiques
Modèle de connecteur très lié aux
protocoles de communication et
donc à l’implantation d’un système
Modèle Olan fortement lié à sa
plate-forme
Plate-forme Olan présentant des gros
problèmes de performance
Langage orienté vers la spécification
structurelle
d’une
architecture
logicielle : très peu de moyen pour
exprimer la dynamique d’un système
Langage de modélisation qui n’offre
pas de moyen de projeter la
spécification d’une architecture
logicielle vers un système
Langage ne permettant pas une
séparation claire entre les propriétés
fonctionnelles et non fonctionnelles
Page 56 sur 62
Nous avons récapitulé les principaux avantages et inconvénients de chaque ADL. Il convient
maintenant de les comparer. L’étude [1] compare la plupart des ADLs sur leur façon de
représenter un composant, un connecteur ou une configuration. Dans ce rapport, nous
proposons une comparaison des langages décrits en amont en mettant en avant leur utilité et
leurs points faibles dans les différentes phases du processus de développement. Nous allons
définir dans un premier temps les phases qui nous paraissent importantes pour le processus de
développement, puis nous indiquerons ce qu’apporte chaque ADL et ce qui lui manque pour
chaque phase.
Les principales phases d’un processus de développement sont les suivantes :
- la phase d’analyse du système,
- la phase de conception du système,
- la phase d’implantation du système,
- la phase de déploiement du système,
- la phase de maintenance du système.
La phase d’analyse du système consiste à analyser les besoins fonctionnels de la future
application. Elle représente l’étape zéro de tout processus de construction de logiciel. Aucun
ADL présenté dans cette section n’est utilisé dans cette phase. En effet, tous les ADLs sont
des outils qui n’ont pas pour objectif de définir ou de modéliser des besoins.
La phase de conception du système consiste à définir les éléments ou les composants d’un
système et leurs interactions (assemblage) et à définir une architecture répondant aux besoins
modélisés dans la phase d’analyse.
Une bonne conception est conditionnée par la possibilité :
- de décrire de manière précise la structure d’une application, c’est à dire les composants du
futur système et les interactions entre ces composants, sans entrer dans des détails
d’implantation,
- de décrire le comportement de l’application (différents états et passage d’un état à l’autre)
et de simuler sa dynamique pour détecter des incohérences comme par exemple les
interblocages,
- de raffiner ce qui est spécifié,
- de proposer un moyen de rapprocher les besoins fonctionnels exprimés dans la phase
d’analyse avec la spécification de l’architecture logicielle.
Il est donc important d’avoir à ce niveau des outils de modélisation qui permettent de décrire
une architecture de manière abstraite en la raffinant et en simulant sa dynamique.
La phase d’implantation consiste à coder et à tester le système. Dans cette phase, les points
suivants sont importants :
- une projection des éléments définis de manière abstraite dans la phase de conception sur
des éléments d’implantation nouveaux ou existants doit pouvoir s’effectuer simplement,
quel que soit le langage de programmation utilisé et en restant cohérent avec la
spécification conceptuelle,
- l’assemblage des éléments de l’architecture doit pouvoir être testé sur une structure
d’accueil.
Les outils privilégiés dans cette phase sont alors :
- des outils de génération de code automatique,
- des outils d’intégration de composants logiciels existants quel que soit le langage de
programmation utilisé,
© Projet ACCORD
Page 57 sur 62
-
des outils de simulation et de tests permettant de tester la cohérence de l’assemblage des
éléments de l’architecture logicielle.
La phase de déploiement consiste à configurer le système avant son exécution. Ainsi, les
composants sont configurés en vue de leur déploiement sur des structures d’accueil. Les
points à mettre en avant dans cette phase sont les suivants :
- les configurations des éléments de l’architecture doivent pouvoir être initialisées ou
modifiées,
- le placement des éléments, lors du démarrage du système doit pouvoir être décrit et
modifiable.
Les outils intéressants pour cette phase sont des outils d’administration pouvant
- décrire les conditions de répartition des éléments de l’architecture,
- déployer automatiquement les composants suivant un plan de déploiement fixé par
l’administrateur,
- configurer les éléments de l’architecture en prenant en compte des propriétés
fonctionnelles et non fonctionnelles décrivant par exemple les propriétés à respecter par
les structures d’accueil.
La phase de maintenance consiste :
- à maintenir le système de façon à ce qu’il s’exécute de la manière la plus optimisée,
- à assurer l’évolution du système et de son architecture (maintenance évolutive) suite à
l’ajout de nouveaux besoins ou à la modification d’un ou plusieurs besoins sans modifier
ou détruire ce qui existe.
Les outils à prendre en compte à ce niveau sont des outils favorisant :
- la rétro-ingénierie et l’intégration de composants existants,
- la modification de l’architecture logicielle d’un système en exécution,
- l’analyse d’impact d’une modification de composant logiciel sur l’ensemble de
l’architecture.
Tous les ADLs ne répondent pas aux critères définis dans les phases. Le tableau suivant
récapitule ce qu’apporte un ADL pour chacune d’elle. Les points forts sont énoncés avec le
symbole {+} et les points faibles sont explicités par le symbole {-}.
REMARQUE : la colonne Analyse du tableau qui suit semble inutile. Il suffirait de dire
qu'aucun ADL n'offre de moyens dans la phase d'analyse.
Analyse
UniCon
Pas de moyens
Aesop
Pas de moyens
© Projet ACCORD
Conception
{+} Permet de définir
une
architecture
logicielle (éléments +
assemblage) grâce à son
éditeur graphique et ses
modèles de composants
et de connecteurs
{-} Les modèles sont
très
proches
de
l’implantation
Implantation
{-} Générateur de code C
uniquement
{-} Les interfaces sont
générées et doivent être
complétées
par
le
programmeur
pour
intégrer les paramètres
d’entrée et de sortie
{+} Facilite l’intégration
de logiciels existants
(exécutables,
source,
{- } Pas de spécification objets )
de la dynamique d’un
système
{+} Permet de définir {-} Très peu de moyens :
facilement et rapidement pas de générateur de
une
architecture code. Il n’y a qu’un
et
un
logicielle grâce à son framework
éditeur graphique et à son environnement
la
framework orienté objet graphique ;
pour la définition de programmation n’est pas
composant
et
de automatisée
connecteur
Déploiement
Maintenance
{-} Pas de moyen
automatique de déployer
un composant et un
connecteur : pas d’outils
pour configurer
des
composants.
{-} Pas de moyen
de modifier ou de
faire évoluer une
application
sans
modifier ce qui
existe déjà.
{-} Pas de moyens
{+}
Facilite
l’intégration
de
logiciels existants
(environnements)
Page 58 sur 62
{-}
Cadre
de {+} Facilite l’intégration
spécification très proche de logiciels existants
du modèle orienté objet (environnements)
et ne permettant qu’une
description statique de
l’application
Darwin
Pas de moyens
{+} Permet de définir
une
architecture
logicielle en spécifiant
les composants et les
communications
entre
ces composants
{-}
la
notion
de
connecteur n’est pas
explicite
{+}
Présence
d’un
framework C++ pour les
connecteurs (objet de
communication) et d’une
plate-forme,
Regis
permettant d’exécuter ce
qui est généré.
{+} Permet de décrire la
répartition
des
composants sur des sites
différents
{-}Difficile
d’intégrer
des
composants qui ne
sont
pas
développés en C++
et
suivant
le
modèle Darwin
{+} Permet de définir la
dynamique d’un système
grâce à la description du
schéma de suppression et
de création d’instances de
composants
Rapide
Pas de moyens
{+} Permet de définir
une
architecture
logicielle en spécifiant
les composants et les
communications
entre
ces composants grâce à
des événements. Forte
description
de
la
dynamique.
{-} Pas de moyens
pour reconfigurer
le système en
exécution
{+}
Présence
d’un {-} Pas de moyen
compilateur permettant
de
construire
des
modules exécutables à
partir d’une description
faite en langage Rapide
{-} Pas de générateur de
code de programmation
de
langage
connu
(C++,C, Java)
{-} Pas de moyen
{-} Pas de modèle de
connecteur explicite
Analyse
{+}
Présence
d’un
simulateur permettant de
visualiser les ordres
partiels d’événements
Conception
Implantation
Déploiement
Maintenance
Wright
Pas de moyens
{+}
Description
de
l’architecture statique et
dynamique d’un système
de manière abstraite
{-} Pas d’outils pour {-} Pas d’outils
générer du code
déploiement
{-} Pas d’environnement
ou
de
plate-forme
associée
de {+} Pas de moyens
C2
Pas de moyens
{+} Description de la
structure de l’architecture
logicielle (modèle de
composant
et
de
connecteur) et de son
comportement
{+} Framework en C++ {-} Peu de moyen pour
ou en Java permettant décrire la répartition et
d’implanter
un définir un plan de
composant
et un déploiement.
connecteur
{+} Facilité de projeter
{+} Séparation de la une
architecture
description
de logicielle sur un système
l’architecture logicielle et
de son système
{+} Intégration facile de
logiciel grâce à la
{+} Environnement de structure
interne
du
modélisation Archstudio composant C2 contenant
et ArchShell
un wrapper
Olan
Pas de moyens
© Projet ACCORD
{-} La modélisation n’est
pas toujours adaptée à
des applications qui ne
sont pas des interfaces
graphiques
{+} Séparation de la
description
de
l’interface,
de
l’implantation et
de
l’administration
d’un
système
{+}
Les
objets
d’implantation liés aux
connecteurs définis par le
modèle Olan sont générés
par l’environnement Olan
{+}
Intégration
facile de logiciel
grâce à la structure
interne
du
composant C2
{+} Possibilité de
faire
évoluer
l’architecture d’un
système en cours
d’exécution
{+} Possibilité de définir
des critères de répartition
pour des composants
d’une même architecture
au
moment
de
l’initialisation
du
{+}
Intégration
facile de logiciel
développé dans des
langages
de
programmation
différents de celui
Page 59 sur 62
ACME
Pas de moyens
système
{+} La plate-forme Olan
{+} Description détaillée permet
de
tester
du comportement du l’architecture
système
{+} Intégration facile des
composants
logiciels
développés dans des
langages
de
programmation différents
de celui utilisé pour
développer la plate-forme
Olan
utilisé
pour
développer
la
{+} Possibilité de définir plate-forme Olan
des
attributs
d’administration pour les {+} Possibilité de
des
caractéristiques du nœud modifier
d’accueil
et
les attributs
caractéristiques
des d’administration po
les
utilisateurs
d’un
ou ur
plusieurs
composants caractéristiques du
d’une même architecture nœud d’accueil et
les caractéristiques
des
utilisateurs
d’un ou plusieurs
composants d’une
même architecture
{-}
Description
de {-} Pas de génération de
l’architecture logicielle code
d’un point de vue
{-} Aucun moyen pour
structurelle
intégrer des composants
existants
{-} Pas de moyen pour {-} Aucun moyen
décrire le déploiement
des composants sur une
structure d’accueil
Par cette comparaison, on peut voir que la plupart des ADLs ne recouvrent pas tout le
processus de développement. Par contre, la plupart des ADLs fournissent des moyens pour
spécifier de manière conceptuelle une architecture logicielle.
5. Conclusion vis à vis du projet ACCORD
En conclusion, on peut dire que, vis-à-vis du projet ACCORD où nous souhaitons définir un
modèle abstrait d’assemblage de composants, les points forts des ADLs sont
-
-
-
-
-
La possibilité de description hiérarchique des composants. En effet, un ensemble de
composants peut être vu comme étant lui-même un composant, ce qui permet une
description récursive et facilite la réutilisation.
Les interactions sont décrites de façon explicite. Tous les ADLs proposent au moins une
définition d’interconnexion syntaxique. Les connecteurs sont vus comme des entités de
première classe.
Certains ADLs travaillent sur la notion de type, classe et instance. Il nous semble
important de travailler à ce niveau là, puisque nous souhaitons détailler le plus possible
l’assemblage et faciliter la réutilisation des éléments.
Certains ADLs proposent la définition de style d’architecture. Ces styles facilitent la
définition de modèle d’architecture. On peut simplement regretter que ces styles soient
souvent très simples et qu’ils ne soient pas accompagnés de conseils d’utilisation.
Certains environnements associés aux ADLs sont très complets. Ils proposent des outils de
conception, générateur de code, canevas, mécanisme pour intégrer des composants
existants (sources, exécutable) comme les ADLs C2, OLAN. Ces outils sont autant d’aide
au passage du modèle abstrait d’assemblage vers les implantations.
Les points faibles rencontrés dans les ADLs sont de plusieurs ordres. On peut citer les points
suivants :
- L’approche proposée par la plupart des ADLs est plutôt structurale, c’est-à-dire statique.
La dynamicité, la description du comportement individuels des composants, ou encore du
comportement global de l’application ne sont pas ou peu exprimées.
© Projet ACCORD
Page 60 sur 62
-
-
-
Les propriétés non-fonctionnelles ne sont pas toujours prises en compte. Il est en effet
intéressant de s’intéresser aux environnements sur lesquels les composants devront
s’exécuter, pour proposer des moyens d’adaptation.
Aucun ADL ne propose de démarche associée complète. Le langage et son utilisation
reste bien souvent à la discrétion de l’architecte et des concepteurs.
Aucune projection vers les plates-formes à base de composants actuelles, telles que les
EJB ou CCM, n’est proposée. Il semble que la projection d’une spécification
d’architecture sur une implantation n’est pas toujours simple et que ce point essentiel ne
soit pas la préoccupation majeure de ces langages. Cette lacune peut alors expliquer
pourquoi le monde de l’industrie du logiciel ne soit pas séduit par ces outils.
Finalement, plusieurs langages sont proches de la réalisation. Ils manquent d’abstraction.
En effet, plusieurs langages sont qualifiés comme étant des langages de configuration. Il
est difficile sur ces langages de proposer des outils de vérification de propriétés.
En conclusion, les ADLs sont des langages de conception qui permettent la définition de
modèles abstraits pour l’assemblage, ceci dès la phase de conception. Ces modèles abstraits
ne sont pas complets et manquent de liens avec les modèles de réalisation. Plusieurs tentatives
ont été faites, mais sans grand succès pour combiner la notation UML, plus connue des
industriels avec les ADLs [18].
6. Bibliographie
[1] N. Medvidovic and R. N. Taylor, A Classification and Comparison Framework for
Software Architecture Description Languages, IEEE Transactions on Software Engineering,
Vol 26, no1, pp70-93, Janvier 2000.
[2] G. Zelesnik, The UniCon Language Reference Manual, School of Computer Science
Carnegie Mellon Universtity, Pittsburgh , Mai 1996.
[3] G. Zelesnik, The UniCon Language User Manual, School of Computer Science Carnegie
Mellon Universtity, Pittsburgh, Juin 1996.
[4] D. Garlan, A introduction to the Aesop System, School of Computer Science, Carnegie
Mellon University, Juillet 1995.
[5] J. Dulay, N. Kramer J. Magee, Structuring Parallel and Distributed Programs, ,IEEE
Software Engineering Journal, vol.8(N.2), pp.73-82, Mars 1993.
[6] Magee J, Dulay N, Kramer J A Constructive Development Environment for Parallel and
Distributed Programs, in Proc. of the IEEE Intn'l Workshop on Configurable Distributed
Systems (IWCCS'94), Pittsburgh PA, USA, Mars 1994.
[7] Magee J, Dulay N., Kramer J, Regis: A Constructive Development Environment for
Distributed Programs, IEEE Distributed Systems Engineering Journal, vol.1(N.5), pp.304312, Dec 1994.
[8] Guide to the Rapide 1.0 Language Reference Manuals, Rapide Design Team Program
Analysis and Verification Group Computer Systems Lab Stanford University, Juillet 1997.
© Projet ACCORD
Page 61 sur 62
[9] R. Allen, A Formal Approach to software Architecture, PhD thesis, School of Computer
Science Carnegie Mellon University,Pittsburgh, Mai 1997.
[10] N. Medvidovic, R. Taylor, E. Whitehead, Formal Modeling of Software Architectures at
Multiple Levels of Abstraction, Department of Information and Computer Science, University
of California, Irvine, Avril 1996.
[11] R. Taylor, N. Medvidovic, K. Anderson, E. Whitehead Jr. Jason, E. Robbins, A
Component- and Message-Based Architectural Style for GUI Software, Department of
Information and Computer Science, University of California, Irvine, Juin 1996.
[12] N. Medvidovic, R. Taylor, Exploiting Architectural Style to Develop a Family of
Applications, IEEE Proceedings Software Engineering, Oct/Dec 1997.
[13] N. Medvidovic, R. Taylor, R. Khare, M. Guntersdorfer, An Architecture-Centered
Approach to Software Environnement Integration, Department of Information and Computer
Science, University of California, Irvine, Mars 2000.
[14] Luc Bellissard, Construction et Configuration d’application réparties, thèse de docteur à
l’institut nationale polytechnique de Grenoble, Décembre 1997.
[15] D. Garlan, R. Monroe, D. Wile, ACME : An Architecture Description Interchange
Language, Computer Science Department, Carnegie Mellon University, Pittsburg et
USC/information science institute, Novembre 1997.
[16] D. Garlan, R. Monroe, D. Wile, ACME : Architectural Description of Component-Based
Systems, Computer Science Department, Carnegie Mellon University, Pittsburg et
USC/information science institute, 1997.
[17] R. Allen, R. Douence, D. Garlan, Specifying Dynamism in Software Architectures,
Proceedings of the First Workshop on the Foundations of Component-Based Systems, Zurich,
Switzerland, September 26 1997
[18] D. Garlan, S.W. Cheng, A. Kompanek, Reconciling the Needs of Architectural
Description with Object-Modeling Notations, Science of Computer Programming Journal,
Special UML Edition, Elsevier Science, 2001.
© Projet ACCORD
Page 62 sur 62

Documents pareils