Un style architectural est une classe générique d - Latece
Transcription
Un style architectural est une classe générique d - Latece
Les langages de description d’architectures Ghizlane El Boussaidi [email protected] Hafedh Mili [email protected] LAboratoire de recherche sur les TEchnologies du Commerce Electronique Université du Québec à Montréal Abstract Architectural description is a central artifact in software design. Indeed, architecture provides a high level description of a system’s structure which reduces its complexity. Hence it is essential to have languages enabling precise specification of architectural descriptions. In this report, we review formal architectural description languages and we also look at the UML2.0 mechanisms that support architectural modeling. Résumé La description architecturale est un artefact central dans la conception logicielle. En effet, l’architecture fournit une description de haut niveau de la structure d’un système ce qui permet de réduire sa complexité. Il est donc essentiel de disposer de langages permettant la spécification précise des descriptions architecturales. Dans ce rapport, nous passons en revue des langages formels de description d’architectures et nous nous penchons aussi sur les mécanismes fournis par UML2.0 pour modéliser les architectures. LATECE Technical Report, October 2006 Page 1 Table des matières 1. Introduction _____________________________________________________ 3 2. Style architectural ________________________________________________ 4 2.1 Définition _____________________________________________________________________________ 4 2.2 Exemple de style architectural : Filtres et Canaux____________________________________________ 4 3. Les langages de description d’architecture (ADLs) ______________________ 5 3.1 Concepts de base _______________________________________________________________________ 6 3.1.1 Les exigences minimales fondamentales__________________________________________________ 6 3.1.2 Les exigences souhaitables : ___________________________________________________________ 7 3.1.3 Les exigences désirables mais non fondamentales : _________________________________________ 7 4. Survol des ADLs _________________________________________________ 8 4.1 Les ADLs se concentrant sur l’aspect structurel _____________________________________________ 8 4.1.1 Wright ____________________________________________________________________________ 8 4.1.2 ACME ___________________________________________________________________________ 13 4.1.3 UniCon __________________________________________________________________________ 17 4.1.4 Aesop____________________________________________________________________________ 22 4.1.5 C2 ______________________________________________________________________________ 24 4.2 Les ADLs se concentrant sur l’aspect dynamique ___________________________________________ 29 4.2.1 Darwin ___________________________________________________________________________ 29 4.2.2 RAPIDE _________________________________________________________________________ 33 5. Synthèse sur les ADLs ____________________________________________ 36 6. La description architecturale dans UML _____________________________ 39 6.1 Présentation sommaire d’UML __________________________________________________________ 39 6.2 Les approches basées sur UML1.x________________________________________________________ 40 6.3 UML2.0______________________________________________________________________________ 43 6.3.1 Le modèle de composant _____________________________________________________________ 43 6.3.2 Le modèle de déploiement____________________________________________________________ 49 6.3.3 Le modèle comportemental ___________________________________________________________ 52 6.4 UML2.0 comme ADL __________________________________________________________________ 54 7. Conclusion _____________________________________________________ 55 8. Références _____________________________________________________ 55 LATECE Technical Report, October 2006 Page 2 1. Introduction Une étape des plus importantes et critiques dans le processus de conception d’un système est la conception architecturale. En effet, l’architecture fournit la description de haut niveau de la structure d’un système ce qui permet de réduire sa complexité. « L’architecture logicielle inclut la description des éléments à partir desquels les systèmes sont construits, les interactions entre ces éléments, les patrons qui guident leur composition et les contraintes sur ses patrons » (Garlan et Shaw, 1994). Ainsi, la conception architecturale se base sur des patrons récurrents d’organisation appelés styles architecturaux. Vu le rôle important que l’architecture joue dans le développement de systèmes complexes, il est devenu indispensable de disposer de langages pour la spécifier de façon précise. Pour cela, plusieurs formalismes de description d’architectures ont été proposés par la communauté de recherche en architecture logicielle, on les appelle les langages de description d’architectures (ADL : Architecture Description Language). « Un ADL se concentre plutôt sur la structure de haut niveau de l’ensemble de l’application, que sur les détails d’implémentation. » (Vestal, 1993). Les plus connus de ces langages sont Wright (Allen, 1997), ACME (Garlan et al., 2000), Rapide (Luckham et al., 1995), UniCon (Shaw et al., 1995), C2 (Taylor et al., 1996), Darwin (Magee et al., 1995) et AESOP (Garlan et al., 1994). Les ADLs proposent des notations formelles pour décrire les concepts de la description architecturale et permettent des analyses rigoureuses des architectures. Cependant, chaque ADL se concentre sur une famille spécifique d’architectures et offre un langage de modélisation et des techniques d’analyse fortement spécialisés. Ce traitement en profondeur et cette rigueur offerts par un ADL peuvent rendre difficile l’intégration des descriptions architecturales avec d’autres artefacts de développement (Medvidovic et al., 2002). D’autres travaux (Medvidovic et al., 2002), (Garlan et al., 2002) (Baresi et al., 2003) (PerezMartinez, 2003) (Zarras et al. 2001) se sont intéressés aux aptitudes du langage UML à modéliser les architectures logicielles et ont proposé quelques alternatives et extensions. Cet intérêt a été motivé par la familiarité des concepteurs et développeurs avec UML et aussi la disponibilité d’outils de modélisation supportant UML. Cependant, UML n’offre pas la rigueur ni les possibilités d’analyses offertes par les ADLs. Dans ce rapport nous nous intéressons au support offert par les ADLs et par UML pour la description architecturale. Le document est organisé de la manière suivante. Nous commençons par définir un style architectural et illustrer cette notion par un exemple. Nous introduisons ensuite à la section 3 les concepts sous-jacents à la description architecturale et qui doivent être modélisés par les ADLs. Nous faisons un survol des ADLs les plus communs dans la section 4 et nous les comparons à la section 5. Dans la section 6, LATECE Technical Report, October 2006 Page 3 nous présentons et discutons des mécanismes offerts par UML pour supporter la description architecturale. Nous concluons à la section 7. 2. Style architectural 2.1 Définition « Les styles architecturaux forment un répertoire de base des architectures » (Garlan et Shaw, 1994). En fait, un style architectural peut être considéré comme une classe générique d’architecture ou un patron d’organisation (exemple : « client-serveur », « filtres et canaux », « architecture par couches », etc.). Il définit les propriétés pour les éléments de conception, les règles et les contraintes sur la façon de les lier (contraintes topologiques) et permet des analyses spécialisées et spécifiques au style. « Un style architectural peut être défini comme un type que l’architecture doit avoir pendant l’exécution » (Le Métayer, 1998). Les éléments du système ne peuvent interagir qu’à travers les liens spécifiés par le style. Un style architectural inclut une spécification statique et une spécification dynamique. La partie statique englobe l’ensemble des éléments (composants et connecteurs) et des contraintes sur ces éléments. La partie dynamique décrit l’évolution possible d’une architecture en réaction à des changements prévus ou imprévus de l’environnement. Selon (Garlan et Shaw, 1994), un style architectural est précisément défini par un ensemble de caractéristiques telles que : le vocabulaire utilisé (les types de composants et de connecteurs), les contraintes de configuration (contraintes topologiques appelées aussi patrons structurels), les invariants du style, les exemples communs d’utilisation, les avantages et inconvénients d’utilisation de ce style et les spécialisations communes du style. Un style architectural spécifie aussi les types d’analyse que l’on peut faire sur ses instances (systèmes construits conformément à ce style). 2.2 Exemple de style architectural : Filtres et Canaux Un des styles architecturaux les plus communs est le style « Filtres et Canaux » (pipes and filters). Dans ce style, un composant reçoit un ensemble de données en entrée et produit un ensemble de données en sortie. Le composant lit continuellement les entrées sur lesquelles il exécute un traitement ou une sorte de « filtrage » pour produire les sorties. Pour cela, les composants sont appelés filtres (Garlan et Shaw, 1994). Les spécifications des filtres peuvent contraindre les entrées et les sorties. Un connecteur, quant à lui, est appelé « Canal » puisqu’il représente une sorte de conduite qui permet de véhiculer les sorties d’un filtre vers les entrées d’un autre. Le style « Filtres et Canaux » exige que les filtres soient des entités indépendantes et qu’ils ne connaissent pas l’identité des autres filtres. De plus, la validité d’un système conforme à ce style ne LATECE Technical Report, October 2006 Page 4 doit pas dépendre de l’ordre dans lequel les filtres exécutent leur traitement. Parmi les exemples les plus connus de systèmes conformes à ce style, on peut citer les programmes écrits en Unix. La Figure 1 représente un exemple simple (séquence linéaire de filtres) du style « Filtre et Canal » où on a deux filtres, le premier reçoit un flux de caractères en entrée et le transmet en sortie au second. Canal 1 Filtre 1 Canal 2 Filtre 2 Canal 3 Figure 1 : Exemple de Filtre et Canal Ce style facilite la compréhension du comportement d’un système vu qu’il le décompose en un ensemble de comportements spécifiés par les filtres. Ainsi, un système conforme à ce style est facile à maintenir (ajouter un nouveau filtre, remplacer un filtre). Ce style favorise aussi la réutilisation puisqu’un même filtre peut interagir avec plusieurs autres filtres via différents canaux lorsque les données échangées sont compatibles. De plus, de par son organisation, ce style supporte l’exécution concurrente (les filtres peuvent correspondre à des tâches séparées s’exécutant en parallèle au besoin) et permet l’analyse des sorties et des analyses d’inter-blocage. Cependant, l’application de ce style peut dégénérer et donner une décomposition purement séquentielle d’un système ce qui n’est pas adapté à certains types d’application (ex : applications interactives). 3. Les langages de description d’architecture (ADLs) Un ADL fournit une syntaxe et une sémantique formelle pour modéliser l’architecture conceptuelle d’un système. Il permet de spécifier abstraitement les éléments d’une architecture sans définir leur implémentation. La majorité des ADLs partagent un ensemble des concepts essentiels à la modélisation architecturale tels que les composants, les connecteurs et les configurations (Medvidovic et Taylor, 2000). Ils visent généralement à spécifier explicitement les composants et la configuration d’un système. Cependant, chaque ADL s’intéresse à une famille d’architecture particulière ou à un domaine donné, et de ce fait il représente une approche particulière de spécification. Un ADL se concentre sur des aspects spécifiques de l’architecture et privilégie des techniques puissantes mais spécifiques d’analyse. Avant de présenter en détail les ADLs les plus communs, nous allons introduire les concepts sous-jacents à la description architecturale et qui doivent être modélisés par un ADL. LATECE Technical Report, October 2006 Page 5 3.1 Concepts de base Les concepts de base qui forment une description architecturale sont le composant, le connecteur et la configuration. Un ADL doit permettre la modélisation de ces concepts en plus de d’autres propriétés. En se basant sur les études faites sur les ADLs (Clements, 1996) (Medvidovic et Taylor, 2000) (Shaw et Garlan, 1994) (Vestal, 1993), nous présentons, brièvement, les propriétés principales qu’un ADL doit avoir. Nous divisons l’ensemble de ces propriétés en trois sous-familles : (1) les exigences minimales fondamentales que tout ADL doit supporter ; (2) les exigences souhaitables dont le support permet des implémentations correctes des architectures ; (3) les exigences désirables mais non fondamentales dont le support aide grandement à la conception architecturale. 3.1.1 Les exigences minimales fondamentales Spécification des composants : «Un composant est une unité de calcul localisée et indépendante.» (Allen, 1997). C’est une unité de calcul ou de données qui peut être atomique ou composite et qui possède une interface décrivant les points d’interaction du composant avec l’environnement. Un ADL doit permettre la spécification d’un type de composant et de son interface. Spécification des connecteurs : Le connecteur modélise les interactions entre les composants et aussi les règles qui régissent ces interactions. Il peut être implanté sous forme d’appel de procédure, de variable partagée, de canal, etc. Un connecteur a les mêmes caractéristiques qu’un composant (Medvidovic et Taylor, 2000). Il a une interface qui regroupe l’ensemble des points d’interaction entre le connecteur et les composants ou connecteurs qu’il relie. Il possède aussi un type qui représente une description abstraite de l’interaction qu’il représente. Il est important qu’un ADL permette de spécifier un connecteur comme une entité de première classe. Cela permet d’associer une interface à un connecteur et aussi de le réutiliser. Spécification des configurations : La configuration architecturale, appelée aussi topologie, décrit la structure complète d’un système. Elle se présente souvent sous forme de graphe connexe regroupant des composants et des connecteurs. Un ADL doit fournir un support adéquat pour modéliser la configuration. Spécification des styles architecturaux : Une architecture est conforme à un style si ses composants et connecteurs sont ceux définis par le style en question et si toutes les configurations qu’elle comporte sont conformes aux contraintes définies par le style. Il est important de pouvoir spécifier explicitement un style architectural pour pouvoir faire un certain nombre d’analyses et de vérifications sur l’architecture d’un système. LATECE Technical Report, October 2006 Page 6 3.1.2 Les exigences souhaitables : Modélisation de la sémantique : La sémantique des composants et des connecteurs est décrite par des modèles de comportement. Le comportement d’un composant inclut l’aspect dynamique du composant alors que celle du connecteur comprend la spécification des protocoles d’interaction qu’il décrit (Medvidovic et Taylor, 2000). Spécification des contraintes : Les contraintes sur un composant ou un connecteur représentent l’ensemble des propriétés qu’il doit avoir et qui ne peuvent être violées. Les contraintes sur une configuration architecturale sont des contraintes globales qui découlent souvent des contraintes sur les composants et les connecteurs participant à la configuration. Composition hiérarchique : Une architecture peut être décrite à différents niveaux d’abstraction. Un composant ou un connecteur peut être lui-même un ensemble de composants et connecteurs. Une architecture entière peut être représentée par un composant. Propriétés non fonctionnelles : Les propriétés non fonctionnelles (ex : sécurité, performance,etc.) représentent des exigences qui ne découlent pas directement de la sémantique des concepts architecturaux (composant, connecteur, configuration). Toutefois, leur description est nécessaire pour une implémentation correcte de ces concepts et aussi pour faire des vérifications, analyses et simulations de comportement en cours d’exécution. 3.1.3 Les exigences désirables mais non fondamentales : Support de la réutilisation : Il est désirable de pouvoir réutiliser des composants et des connecteurs aussi bien que des configurations et des descriptions de styles dans la description de différents systèmes. Aussi la modélisation des composants et des connecteurs par des types paramétrables favorise leur réutilisation (Medvidovic et Taylor, 2000). Évolution : Un composant, un connecteur et même un système sont amenés à évoluer continuellement. Cette évolution se traduit par le changement de leurs propriétés. Ce changement de propriétés est un aspect clé que les ADLs doivent supporter. Support d’outil : La disponibilité d’un outil renforce l’utilité d’un ADL. En effet, le support d’outil peut faciliter la conception architecturale d’un système ainsi que l’évaluation de ses propriétés. L’outil peut même aller jusqu’à la génération d’un système exécutable à partir de la description architecturale. LATECE Technical Report, October 2006 Page 7 4. Survol des ADLs Les ADLs couvrent différents domaines et se concentrent donc sur des concepts et aspects différents de la description architecturale. Darwin se concentre sur la construction de systèmes distribués. Le langage RAPIDE se concentre sur la spécification et l’analyse de l’aspect dynamique dans les architectures. Aesop supporte l’utilisation des styles architecturaux et vise principalement à fournir une plate forme de développement basée sur les styles. ACME, pour sa part, représente plus un langage unificateur pour l’ensemble des ADLs. Il a pour but de permettre l’échange de descriptions architecturales exprimées par différents ADLs. Le langage C2 supporte la description des systèmes distribués dynamiques, en particulier les systèmes d’interface utilisateur. UniCon permet la composition et la vérification des systèmes à partir d’éléments prédéfins. Le langage Wright se concentre plus sur la modélisation de tous les éléments architecturaux (composant, connecteur, configuration et style) et sur les analyses statiques, en particulier, les analyses des inter-blocages dans les systèmes concurrents. En étudiant ces différents langages, nous avons pu identifier deux grandes familles d’ADLs. La première famille d’ADLs se concentre sur la spécification explicite des propriétés architecturales structurelles en particulier ces ADLs spécifient les connecteurs comme des entités de première classe. Cette famille comprend les langages Wright, ACME, Aesop, C2 et UniCon. La seconde famille se concentre plutôt sur la spécification de l’aspect dynamique des architectures et ne spécifie pas de façon explicite les connecteurs. Cette famille inclut les langages Darwin et RAPIDE. Les ADLs que nous avons étudiés peuvent aussi être classés selon leur « généricité ». En effet, contrairement aux autres ADLs, ACME et Aesop visent à fournir un modèle architectural générique. 4.1 Les ADLs se concentrant sur l’aspect structurel 4.1.1 Wright Le langage Wright a été développé à l’université Carnegie Mellon en 1997 (Allen, 1997)(Allen et Garlan, 1997). Il décrit les composants et les connecteurs comme des éléments de première classe d’une architecture. « Il fournit une base formelle pour la description des configurations et des styles architecturaux » (Allen, 1997). En effet, il utilise une notation basée sur CSP (Hoare, 1985) pour décrire le comportement et les interactions, ce qui permet de définir une sémantique formelle et de rendre possible un certain nombre d’analyse et de vérification. LATECE Technical Report, October 2006 Page 8 Wright fournit une spécification explicite pour le composant, le connecteur, la configuration et même le style. Un composant est décrit en deux parties. Une partie qui contient la déclaration d’un ensemble de ports qui représentent son interface et une partie qui représente la description du comportement du composant appelée calcul (computation). Chaque port représente un point d’interaction entre le composant et son environnement. Une spécification formelle exprimée par le langage CSP est associée à chaque port, elle exprime les propriétés et les attentes du composant vu à travers ce port et elle constitue une partie de son comportement. La spécification du calcul (computation) fournit une description complète du comportement et des propriétés du composant en montrant comment les ports sont regroupés et utilisés. Les analyses faites sur le composant se baseront sur cette spécification. Dans une architecture Filtre et Canal (pipe and filter), considérons un exemple où on a deux filtres (Filtre1, Filtre2), le premier reçoit un flux de caractères en entrée et le transmet en sortie au second filtre. Filtre1 Filtre2 Figure 2. exemple de filtre et canal Le filtre correspond à un composant qu’on peut décrire simplement avec le langage Wright comme suit : Component Filtre Port Entrée [Lire les données jusqu’à ce que la fin des données soit atteinte] Port Sortie [sortir les données de manière permanente] Computation [Lire continuellement les données à partir du port Entrée, puis les envoyer sur le port Sortie] Les ports « Entrée » et « Sortie » forment l’interface du composant « Filtre ». Les spécifications des deux ports et de la partie calcul sont normalement exprimées avec le langage CSP. Le langage Wright définit explicitement un type de connecteur. Ce type correspond, en fait, à un patron d’interaction qui peut être utilisé par plusieurs instances de connecteur. Un connecteur permet ainsi de structurer la façon dont un composant interagit avec le reste du système et de fournir des exigences auxquelles un composant doit se conformer. De la même façon qu’un composant est défini, un type de connecteur est décrit en deux parties. Une partie qui définit un ensemble de rôles et une partie qui représente la spécification d’assemblage (glue). Chaque rôle correspond à une partie intervenante dans l’interaction et sa spécification, exprimée en CSP, décrit le comportement attendu de cet intervenant. La spécification d’assemblage, quat à elle, décrit comment les activités des rôles sont coordonnées. En fait, elle spécifie LATECE Technical Report, October 2006 Page 9 comment les calculs (computation) des différents participants (composants) sont combinés pour former un calcul plus large et qui correspond au comportement global et complet du connecteur. Dans l’exemple précédent, le canal a deux rôles (source et récepteur), la partie « Glue » décrit comment les données sont délivrées du rôle Source au rôle Récepteur. La description avec Wright est comme suit : Connector Canal Role Source [produire continuellement les données, signaler la fin par une fermeture] Role Récepteur [Lire continuellement les données, fermer à la fin ou avant la fin des données] Glue [ Récepteur reçoit les données dans le même ordre qu’elles sont produites par Source] Pour chaque rôle déclaré dans la spécification du connecteur ainsi que pour la partie assemblage (Glue), on fournit une description en CSP. L’exemple suivant montre la spécification détaillée d’un connecteur entre les composants Client et Serveur. Le rôle du serveur est décrit par un processus continue qui accepte une invocation et envoie un retour ou qui se termine avec succès (le processus noté § représente un processus qui se termine avec succès). Le rôle du client est décrit de façon similaire par un processus continue qui appelle un service et reçoit le résultat ou se termine avec succès. La différence majeure dans la spécification des deux rôles est le choix de l’opérateur (interne Π ou externe ) qui permet de distinguer formellement entre une situation où le comportement d’un processus est dicté par l’environnement (ici le serveur est obligé de fournir un service lorsqu’il y a une requête), et la situation ou un rôle peut choisir d’utiliser des services mais il n y est pas obligé (c’est le cas du client qui peut émettre une requête ou pas). Le processus d’assemblage « glue » coordonne le comportement des deux rôles en indiquant comment les événements de chaque rôle interagissent ensemble. LATECE Technical Report, October 2006 Page 10 Une configuration représente la description de l’architecture complète d’un système. Elle regroupe des instances de composants reliés via des instances de connecteurs. L’architecture est composée de trois parties. La première partie définit les types de connecteurs et de composants. La deuxième partie spécifie un ensemble d’instances de composants et connecteurs. Plusieurs instances du même type de composant ou connecteur peuvent exister dans la même configuration. Pour cela chaque instance est nommé d’une façon explicite et unique. Dans la troisième partie de la description, les instances de composants et connecteurs sont combinées en précisant quels ports (d’un composant) sont attachés à quels rôles (de connecteur). Cette partie décrit, donc, la topologie de la configuration. La configuration correspondante à notre exemple a cette forme : Configuration Filtre-Canal Component Filtre Connector Canal Instances Filtre1, Filtre2 : Filtre C1 : Canal Attachments Filtre1.Sortie as C1.Source Filtre2.Entrée as C1.Récepteur End Filtre-Canal. Les ports et les rôles associés dans la troisième partie « Attachments » doivent être compatibles. Cela signifie que le port est conforme aux règles imposées par le rôle pour pouvoir participer à l’interaction spécifiée par le connecteur. Les spécifications des ports et des rôles sont nécessaires pour la vérification de la compatibilité. Le langage Wright permet la composition hiérarchique. En fait, la partie calcul (computation) d’un composant peut être représentée par une configuration correspondant au sous-système architectural que le composant représente. De la même façon la partie glue d’un connecteur peut être exprimée sous forme de configuration. WRIGHT permet aussi la spécification d’un vocabulaire par la définition des types de composant et connecteur. Il utilise les types d’interfaces pour spécifier les contraintes sur une partie d’un composant (port) ou un connecteur (rôle). Par exemple le style Filtre-Canal peut définir deux types d’interfaces (EntréeDonnée et SortieDonnée) pouvant être utilisées par un Filtre. En plus, pour pouvoir réutiliser les mêmes descriptions, Wright permet de paramétrer les types. En effet, on peut remplacer par une variable la description d’un port ou d’un rôle, un calcul ou le nom d’une interface. La variable sera substituée par un paramètre au moment où le type concerné est instancié. LATECE Technical Report, October 2006 Page 11 Pour qu’un système soit conforme à un style, il doit en plus de se conformer au vocabulaire du style, contenir des configurations qui obéissent toutes aux contraintes et propriétés intrinsèques au style. Pour ce faire, WRIGHT utilise des prédicats logiques de premier ordre pour exprimer ces contraintes. Par exemple, les connecteurs dans l’architecture Filtre-Canal (pipe-filter) doivent être tous de type Canal. Cela est exprimé en WRIGHT avec le prédicat : ∀ c : Connectors . Type (c) = Canal. La spécification d’une partie du style Filtre-Canal est exprimée avec WRIGHT comme suit : Style Filtre-Canal Component Filtre Connector Canal Interface Type EntréeDonnée = [Lire continuellement les données, fermer le port à la fin ou avant la fin des données] Interface Type SortieDonnée = [produire continuellement les données, fermer le port pour signaler la fin des données] Constraints ∀ c : Connectors . Type (c) = Pipe Λ ∀ c : Component ; p :Port | p∈ Ports(c ) . Type(p)= EntréeDonnée v Type(p) = SortieDonnée [etc..] endStyle Wright permet aussi l’extension des styles en définissant des sous-styles. Un sous-style est soumis à toutes les contraintes de son « super-style » et inclut tout son vocabulaire. Pour conclure, l’une des caractéristiques essentielles de WRIGHT est qu’il modélise d’une façon explicite un connecteur. Cela permet la séparation des deux concepts composant et connecteur et de promouvoir, ainsi, la réutilisation des deux. Aussi, l’utilisation du langage CSP pour exprimer les comportements et les interactions, permet à WRIGHT de spécifier les éléments architecturaux d’une façon précise et abstraite. L’utilisation des prédicats pour spécifier le style architectural, permet aussi un certain nombre de vérifications comme la cohérence de l’interface d’un composant avec le connecteur auquel il est attaché, la cohérence interne d’un connecteur et la complétude d’une configuration. Cependant, l’utilisation d’un langage comme CSP rend l’utilisation et l’assimilation de WRIGHT assez difficile. En plus, WRIGHT ne dispose pas d’un outil pour permettre d’aller de la spécification abstraite jusqu’à l’implémentation et la génération de code. Il s’est plus concentré sur l’analyse statique et plus précisément les analyses des interblocages. Un autre inconvénient de WRIGHT est qu’il ne supporte pas la modélisation des propriétés non fonctionnelles. LATECE Technical Report, October 2006 Page 12 4.1.2 ACME ACME (Garlan et al., 1997) (Garlan et al., 2000), développé à l’université Carnegie Mellon, représente une base commune aux langages de description d’architecture. Il a pour but de permettre l’échange de spécifications architecturales entre différents ADLs. ACME se base sur sept types d’entités pour décrire une architecture : les composants, les connecteurs, les systèmes, les ports, les rôles, les représentations et les rep-maps (representation map). Un composant correspond, comme dans WRIGHT, à une unité de calcul par exemple : un client, un serveur, un filtre, etc. Les ports représentent les points d’interaction du composant avec son environnement. Un connecteur représente des interactions entre composants et a aussi une interface composée de rôles. Chaque rôle correspond à un participant à l’interaction. La fig.3 représente un diagramme correspondant à une architecture client-serveur. Ce système contient deux composants : le client et le serveur. Ces composants sont reliés par le connecteur RPC. figure 3. architecture client-serveur Ce système est décrit avec ACME comme suit : System simple_cs = { 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 } } ACME permet la composition hiérarchique. En effet, un composant ou un connecteur peut avoir plusieurs descriptions de niveau plus bas. Ces descriptions sont appelées représentations. Les « rep-maps », quant à elles, établissent la correspondance entre l’interface externe d’un composant ou connecteur et ses représentations. Dans un cas simple de composant représentant un sous-système, une rep-map fait l’association entre les ports du composant et les ports des composants appartenant à ce sous-système. Pour spécifier des informations additionnelles relatives au domaine ou au comportement, chacune de ces sept entités qu’on vient de définir, peut être annotée avec des listes de propriétés. Une propriété est LATECE Technical Report, October 2006 Page 13 caractérisée par son nom, son type et sa valeur. Le type peut être simple : entier, caractère ou booléen, il peut indiquer un « sous-langage » avec lequel la propriété est spécifiée, comme il peut être « external » pointant sur un lien externe. figure 4. représentations et propriétés d’un composant L’exemple du client-serveur, intégrant des propriétés, est décrit comme suit : System simple_cs = { Component client = { Port send-request; Properties {Aesop-style : style-id = client-server; 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 a aussi introduit la notion de gabarit « template » pour définir des structures syntaxiques paramétrées que l’on peut instancier plusieurs fois. Les gabarits appartenant à la même famille de systèmes, LATECE Technical Report, October 2006 Page 14 sont regroupés pour définir un style architectural. Le style client-serveur, par exemple, inclura des gabarits pour définir le client, le serveur et le connecteur RPC. Il est décrit comme suit : Style client-server = { Component Template client(rpc-call-ports : Ports) = { Ports rpc-call-ports; Properties { Aesop-style : style-id = client-server; Unicon-style : style-id = cs; source-code : external = "CODE-LIB/client.c" }} Component Template server(rpc-receive-ports : Ports) = { Ports rpc-receive-ports; Properties { Aesop-style : style-id = client-server; Unicon-style : style-id = cs; component-class : type = server; source-code : external = "CODE-LIB/server.c" }} Template rpc(caller_port, callee_port : Port) defining (conn : Connector) = { 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; }} } Un exemple d’instance de ce style se présente comme suit : System complex_cs : client-server = { 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); } ACME se concentre plus sur la spécification de la structure d’une architecture que sur l’aspect sémantique. Il se base sur un cadre sémantique ouvert (open semantic framework) de spécification. « Ce cadre fournit la sémantique structurelle de base tout en permettant à des ADLs spécifiques de définir le comportement des architectures en utilisant la construction : propriété ». Il permet la spécification dans une logique formelle des aspects structurels du langage. Cette spécification est appelée prescription. LATECE Technical Report, October 2006 Page 15 Un exemple de prescription concernant l’exemple du client-serveur et exprimant un certain nombre de relations et contraintes, est comme suit : exists client, server, rpc | component(client) ^ component(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) => 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)) Pour illustrer comment ACME peut jouer un rôle d’intégrateur entre différents ADLs, (Garlan et al., 1997) ont effectué une opération de traduction d’une description écrite avec le langage WRIGHT au langage RAPIDE. La traduction se fait en trois étapes comme on peut le voir sur la figure 5. figure 5. Traduction de WRIGHT vers RAPIDE par l’intermédiaire d’ACME La première et la troisième étape sont faciles à réaliser. En effet, la correspondance entre les structures architecturales de WRIGHT et ACME se fait facilement, les spécifications comportementales sont aussi traduites en annotations. De la même façon, les descriptions ACME, annotées avec des spécifications du langage RAPIDE, sont traduites facilement en descriptions RAPIDE. L’étape intermédiaire est la plus difficile, elle consiste à traduire une annotation exprimée en WRIGHT en une annotation exprimée en RAPIDE. Cette difficulté est dû principalement au fait que le connecteur n’est pas une entité de première classe dans le langage RAPIDE. (Garlan et al., 1997) ont choisi de traduire tous les connecteurs non triviaux dans WRIGHT en composants dans RAPIDE et d’utiliser de simples connecteurs sous forme d’événements associés pour lier les composants. LATECE Technical Report, October 2006 Page 16 Pour conclure, ACME est plus un médiateur entre ADLs qu’un ADL. Il permet à n’importe quel outil qui supporte les sept concepts de base d’interagir avec d’autres outils. En fait, ACME fournit des bases simples qui forment un point de départ pour le développement de nouveaux ADLs. De plus, l’utilisation des « Templates » et des styles permet d’encapsuler des patrons réutilisables. Des ADLs peuvent même être construits en choisissant simplement un ensemble de « Templates » ou styles déjà définis. Cependant, ACME ne permet pas la spécification directe de la sémantique ni des propriétés non fonctionnelles, il permet de spécifier des annotations exprimées dans différents ADLs, mais ces annotations sont non interprétables par l’outil accompagnant ACME lui-même. Cet outil ne permet pas non plus le raffinement du modèle architectural et donc on ne peut pas aller jusqu’à la génération de code. La dynamique du système, elle non plus, n’est pas prise en charge par ACME, ce qui limite les analyses possibles à des analyses syntaxiques. Finalement, l’utilisation de ACME comme un langage d’intégration entre différents ADLs, est dépendante de l’existence d’outils « traducteurs » entre lui et ces ADLs. 4.1.3 UniCon UniCon (Language for Universal Connector support) (Shaw et al., 1995) (Zelesnik, 1996) se base sur deux types de constructions : Composant et Connecteur. Ces deux concepts ont les mêmes propriétés à l'exception que les connecteurs ne sont pas composites alors que les composants peuvent l'être. Un composant ou un connecteur a les caractéristiques suivantes : un nom, une spécification (appelée Interface pour un composant et Protocole pour un connecteur), un type, un ensemble de propriétés sous forme de liste de propriétés (attributs et leurs valeurs associées), un ensemble de points d'association (appelés Players pour les composants et Rôles pour les connecteurs), et une implantation. Les attributs dans la liste de propriétés associée à un composant fournissent une spécification plus détaillée du composant et le contraignent. L'implantation d’un composant peut être composite ou non. Son interface doit être compatible avec son implantation. Si l'implantation est composite, l'interface doit être compatible avec les interfaces de ses composants et avec les protocoles de ses connecteurs. L'interface fournit des garanties de comportement et de performances du composant. Elle doit inclure : le type du composant, des déclarations et des contraintes sur le composant et les players définis par le composant. Les players sont les unités sémantiques visibles à travers lesquelles un composant interagit. Chaque player a un nom, un type et des attributs optionnels (signature, spécifications fonctionnelles, contraintes, etc.). De façon analogue aux composants, les spécifications détaillées des players ont la forme de listes de propriétés. Pour illustrer, l’exemple d’un système Pipe-and-Filter (du style Unix) est utilisé. Ce système (Fig.6) implante un indexeur KWIC (Keyword in context). Cet exemple inclut 4 filtres (caps, shifter, merge, sorter), LATECE Technical Report, October 2006 Page 17 un fichier (req-data), 4 canaux et 2 streams qui sont les players du système entier qui est lui même un filtre. 3 des filtres ont une interface simple (stdin, stdout et stderr), le filtre merge a, par contre, deux entrées. Figure 6. Le système indexeur KWIC La figure 7 montre la spécification textuelle de deux composants du système KWIC. Le composant sort est un composant simple alors le composant KWIC représente un composant composite correspondant au système entier. Un système est considéré dans UniCon comme un composant composite. UniCon limite les types des composants à un ensemble prédéfini (énumération). Pour chaque type de composant, il y a aussi des types prédéfins de players qui sont permis. La table suivante montre les types supportés de composants et les types de players associés. Remarque : Le type General permet tout type de player, permettant ainsi la définition de composants arbitraires, mais il ne supporte ni analyses ni vérifications. LATECE Technical Report, October 2006 Page 18 Figure 7. Spécification d’un composant primitif et d’un composant composite avec UniCon Les composants primitifs sont implémentés directement dans du code avec un langage de programmation ou comme données stockées dans des fichiers. UniCon permet plusieurs représentations d’un même composant. L’attribut Variant permet de choisir la représentation désirée lors de l’instanciation d’un LATECE Technical Report, October 2006 Page 19 composant. Pour sa part, l’implantation d’un composant composite doit fournir 3 types d’information : (1) les parties participantes : instanciation de composants et de connecteurs contenus dans le composant ; (2) la configuration : description de la façon dont les instances de connecteurs relient celles des composants (associations entre players et rôles); (3) l’abstraction : spécification de la façon dont les players de l’interface du composant global sont associés avec les players de l’implantation. Les players de cette interface sont appelés ExternalPlayers car ce sont les players que le composant doit fournir. Dans l’implantation, les players sont fournis lorsque les composants sont instanciés, ce sont des InternalPlayers. L’étape d’abstraction définit donc les ExternalPlayers en terme de InternalPlayers. L’implantation du composant KWIC (fig.7) est composite. Elle définit d’abord les parties à utiliser (composants et connecteurs). Ensuite, elle associe l’entrée du premier filtre (caps) à l’entrée de l’interface de KWIC et elle associe la sortie du dernier filtre (sorter) à la sortie de l’interface de KWIC. Ceci est un cas simple où les ExternalPlayers sont associés aux InternalPlayers du même type. Dans certains cas, l’association peut ne pas être directe. Finalement, l’implantation de KWIC définit la configuration du système en indiquant quelles entrées et sorties sont reliées et avec quels canaux. L’exemple de la fig.7 montre deux façons de faire cela : (1) en associant individuellement les players aux rôles des canaux déjà instanciés ; (2) par une seule instruction qui instancie implicitement le canal et fait toutes les connexions en même temps. Un connecteur spécifie un protocole et une implantation. Le protocole décrit une classe d’interactions que le connecteur fournit. Un protocole définit des rôles correspondants aux responsabilités des parties participantes lesquelles définissent des exigences sur les players des composants pouvant participer à l’interaction décrite par le protocole. Le protocole doit inclure : le type du connecteur, les assertions qui contraignent le connecteur entier, et les rôles qui participent au protocole. Les rôles sont les unités sémantiques visibles à travers lesquelles un connecteur réalise l’interaction entre les composants. Un rôle doit spécifier un nom, un type et il peut spécifier optionnellement d’autres attributs. Les spécifications détaillées des rôles ont la forme de listes de propriétés. La fig.8 montre la définition d’un connecteur canal (pipe) du système KWIC. La spécification détaillée de chaque connecteur est réalisée par une liste de propriétés (associations attributs/valeurs). Il est à noter que l’implantation d’un connecteur est définie et générée par UniCon (BUILTIN). LATECE Technical Report, October 2006 Page 20 Figure 8. Un exemple de connecteur Seuls les implantations primitives des connecteurs sont supportées. Les types des connecteurs et les types des rôles font partie d’un ensemble prédéfini de types. Les types sont décrits dans la table suivante : UniCon offre une notation graphique pour construire les spécifications de façon incrémentale. La figure 6, par exemple, a été générée par l’interface graphique mais les annotations ont été ajoutées manuellement. L’éditeur graphique d’UniCon invoque des mécanismes de contrôle pour vérifier autant que possible le diagramme lors de son développement de façon à prévenir les erreurs au lieu de les corriger après développement. Lorsqu’une composition graphique est complétée, l’outil génère une représentation textuelle LATECE Technical Report, October 2006 Page 21 du composant. L’implantation de UniCon offre aussi des facilités pour invoquer un outil d’analyses (RMA : rate monotonic analysis) qui permet des analyses de planification en temps réel. Pour conclure, UniCon spécifie de façon explicite les connecteurs. Il permet de construire de façon incrémentale un système tout en effectuant une validation de la composition réalisée. Enfin, le langage est doté d’un environnement contenant un éditeur graphique, un analyseur syntaxique et un générateur de code en langage C. Cependant, UniCon se concentre sur les aspects structurels d’une architecture, l’aspect dynamique n’est pas pris en compte. De plus, les types des composants et des connecteurs font partie d’un ensemble prédéfini de types. Aussi, un connecteur ne peut pas être composite et en plus il n’est pas possible de lui associer une implantation autre que celle créée par UniCon. UniCon ne fournit pas de construction pour spécifier un style architectural. De plus, Il ne se base sur aucune notation formelle pour spécifier la sémantique des composants et connecteurs mais plutôt sur une liste d’attributs et n’offre pas de support pour la spécification des propriétés fonctionnelles. 4.1.4 Aesop Aesop (Garlan et al., 1994) (Garlan, 1995) a été développé dans le but de générer à un moindre coût des environnements de développement spécifiques à des styles architecturaux et cela en spécialisant un modèle architectural générique. En effet, en termes des propriétés d’un style, le vocabulaire de conception d’Aesop est générique (composant, connecteur, etc.), les configurations ne sont pas contraintes, il n’y a pas d’interprétation sémantique et les analyses sont limités à la vérification de propriétés topologiques. Les outils associés à Aesop incluent un éditeur graphique et un éditeur de texte pour les annotations. La description architecturale dans Aesop est basée sur une ontologie générique de 7 entités (Figure 9) : composants, connecteurs, configurations, ports, rôles, représentations et associations (bindings). Les composants et les connecteurs ont des interfaces. L’interface d’un composant est défini par un ensemble de ports qui déterminent les points d’interaction du composant avec son environnement. L’interface d’un connecteur est définie par un ensemble de rôles qui identifient les participants dans l’interaction. De façon analogue à ACME, Aesop utilise une représentation pour décrire le « contenu » (ex : fichier, code, etc.) ou la configuration interne d’un composant ou d’un connecteur (dans le cas où ils sont composites). Les bindings permettent de faire la correspondance entre les éléments de la configuration interne et l’interface externe d’un composant ou d’un connecteur. Un binding (Figure 9) identifie un port interne (resp. rôle interne) à un port externe (resp. rôle externe). LATECE Technical Report, October 2006 Page 22 Figure 9. Éléments génériques d’une description architecturale Dans Aesop, chacun de ces 7 concepts est représenté par une classe C++. Les opérations supportées par ces classes incluent l’ajout et la suppression de ports à des composants, la connexion d’un rôle à un port, l’établissement d’une correspondance (binding) entre deux ports ou deux rôles, l’ajout d’une nouvelle représentation à un port ou un connecteur, etc. Souvent, la représentation d’un composant ou d’un connecteur n’est pas architecturale (ex : code source). Cette représentation est mieux manipulée par des outils externes non architecturaux (ex : compilateur). Pour traiter ces données externes, Aesop fournit un sous-type de la représentation appelée External_Rep (Fig.10). Figure 10. Définition des styles par sous-typage Les interfaces définies par Aesop sont intentionnellement minimales. Le but est de fournir un cadre minimal pour la description architecturale permettant de spécifier des informations additionnelles comme des élaborations stylistiques. Pour définir un style Aesop utilise le sous-typage : un vocabulaire spécifique à un style est spécifié par des sous-types des classes architecturales de base ou de leurs sous-types. Les contraintes du style sont alors supportées par les méthodes de ces types. De plus, un style peut identifier des outils externes (ex : outil d’analyses, outil de développement). Cependant, les sous-classes du style doivent respecter la comportement sémantique de leurs super-classes : une sous-classe doit fournir un comportement LATECE Technical Report, October 2006 Page 23 strict de sous-typage pour les opérations mais elles peuvent introduire des sources additionnelles d’échec (ex : l’opération d’ajout d’un port à un composant doit être supportée par le style pipe-filter, mais dans le cas du filtre on ne permet l’ajout d’un port que s’il est une instance d’un type de ports défini par le style : port d’entrée ou port de sortie). La figure 10 montre la hiérarchie des types utilisée pour définir les style pipefilter et pipeline (pipeline est défini comme un sous-type de pipe-filter). Aesop fournit une interface par défaut sous la forme d’un éditeur graphique. Pour générer un environnement spécifique à un style, cet éditeur doit aussi être spécialisé. Pour ce faire, chaque classe architecturale est associée à une ou plusieurs classes de visualisation. Les nouvelles classes introduites par un style héritent des visualisations de leurs super-classes mais peuvent définir leurs propres classes de visualisation. L’avantage de Aesop est qu’il permet de définir plusieurs styles architecturaux. Son modèle architectural générique définit explicitement tous les concepts de base (composant, connecteur et configuration). Aussi, il permet d’intégrer d’autres environnements de développement et des outils externes. Cependant, les contraintes et invariants d’un style ne sont pas spécifiés de façon explicite et claire. Ils sont encodés de façon impérative dans les méthodes des types associés au style. De plus, l’aspect dynamique et les propriétés fonctionnelles des architectures ne sont pas supportés. 4.1.5 C2 C2 (Taylor et al., 1996) a été conçu pour supporter les besoins particuliers des applications possédant des interfaces graphiques. Selon ces concepteurs C2 peut aussi supporter d’autres types d’applications. En fait, C2 a été introduit comme un style architectural représenté par un réseau de composants reliés ensemble par des dispositifs de transmission de messages. Les éléments clés du style C2 sont les composants et les connecteurs. Une architecture est une configuration d’un ensemble de composants et de connecteurs. C2 spécifie aussi un ensemble de règles pour relier les composants et les connecteurs. Les composants communiquent uniquement par passage de message et jamais à travers une mémoire partagée. Composants et connecteurs possèdent deux interfaces («top» et «bottom»). Une interface «top» (resp. «bottom») d’un composant peut être attachée au plus à une interface «bottom» (resp. «top») d’un connecteur. Par contre, un connecteur peut être attaché à n’importe quel nombre de composants et de connecteurs. La responsabilité d’un connecteur est le passage et la diffusion de messages. Il peut aussi appliquer des règles de filtrage et de diffusion de messages (no filtering, notification filtering, prioritized et message sink). LATECE Technical Report, October 2006 Page 24 Un composant peut avoir un état et ses propres tâches de contrôle. Son interface «top» définit l’ensemble des notifications auxquelles le composant répond et l’ensemble des requêtes que le composant émet vers le haut de l’architecture. En fait, les requêtes peuvent être envoyées seulement vers le haut de l’architecture «upward» et les notifications vers le bas «downward». L’interface «bottom» d’un composant définit l’ensemble des notifications qu’il émet vers le bas de l’architecture et l’ensemble des requêtes auxquelles il répond. Un composant C2 (Figure 11) contient : (1) Un objet (internal object) avec une interface définie, cet objet peut être complexe ; (2) Un encapsulateur de l’objet qui à chaque invocation à une routine de l’interface de l’objet, transforme cette invocation et toutes les valeurs retournées en une notification de l’interface «bottom» du composant et envoie cette notification au connecteur sous le composant. Ainsi, les types de notifications émises par un composant sont déterminées par l’interface de son objet interne. (3) Un gestionnaire de dialogues et contraintes qui est le seul à pouvoir invoquer les routines d’accès d’un objet. La partie dialogue peut avoir sa propre tâche de contrôle et peut agir sur un objet en réaction à une notification qu’elle a reçu d’un connecteur au dessus du composant ou pour exécuter une requête reçue du connecteur au dessous du composant ou pour maintenir certaines contraintes définies dans le dialogue. (4) Un traducteur de domaine qui aide à faire la correspondance entre le domaine de la sémantique interne du composant et celui du connecteur au dessus du composant. En pratique, une notification annonce des changements d’état de l’objet interne d’un composant alors qu’une requête est une directive générée par la partie dialogue d’un composant demandant qu’une action soit réalisée par certains composants qui sont au dessus du composant concerné. Figure 11. L’architecture interne d’un composant C2 La syntaxe (en BNF) d’un composant en C2 se présente comme suit : LATECE Technical Report, October 2006 Page 25 Un extrait de la syntaxe de l’interface montrant les deux types «top» et «bottom» se présente ainsi : Pour illustrer, nous utilisons un exemple extrait de (Medvidovic et al., 2002). C’est une version simplifiée d’un système d’ordonnancement de réunions. Dans ce système, un initiateur de réunion demande à tous les participants l’ensemble des dates auxquelles ils ne peuvent être présents à la réunion (exclusion set) et l’ensemble des dates auxquelles ils préfèrent que la réunion se tienne (preference set). Ces ensembles de dates sont contenues dans un intervalle de temps imposé par l’initiateur (date range). La figure 12 montre une vue graphique du style architectural C2 pour ce système qui contient des composants supportant les fonctionnalités d’un initiateur (Meeting Initiator) et des participants (Attendees et ImportantAttendees). Trois connecteurs sont utilisés pour l’échange de messages entre composants. Certains messages de l’initiateur sont envoyés à tous les participants alors que d’autres sont destinés seulement aux participants importants. C’est le connecteur «MainConn» qui s’assure que les connecteurs «AttConn» et «ImportantAttConn» reçoivent seulement les messages destinés aux composants qui leur sont respectivement attachés. LATECE Technical Report, October 2006 Page 26 Figure 12. Architecture du système d’ordonnancement de réunions L’initiateur envoie des requêtes aux participants qui répondent par notification. Il essaye alors d’organiser une réunion et la confirme aux participants (si elle peut être organisée). Sinon, il envoie d’autres requêtes aux participants pour étendre l’intervalle de temps établi, ou ajouter des dates préférées ou supprimer un ensemble de dates exclues ou se retirer de la réunion. L’initiateur communique avec les participants à travers son interface « top ». Sa spécification en C2 se présente comme suit : La partie startup incluse dans la partie behavior de l’initiateur spécifie les requêtes qu’il envoie pour initier le processus. Les participants, quant à eux, communiquent avec les autres parties à travers leurs interfaces «bottom». LATECE Technical Report, October 2006 Page 27 Un participant important est une spécialisation d’un participant. Il a les mêmes fonctionnalités d’un participant mais il ajoute une fonctionnalité qui est la spécification des préférences de lieu de réunion : L’architecture entière du système est décrite comme suit : LATECE Technical Report, October 2006 Page 28 Un système ayant 3 simples participants et 2 participants importants est instancié comme suit : Finalement, C2 est doté d’un environnement (ARGO et DRADEL) permettant l’édition graphique des modèles architecturaux, l’analyse de la syntaxe et la sémantique des modèles et la génération d’une partie de l’implantation d’un système. Parmi les avantages de C2 est qu’il assure une certaine indépendance du composant vis à vis de la partie du système qui est en dessous de lui. L’association de tâches de contrôles (threads) aux composants facilite la modélisation des systèmes concurrents ou distribués. C2 permet aussi la construction des configurations à partir de composants hétérogènes. Cependant, il ne définit pas la sémantique des connecteurs même s’il les spécifie de façon explicite. De plus, C2 ne permet pas de spécifier explicitement un style architectural et ne supporte pas la spécification des propriétés fonctionnelles. 4.2 Les ADLs se concentrant sur l’aspect dynamique 4.2.1 Darwin Darwin (Magee et al., 1995) a été conçu dans l’objectif de faciliter la conception de systèmes distribués. C’est une notation pour spécifier la structure des systèmes composés à partir de différents LATECE Technical Report, October 2006 Page 29 composants utilisant différents mécanismes d’interaction. Darwin offre aussi bien une représentation textuelle que graphique des concepts architecturaux qu’il permet de spécifier. Les concepts utilisés dans Darwin sont les composants et les services. Les services représentent les mécanismes par lesquels les composants interagissent. Un composant est spécifié en Darwin par les services qu’il fournit pour permettre à d’autres composants d’interagir avec lui et les services qu’il requiert pour interagir avec d’autres composants. La figure 13 montre un exemple de composant qui est un filtre qui fournit (provides) un service (output) et requiert (requires) un service (input). Le type de service est spécifié entre <>. Dans cet exemple, le mécanisme de communication est un stream et le type de données communiquées est char. Un composant peut fournir plusieurs services et en requérir plusieurs. Les noms des services sont locaux. En fait, un composant n’a pas à connaître les noms globaux des services externes ni leur localisation dans le système distribué. Cela permet d’implanter et tester un composant indépendamment du reste du système et aussi de le réutiliser et le remplacer facilement. Figure 13. Exemple d’un composant Un composant composite est défini en déclarant les instances des composants (potentiellement concurrents et distribués) qu’il contient et les liaisons (bindings) entre ces composants. Les bindings associent les services requis par un composant aux services fournis par d’autres. La figure 14 montre un composant pipeline composé d’une succession linéaire d’instances de filtres. Chaque entrée d’une instance d’un filtre est liée à la sortie de l’instance qui la précède. Les liaisons sont déclarées par le mot clé bind. Les services requis qui ne peuvent être satisfaits à l’intérieur du composant sont rendus visibles à un plus haut niveau en les liant à un service requis de l’interface du composant composite, c’est le cas dans l’exemple du service requis (input) du filtre F[0]. De la même façon, les services fournis qui sont requis en dehors du composant composite sont liés à un service fournis par l’interface du composant composite, par exemple le service fourni (output) par F[n-1]. Les outils accompagnant Darwin vérifient que les liaisons sont faites entre services requis et services fournis ayant des types compatibles. Plusieurs services requis peuvent être reliés à un seul service fourni. Aussi, un service peut transmettre ou recevoir l’information ou faire les deux. LATECE Technical Report, October 2006 Page 30 Figure 14. Exemple d’un composant composite Dans l’exemple de la figure 14, chaque instance de filtre F[k] est localisée dans une machine différente moyennant l’annotation @k+1. Les entiers identifiant les machines sont associés aux adresses réelles des machines par le système runtime de Darwin. Ce niveau d’indirection dans l’association permet des spécifications portables. Pour pouvoir spécifier la sémantique précise des composants, Darwin utilise le π-calculus (réf) qui est un langage formel de processus visant à décrire et analyser les propriétés des processus concurrents et mobiles. La déclaration d’un service fourni (provide p) est modélisé avec le π-calculus (Figure 15) par un processus appelé agent Prov(p,s) qui est accédé par le nom p et qui gère le service s. Le service s est simplement le nom ou la référence à un service implanté par un composant. Darwin ne se préoccupe pas de la manière dont le service est implanté, il s’occupe de placer le service s là où il est requis. L’agent Prov reçoit la localisation x où s est requis et envoie s à cette localisation. Comme le service peut être requis par plusieurs composants, l’agent Prov est défini comme étant un processus répétitif (noté : !). La déclaration d’un service requis (require r) est faite de façon similaire par un agent Req(r,l) (Figure 16). Req(r,l) reçoit le nom d’accès (y) d’un agent Prov et lui envoie la localisation l où le service est requis. Finalement, le binding est modélisé par un agent Bind(r,p) (Figure 17) qui envoie simplement le nom d’accès de l’agent Prov à LATECE Technical Report, October 2006 Page 31 l’agent Req. La composition des agents Req, Bind et Prov (notée Req(r,l) | Bind(r,p) | Prov(p,s) ) résulte en un binding ( ) où le nom du service s est envoyé à la place l où il est requis. Figure 15. Déclaration d’un service fourni en π-calculus Figure 16. Déclaration d’un service requis en π-calculus Figure 17. Déclaration d’un binding en π-calculus Dans Darwin, chaque composant primitif est représenté par un agent qui est une composition des agents Prov et Req qui gèrent ces services et des agents qui définissent son comportement. Une configuration architecturale est représentée par une composition des agents représentants les instances de ses composants et des agents représentant les bindings (simples ou hiérarchiques pour les cas des composants composites). Les instanciations et les bindings se font de façon concurrente. De plus, pour supporter la reconfiguration dynamique des architectures, Darwin offre deux types d’instanciations : l’instanciation retardée (lazy) et l’instanciation dynamique. L’instanciation retardée consiste à instancier un composant seulement lorsque ses services sont requis par d’autres composants. L’instanciation dynamique, quant à elle, est supportée par des constructions qui permettent d’inctancier les composants pendant l’exécution. LATECE Technical Report, October 2006 Page 32 Darwin est supporté par un environnement appelé Regis (réf) où les composants primitifs sont implantés en C++. Regis offre un éditeur graphique permettant différentes vues sur le système en cours de développement. Il permet aussi certains types d’analyses. Finalement, malgré son utilisation du langage π-calculus, Darwin ne décrit pas les propriétés des composants et des services d’une configuration. Aussi le support des styles architecturaux est limité à des configurations paramétrées (Allen, 1997). De plus, les interactions ne sont pas explicitement spécifiées par des connecteurs ce qui ne favorise pas leur réutilisation. 4.2.2 RAPIDE Dans RAPIDE, développé par (Luckham et al., 1995) à l’Université de Stanford, une architecture est composée d’un ensemble de spécifications de modules (interfaces), un ensemble de règles de communication et d’interaction entre ces interfaces et un ensemble de contraintes formelles définissant des patrons de communication. Ces constructions architecturales ont un modèle d’exécution basé événement. En fait, RAPIDE permet la spécification des systèmes comme des ensembles d’événements partiellement ordonnés (poset : Partially Ordered event Set). Un composant peut être formé de plusieurs processus. Ces processus observent et réagissent au poset généré par l’exécution d’une architecture. RAPIDE comprend cinq parties ou langages : le langage des types pour décrire les interfaces des composants, le langage d’architecture pour décrire le flux des événements entre composants, le langage de spécification pour écrire des contraintes sur le comportement des composants, le langage exécutable pour écrire des modules exécutables et le langage de patron pour décrire des patrons d’événements. Un composant comprend deux parties : une interface et un module. Une interface définit l’ensemble des services fournis ou requis par le module, autrement dit, elle définit un type d’interaction. Le module encapsule un prototype exécutable du composant ou il le définit hiérarchiquement comme une architecture de d’autres composants. Les éléments déclarés dans une interface sont : le type, les fonctions (communication synchrone), les actions (communication asynchrone), les contraintes et le comportement. Les fonctions et les actions peuvent avoir une visibilité de type public, private ou extern. Le type public fait référence à des services requis par d’autres modules, le type extern à ceux fournis par le module et le type private à ceux fournis par le module et qui sont visibles uniquement aux autres modules de même type. LATECE Technical Report, October 2006 Page 33 Les contraintes, quant à elles, sont écrites avec le langage de spécification. Ce sont des patrons d’événement qui contraignent le comportement visible d’un module. Les contraintes permettent de détecter les violations de conformité à l’interface par les modules pendant l’exécution. Dans RAPIDE, une interface peut hériter d’une autre en utilisant une déclaration de dérivation. RAPIDE sépare l’héritage d’interface de l’héritage d’implémentation. Une interface peut contenir la description du comportement du module (clause behavior). Cette description est écrite dans le langage d’architecture. Elle est spécifiée sous forme de règles de transition d’état où le composant observe un patron d’événements (trigger) puis génère un patron associé d’événements (body) en réponse. RAPIDE définit plusieurs opérateurs exprimant la dépendance entre événements (→ : dépendance causale, || : indépendance, and : simultanéité,…). Un patron d’événement est construit grâce à ces opérateurs. Le comportement est utilisé comme une contrainte contre laquelle l’exécution du module est vérifiée. Une version simplifiée du standard X/Open DTP (distributed transaction processing) est utilisée comme exemple (Fig.18). Elle comprend une application (AP), un gestionnaire de transaction (TM) et un ou plusieurs gestionnaires de ressources (RMs). Application Program (AP) Transaction Manager (TM) Resource Managers (RMs) Figure 18. Architecture X/Open DTP Les modules Application et Resource peuvent être décrits avec RAPIDE comme suit : type Application is interface extern action Request(p : params); public action Results(p : params); behavior (?M in String) Receive(?M) => Results(?M); LATECE Technical Report, October 2006 Page 34 end Application; type Ressource is interface extern action Results(Msg :string) ; public action Receive(Msg :string) ; end Ressource; La première interface indique qu’un module Application peut appeler l’action Request et qu’il fournit l’action Results. La partie behavior stipule que lorsqu’un événement Receive est reçu, un événement Results est généré avec le même paramètre M. Une architecture, dans RAPIDE, est un module avec un type d’interface. Elle comprend un ensemble de composants et connexions. Elle définit le flux de données et la synchronisation entre modules en utilisant leurs interfaces. La connexion définit un flux causal d’événements ou un appel de fonction entre composants. Elle peut aussi relier les événements de l’interface de l’architecture et ceux des interfaces de ses composants. L’interface Application peut être connectée d’une façon simple à l’interface Resource comme suit : architecture AP_RM_Seulement return X/Open is P :Application; Q :Ressource; … connect (?M in string) P.Request(?M) to Q.Receive(?M); … end AP_RM_Seulement; Cette architecture spécifie que chaque fois que l’application P génère un événement Request, un événement Receive est généré dans la ressource R avec la même donnée. La connexion « to » relie deux événements simples, elle est dite basique. Il existe d’autres types d’opérateurs permettant des connexions plus complexes, comme l’opérateur de diffusion « ||> » et l’opérateur pipe-line « => ». Pour finir, en utilisant un modèle d’événement, RAPIDE permet la spécification de la dynamique d’un système. En plus, il est doté d’un environnement textuel et graphique pour décrire une architecture. Cet environnement inclut un analyseur syntaxique, un compilateur et un outil permettant l’analyse d’une architecture par simulation. L’inconvénient majeur de RAPIDE est qu’il ne permet pas de spécifier les LATECE Technical Report, October 2006 Page 35 connecteurs d’une façon explicite. Ce qui ne permet pas leur manipulation durant la conception ni leur réutilisation. Pour ce qui est des propriétés non fonctionnelles, RAPIDE comme la plupart des ADLs, ne supporte pas leur modélisation. 5. Synthèse sur les ADLs Comme le montre la table 1, même s’ils emploient parfois des terminologies différentes, tous les ADLs considérés permettent de spécifier un composant, son interface et son type. Par contre, ils ne spécifient pas tous de façon explicite un connecteur (ex : Darwin et Rapide). Les ADLs qui ne permettent pas de définir un connecteur de façon explicite ne permettent pas non plus de spécifier son interface et ne favorisent pas sa réutilisation. Ils ne différencient pas entre type et instance d’un connecteur et n’offrent pas de support à son évolution (Medvidovic et al., 2002). La majorité des ADLs ne supportent pas non plus l’évolution d’un composant ou d’une architecture mais les décrivent de façon statique (Table 3). Certains ADLs (ex : Rapide, UniCon, Wright) permettent de spécifier la sémantique des composants et des connecteurs lorsqu’ils les spécifient explicitement. La sémantique est exprimée de façon très variée (Table 2). Dans UniCon, elle se limite à une liste de propriétés alors que dans Wright elle est exprimée formellement avec le langage CSP. De façon générale, les langages « génériques » (Aesop, ACME) se concentrent sur l’aspect structurel et négligent l’aspect sémantique. Par contre, les langages qui se concentrent sur l’aspect dynamique des architectures (Darwin, Rapide), ne modélisent pas explicitement tous les concepts architecturaux, en particulier les connecteurs (Table 1). À l’exception de UniCon, aucun ADL ne supporte vraiment la spécification des propriétés non fonctionnelles des composants et des connecteurs (Table 2). LATECE Technical Report, October 2006 Page 36 ACME Aesop C2 Darwin Rapide UniCon Wright Composant Composant Composant générique à spécialiser Composant Interface et module Connecteur explicite Connecteur explicite Connecteur générique à explicite spécialiser Composant (ensemble prédéfini de types) Connecteur explicite (ensemble prédéfini de types) Composant Connecteur Composant (interface sous forme de services) connecteur non explicite, Bindings des services. Composant composite «Attachments» spécifie explicitement une configuration comme un assemblage d’instances de composants et de connecteurs. Non Spécifie explicitement un style en utilisant des types de composants, de connecteurs, d’interfaces et des prédicats. Configuration «Attachments» spécifie explicitement une configuration comme un assemblage d’instances de composants et de connecteurs. Topologie explicite de l’architecture Composant composite Style Non Configuration paramétrée Configuration générique à spécialiser. Des bindings permettent de faire la liaison entre la configuration interne et l’interface externe d’un composant ou d’un connecteur. Des «templates» Style générique à sont regroupés pour spécialiser. définir un style architectural. connecteur non explicite, connexion par flux causal d’événements ou par appel de fonction «connect» : flux causal d’événements ou appel de fonctions entre composants. Non Connecteur explicite Table 1. Support par les ADLs des exigences minimales et fondamentales LATECE Technical Report, October 2006 Page 37 ACME Aesop C2 Darwin Rapide UniCon Wright Non. Il peut se baser sur la sémantique de d’autres langages grâce à son système d’annotations avec des listes de propriétés. Ces annotations ne sont pas interprétables. À travers les interfaces uniquement. Spécifiée au besoin par des langages spécifiques aux styles. «behavior» décrit le comportement d’un composant. Pré et postconditions des méthodes. Modèle d’interaction et de composition en π-claculus Comportemen t dynamique décrit par des poset (ensembles d’événements partiellement ordonnés) Liste de propriétés associée à un composant ou connecteur. Comportements dynamique des composants et des connecteurs décrits en CSP. Les contraintes supportées par les méthodes des types. Contraintes de Non style et à travers les interfaces. Spécifiées par le langage de spécification. Liste de propriétés associée à un composant ou connecteur. Composition hiérarchique un composant ou un connecteur peut avoir plusieurs représentations de niveau plus bas. Composants et Connecteurs peuvent avoir plusieurs représentations de niveau plus bas. Composant spécifié sous forme d’architecture. Composant composite dont les services sont liés aux services des composants qu’il contient. Les composants peuvent être composites. Propriétés non fonctionnelle s Non. il permet de spécifier des annotations exprimées dans différents ADLs mais elles ne sont pas interprétables Non. Permet d’exprimer des propriétés de façon textuelle et non interprétable. Non Non Correspondan ce entre événements de l’interface d’une architecture et ceux de l’interface d’un composant. Non Spécifiées par des types d’interfaces dans le cas des composants et connecteurs. Utilise des prédicats pour exprimer les contraintes dans la spécification d’un style. Composants et Connecteurs peuvent être composites. Sémantique Contraintes Certaines propriétés comme la planification (schedulability) Non Table 2. Support par les ADLs des exigences souhaitables LATECE Technical Report, October 2006 Page 38 ACME Aesop C2 Darwin Rapide UniCon Wright Réutilisation Utilise un «template» pour définir une structure syntaxique paramétrée que l’on peut instancier plusieurs fois. Les composants, les connecteurs et les styles peuvent être étendus. Les composants et les connecteurs peuvent être étendus. Les types peuvent être paramétrés. Héritage d’interface et héritage de modules. Les types peuvent être paramétrés. Les types des composants et des connecteurs peuvent être réutilisés. Évolution Non. Évolution des composants et des connecteurs via le sous-typage Non. Évolution par sous-typage. Non. Évolution des composants et connecteurs via le soustypage. Instanciation dynamique des composants. Non Support d’outil Outil de visualisation. Éditeur graphique et générateur de code pour le style pipefilter. Permet d’intégrer des outils externes. Éditeur textuel et graphique, analyseur de la syntaxe et la sémantique et générateur de code. Éditeur textuel et graphique, analyseur syntaxique et générateur de code C++. Évolution des composants via le soustypage. Évolution de la configuration Outils de simulation et d’analyse. Les types des composants et des connecteurs peuvent être réutilisés. Les types peuvent être paramétrés. Les styles peuvent être étendus. Non. Évolution par le paramétrage des types. Outils : modélisation, analyse syntaxique et génération de code en C. Édition textuelle, analyseur de syntaxe et type, analyseur pour détection des inter-blocages. Table 3. Support par les ADLs des exigences désirables mais non fondamentales 6. La description architecturale dans UML Une description architecturale doit être comprise et manipulée par plusieurs intervenants qui ont peu de connaissance dans le domaine des spécifications formelles. C’est l’une des raisons pour lesquelles plusieurs tentatives ont été faites pour utiliser ou étudier la possibilité d’utilisation d’UML (Unified Modeling Language) (UML2.0, 2005) (UML2.0, 2006) comme un langage de description des architectures. L’autre raison est que UML est un standard incontournable qui est accompagné par plusieurs outils de support. En effet, utiliser UML pour décrire les architectures, permettra à ses utilisateurs de bénéficier des analyses puissantes offertes par les ADLs et aux utilisateurs des ADLs d’utiliser les outils UML. 6.1 Présentation sommaire d’UML UML est un langage de modélisation résultant de l’unification d’un certain nombre de méthodes (OMT, OOSE, OOAD, etc.). Il décrit un système en utilisant une notation graphique orientée objet. Il a une syntaxe semi-formelle et une sémantique. Pour modéliser un système, UML fournit plusieurs modèles chacun décrivant un aspect. Ces modèles sont exprimés sous forme de diagrammes (de classes, d’états, de packages, de cas d’utilisation, de déploiement). LATECE Technical Report, October 2006 Page 39 La sémantique d'UML manque de précision, ce qui limite l'utilisation des modèles UML à un moyen de compréhension et de communication ou au plus à la génération de la structure d'un système. Cependant, UML offre des moyens qui permettent d'étendre et de préciser la sémantique des éléments de ses modèles. Les mécanismes d'extension sont les valeurs marquées (tag) (attributs associés à des éléments du modèle), les contraintes (restrictions sémantiques sur les éléments du modèle), les stéréotypes (regroupent des contraintes et des valeurs marquées sous un nom pour pouvoir les appliquer à des éléments du modèle) et les profils (regroupent des stéréotypes, des valeurs marquées et des contraintes spécifiques à la modélisation dans un domaine particulier). Les contraintes sont exprimées d’une façon non ambiguë avec le langage formel OCL (Object Constraint Language) (OCL2.0, 2005). Ce dernier permet l’application de ces contraintes sur un élément ou une collection d’éléments. UML est défini selon l’architecture à 4 couches de méta-modélisation de l’OMG (OMG, 2003) (méta-méta-modèle, méta-modèle, modèle, les objets de l’utilisateur). Chaque couche de cette architecture définit des modèles pour spécifier les modèles de la couche inférieure. Ainsi, le méta-modèle est lui même un modèle UML qui spécifie la syntaxe abstraite des modèles UML. Ces derniers décrivent l’information particulière à un domaine, et sont instanciés par les objets de l’utilisateur. 6.2 Les approches basées sur UML1.x Plusieurs chercheurs (Garlan et al., 2002) (Medvidovic et al., 2002) (Baresi et al., 2003) (Zarras et al., 2001) (Perez-Martinez, 2003) se sont intéressés à la possibilité de modéliser une architecture en utilisant UML. Plusieurs stratégies ont été adoptées. Medvidovic et al. (Medvidovic et al., 2002) ont étudié deux stratégies conformes au standard UML. La première stratégie suggère d’utiliser UML tel qu’il est, pour représenter les concepts architecturaux. La seconde stratégie consiste à contraindre UML en utilisant ses extensions. Dans la première stratégie, en utilisant UML pour modéliser des applications de la même façon qu’un ADL, Medvidovic et al. ont représenté certaines entités architecturales ayant différentes responsabilités (composant et connecteur) avec le même concept (Classe). Les règles d’un style architectural sont représentées par des contraintes structurelles, mais elles ne sont pas directement reflétées dans le modèle UML comme cela est possible avec un ADL. En plus, le modèle UML doit être documenté pour empêcher des modifications futures non conformes aux règles du style. En ce qui concerne l’aspect dynamique de l’architecture, il peut être modélisé avec les diagrammes d’UML comme les diagrammes de séquence, de collaboration et d’état. Toutefois, il n’est pas garanti que les comportements et interactions prévus sont correctement et fidèlement modélisés. LATECE Technical Report, October 2006 Page 40 La seconde stratégie utilise le langage OCL pour ajouter des contraintes au niveau du méta-modèle d’UML. Elle consiste à définir des stéréotypes et les appliquer aux instances d’une ou plusieurs méta-classes d’UML pour contraindre leurs sémantiques à celle de l’ADL associé. Medvidovic et al. ont illustré l’approche par des extensions correspondant à 3 ADLs : C2, WRIGHT et RAPIDE. La prise en charge des règles du style C2 a été relativement simple dans la mesure où le style a été entièrement exprimé par des classes stéréotypées et leurs associations. Dans le cas du langage WRIGHT, il fallait modéliser la sémantique des entités architecturales : des machines à état UML ont été utilisées pour modéliser le comportement et les interactions d’un composant ou connecteur. De même, les comportements des composants dans RAPIDE ont été modélisés avec des machines à état UML. Une correspondance a été établie entre les événements dans RAPIDE et les signaux dans les diagrammes d’état d’UML. Toutefois, le modèle devient très compliqué vu qu’il faut maintenir l’information à propos de l’ordre causal des événements dans RAPIDE. Cette deuxième stratégie souligne les limitations sémantiques d’UML quant à la modélisation de certaines préoccupations architecturales. En plus, elle utilise OCL qui peut ne pas être supporté par les outils UML vu qu’il est considéré comme une partie non interprétée d’UML. Une autre limite de la stratégie est qu’elle n’offre aucune garantie que les règles d’un style architectural donné seront toujours respectées. Et finalement, les deux stratégies nécessitent des mises en correspondances pour chaque ADL. Garlan et al. (Garlan et al., 2002) considèrent quatre stratégies pour la représentation en UML des architectures. Les stratégies diffèrent par le choix des constructions UML utilisées pour spécifier le type d’un composant et ses instances. La 1ère stratégie représente le type d’un composant par une classe et les instances du composant par des objets. La 2ième stratégie propose de représenter aussi bien les composants que leurs instances par des classes. La 3ième stratégie consiste à représenter un composant architectural par un composant d’UML. Un composant dans UML1.x décrit un artefact d’implantation et non un composant au sens des ADLs. La 4ième stratégie modélise un composant comme un sous-système UML. Le choix des constructions représentant les ports, les connecteurs, les configurations (systèmes) et les représentations (sous-systèmes) dépend des constructions utilisées pour modéliser un composant et ses instances. Un connecteur, par exemple, peut être modélisé par une association, une classe d’association, une classe, une dépendance entre composants, un composant ou un sous-système. Les quatre stratégies ont été examinées en fonction de la complétude, la lisibilité et la conformité sémantique de la description architecturale qu’elles permettent. La conformité sémantique signifie ici que le modèle décrivant une architecture est un modèle UML légal et que son interprétation est identique à celle de la description fournie par un ADL. Selon Garlan et al., la majorité des stratégies ne sont pas complètes ou LATECE Technical Report, October 2006 Page 41 conformes sémantiquement. De plus, les stratégies assurant un degré élevé de complétude sont aussi celles qui ne facilitent pas la lisibilité et inversement. Zarras et al., (Zarras et al., 2001) proposent, quant à eux, un profile UML pour décrire les architectures. Ils ont donc défini un stéréotype pour chaque concept architectural (i.e. composant, connecteur et configuration). L’utilisation des mécanismes standards d’extension offerts par UML (tags, contraintes, stéréotypes et profils), pour supporter les descriptions architecturales a l’avantage considérable de permettre l’utilisation des différents outils existants supportant UML. Cela n’est pas le cas quand on étend le métamodèle UML en introduisant de nouveaux concepts (e.g. voir (Perez-Martinez, 2003)). D’autres chercheurs ont adopté une démarche complètement différente des stratégies que nous avons citées. Baresi et al. (Baresi et al., 2003) utilisent des diagrammes de classes pour modéliser la partie statique d’un style architectural. Les composants et leurs relations, dans une architecture concrète, sont représentés par des classes et leurs associations. Des contraintes et des règles peuvent être ajoutées au modèle sous forme d’expressions OCL. La particularité de l’approche est qu’elle utilise des règles de transformation de graphes pour modéliser les aspects dynamiques d’un style architectural. Une règle est représentée par une paire d’instances de graphe : une instance pour définir les pré-conditions pour l’application de la règle et une instance pour décrire les post-conditions. Ces deux instances sont intégrées dans un seul diagramme de collaboration UML où les éléments qui sont à supprimer (après application de la règle) sont marqués du tag {destroyed} et ceux à ajouter ont un tag {new}. Des techniques de validation et de vérification sont proposées pour démontrer la correction et la cohérence des descriptions architecturales basées sur les transformations de graphes. Les règles de transformation de graphes présentent une méthode intéressante pour spécifier l’aspect dynamique d’une architecture. Cependant, il n’est pas facile d’exprimer les règles, les contraintes et les mécanismes de contrôle d’une façon claire et précise tout en garantissant des analyses très puissantes. Aussi, Il n’y a pas d’outils supportant l’approche. Ce que l’on peut retenir de toutes ces études est que UML1.x ne favorise pas une démarche unique et meilleure pour décrire les concepts architecturaux (Garlan et al., 2002). En effet, la majorité des travaux étudiés ont souligné l’inadaptabilité d’UML1.x à la spécification explicite et complète des architectures. LATECE Technical Report, October 2006 Page 42 6.3 UML2.0 6.3.1 Le modèle de composant UML 2.0 a introduit de nouvelles constructions qui le rendent plus adapté au développement à base de composants et à la spécification des descriptions architecturales. Dans UML2.0, un composant possède un certain nombre d’interfaces fournies et d’interfaces requises. Une interface fournie spécifie les fonctionnalités fournies par un composant et une interface requise spécifie les fonctionnalités nécessaires au fonctionnement du composant. Le type d’un composant est donc défini par ses interfaces. La figure 19 montre un exemple de composant qui a deux interfaces fournies et trois interfaces requises (Person, Invoice et OrderableItem). Un composant interagit avec son environnement à travers des points d’interaction appelés ports. Les ports sont typés : un port fourni (resp. requis) a pour type une interface fournie (resp. requise). Les interfaces d’un composant sont exposées via les ports. Figure 19. Exemple de composant UML2.0 distingue les composants de base (atomiques) des composants composites appelés structures composites. Le paquetage BasicComponents (Fig.20) du méta-modèle d’UML2.0 définit un composant atomique comme un élément exécutable dans un système. Un composant atomique est un sous type de la méta-classe Class. Il peut donc avoir des attributs et des opérations comme il peut participer à des relations de généralisation ou d’association. Un composant de base possède une spécification externe sous forme d’interfaces fournies et requises et une implantation interne composée d’un ou plusieurs Classifiers qui réalisent son comportement. En effet, un composant est défini comme une unité qui encapsule l’état et le comportement d’un ensemble de classifiers. Le paquetage PackagingComponents (Figure 21), quant à lui, étend le concept de composant de base pour spécifier une structure composite qui est définie comme un block de construction pouvant contenir et importer un ensemble d’éléments. LATECE Technical Report, October 2006 Page 43 Figure 20. Les méta-classes définissant les composants de base Figure 21. Les méta-classes définissant les composants composites Un composant peut être représenté de différentes façons. On peut le représenter par une classe avec des compartiments contenant les interfaces, les attributs et les opérations. La représentation peut être une vue externe (« boite blanche ») où on montre seulement les interfaces du composant dans un compartiment de la classe. On peut attacher (optionnel) à une interface, un port ou le composant lui-même la description de son comportement sous forme d’une « machine à états ». On peut aussi représenter une interface comme un classifier ce qui permet d’afficher sa signature complète. Dans la vue interne («boite blanche»), par contre, des compartiments additionnels permettent de montrer les Classifiers réalisant le composant et aussi des listes des parties ou connecteurs faisant partie du composant ou d’artefacts d’implantation. Pour une présentation plus détaillée d’un composant (ex : Fig.22), on peut définir sa structure interne en terme de ses parties (instances de classes) et les connecteurs (instances d’associations) entre ces parties. La liaison entre les ports ou les interfaces des composants se font par des connecteurs. On distingue entre connecteurs de délégation et connecteurs d’assemblage. Les connecteurs de délégation relient les ports d’un composant aux éléments qu’il contient et qui réalisent son comportement. Ils modélisent la décomposition hiérarchique d’un comportement. La délégation peut se faire sur plusieurs niveaux LATECE Technical Report, October 2006 Page 44 (composition imbriquée). Deux interfaces (ports) reliées par un connecteur de délégation doivent être de type compatibles (les deux sont requises ou les deux sont fournies). Dans la figure 22, par exemple, on peut voir deux connecteurs de délégation (marqués par le mot clé « delegate »). Un connecteur d’assemblage relie deux composants, il joint une interface requise (port requis) à une interface fournie (un port fourni). Un exemple de connecteur d’assemblage est monté à la figure 23. Ce connecteur relie l’interface requise OrderableItem d’une instance du composant Order à l’interface fournie OrderableItem d’une instance du composant Product. Le type d’un connecteur est spécifié par un attribut (ConnectorKind) dont le type est une énumération ({assembly, delegation}). Figure 22. Une vue «boite blanche» de la structure interne d’un composant composite Figure 23. Un connecteur d’assemblage reliant les instances des composants Order et Product Plusieurs paquetages du méta-modèle UML2.0 permettent de spécifier les structures composites. Le paquetage InternalStructure (Figure 24 et 25) permet de spécifier les structures internes des composants. La méta-classe StructuredClassifier spécifie un classifier dont le comportement peut être décrit complètement ou partiellement par la collaboration d’instances qu’il contient ou référence. La méta-classe Property LATECE Technical Report, October 2006 Page 45 modélise les propriétés d’une instance de StructuredClassifier, en particulier, elle spécifie les instances pouvant être contenues dans l’instance d’un classifier (association part dans la figure 24). Le concept ConnectableElement représente des rôles pouvant être attribués aux instances de Property contenues dans l’instance d’un classifier. Ces rôles peuvent être reliés par des connecteurs. Un connecteur (Figure 25) est un lien qui permet aux instances de communiquer entre elles. Il peut représenter une instance d’une association ou un moyen de communication tel qu’un passage de paramètre, partage de variable, etc. Chaque extrémité de connecteur ConnectorEnd représente un rôle distinct faisant partie de la communication représentée par le connecteur. Un exemple de classe composite contenant 4 parties est montrée à la figure 26. Figure 24. Extrait du paquetage InternalStructure Figure 25. Extrait du paquetage InternalStructure LATECE Technical Report, October 2006 Page 46 Le paquetage Ports (Figure 27) fournit les concepts nécessaires pour spécifier les points d’interaction entre un classifier et son environnement. Le concept central dans ce paquetage est la métaclasse Port qui est défini comme une propriété d’un classifier (EncapsulatedClassifier dans la figure 27) qui est une extension de la métaclasse StructuredClassifier. EncapsulatedClassifier est un classifier ayant des ports typés par des interfaces. La métaclasse Port représente un point d’interaction entre un classifier et son environnement ou entre un classifier et ses parties internes. L’attribut isBehavior de Port spécifie, quand il est mis à « true », que les requêtes reçues via ce port seront traitées par l’instance du classifier qui contient le port et non pas par les instances pouvant être contenues par ce classifier. Par défaut, isBehavior est mise à « false ». L’attribut isService, quant à lui, spécifie, quand il est mis à « true », que le port est utilisé pour fournir une fonctionnalité publiée d’un classifier, sinon le port ne représente pas une fonctionnalité visible essentielle du classifier. Par défaut, un port est visible. La figure 22 montre une structure composite (store) ayant deux ports. Par contre, la figure 26 montre que les connecteurs ne sont pas attachés nécessairement aux parties d’une structure composite via des ports. Figure 26. Exemple de diagramme de structure Figure 27. Le paquetage Ports LATECE Technical Report, October 2006 Page 47 Le paquetage Collaborations (Figure 28 et 29) fournit les mécanismes permettant de décrire la collaboration entre un ensemble d’instances en leur attribuant des rôles qui sont typés par les interfaces des instances auxquelles ils sont associés. Le classifier est donc étendu de façon à ce qu’il puisse utiliser des collaborations appelées CollaborationUse (Figure 29). Une collaboration spécifie un ensemble de participants nécessaires pour réaliser une tâche spécifique. Ces participants sont spécifiés par des rôles reliés par des connecteurs. Les rôles sont typés par des interfaces. Une collaboration n’est pas instanciable directement. Une CollaborationUse représente l’application du patron décrit par une collaboration dans un contexte spécifique. En effet, les propriétés d’un classifier sont associées aux rôles d’une collaboration par l’intermédiaire des bindings des rôles d’une CollaborationUse. Une des CollaborationUse (représentée par l’association representation de la figure 29) d’un classifier peut décrire le comportement du classifier luimême. Les collaborations sont très utiles pour décrire les patrons de conception. Figure 28. Extrait du paquetage Collaborations Figure 29. Utilisation des collaboration et association des rôles LATECE Technical Report, October 2006 Page 48 Finalement, le paquetage StructuredClasses (partie gauche de la figure 30) étend la méta-classe EncapsulatedClass pour définir des classes pouvant avoir des ports et une structure interne et, le paquetage Actions (partie droite de la figure 30) étend les actions de base visant un objet pour introduire des actions spécifiques (InvocationAction) aux structures composites (ex : envoi de messages à travers un port). Figure 30. Les paquetages StructuredClasses et Actions 6.3.2 Le modèle de déploiement L’aspect implémentation d’une architecture est décrit par le paquetage de déploiement qui est composé de trois paquetages spécifiant un certain nombre de constructions qui permettent de définir une architecture d’exécution. Le paquetage Artifacts (Figure 31) définit la construction Artifact qui étend un Classifier pour représenter un élément concret (physique) résultant du processus de développement (e.g. fichier source, fichier de modèle, table dans une base de données, etc.). Un artifact peut être construit à partir de d’autres artifacts et il manifeste un ensemble d’éléments qui ont servi à sa génération. Une instance particulière d’un artifact est déployée en une instance d’un nœud. Figure 31. Le paquetage Artifacts LATECE Technical Report, October 2006 Page 49 Le paquetage Nodes (Figure 32 et 33) définit le concept de nœud et la relation basique de déploiement entre les artifacts et les nœuds. Un nœud représente soit un composant hardware ou un environnement d’exécution, c’est une ressource sur laquelle des artifacts peuvent être déployés. Les noeuds sont définis de façon imbriquée. Ils sont connectés par des chemins (paths) de communication pour créer un système relié. Un chemin de communication est en fait une association entre les localisations de deux artifacts déployés. Ces localisations sont appelées DeploymentTargets. Le déploiement est l’allocation d’un artifact ou d’une instance d’artifact à une cible de déploiement. Un artifact déployé est donc un artifact ou une instance d’artifact. Un nœud est un sous-type de Class et peut donc avoir une structure interne. Le paquetage ComponentDeployments (Figure 34) étend le modèle de dépoilement de base pour supporter des mécanismes de déploiement de certaines technologies communes de composants. Il définit le concept « spécification de déploiement » qui décrit les paramètres d’exécution d’un artifact composant déployé sur un nœud. L’ensemble des propriétés de déploiement d’une spécification sont spécifiques à un certain type de conteneur (Container). Figure 32. Le concept Noeud LATECE Technical Report, October 2006 Page 50 Figure 33. Définition de la relation de déploiement Figure 34. Le paquetage ComponentDeployments Un exemple de diagramme de déploiment est montré à la figure 35. Sur ce diagramme, il y a deux types de nœud (AppServer et DBServer) communiquants entre eux. Des artifacts (Order.jar, RequestHandler.jar) dont déployés sur un des nœuds. Figure 35. Exemple de diagramme de déploiement LATECE Technical Report, October 2006 Page 51 6.3.3 Le modèle comportemental Le comportement d’une classe peut être décrit par des interactions, des activités ou des machines à états. « Une action représente l’unité fondamentale de la spécification du comportement ». Les actions peuvent être reliées à des activités, des machines à états ou d’autres comportements. Une action peut être une action d’invocation (e.g. appel d’opération, envoi de message, etc.), une action de réorganisation structurelle (e.g. création d’objet, suppression, etc.) ou une action de calcul (fonction qui prend un ensemble d’entrées et donne un ensemble de sorties). Cette distinction permet une correspondance propre avec le modèle physique. Les actions reçoivent et fournissent des valeurs par l’intermédiaire d’éléments typés appelés « pins ». Les activités spécifient des séquences d’actions et des conditions pour coordonner ces séquences. La figure 36 montre un exemple d’activité décrivant un processus de commande avec des pré- et post-conditions et recevant un paramètre en entrée. Un des changements majeurs apportés par UML2.0 est l’intégration des activité avec les actions qui leur sont reliées. Figure 36. Exemple d’une activité « Une interaction est une unité de comportement qui se concentre sur un échange observable d’informations entre des éléments connectables ». Elle peut être présentée par différents types de diagrammes : diagrammes de séquence, diagrammes de communication (appelés diagrammes de collaboration dans UML1.x) et diagrammes d’interaction. Un exemple d’interaction décrite par un diagramme de séquence est montré à la figure 37. De plus, une interaction peut être utilisée dans la description d’une autre interaction (figure 38). Les diagrammes d’interaction, quant à eux, définissent les interactions en utilisant des diagrammes d’activités et des diagrammes de séquence (figure 39). LATECE Technical Report, October 2006 Page 52 Figure 37. Une interaction décrite par un diagramme de séquence Figure 38. Une interaction qui référence d’autres interactions LATECE Technical Report, October 2006 Page 53 Figure 39. Exemple de diagramme d’interaction 6.4 UML2.0 comme ADL Par rapport aux versions précédentes d’UML, beaucoup de concepts ont été introduit par UML2.0 visant à améliorer le support offert pour les descriptions architecturales. Cependant, il y a encore différentes façons de représenter certains concepts architecturaux avec UML2.0 (Ivers et al., 2004), ce qui ne facilite pas la tâche des architectes. De plus, le concept de Connecteur n’est pas modélisé comme une entité de première classe : la façon dont un connecteur est spécifié ne permet pas de lui attribuer une interface ni une LATECE Technical Report, October 2006 Page 54 sémantique comme le font certains ADLs (e.g. Wright). Aussi, UML2.0 ne décrit pas les propriétés fonctionnelles et n’offre pas un support explicite pour la modélisation des styles architecturaux. Toutefois, on peut représenter un style architectural en utilisant les mécanismes standards d’extensions offerts par UML, en particulier les profiles. 7. Conclusion Les ADLs se sont intéressés à la spécification des architectures d’une façon formelle et rigoureuse mais souvent très spécialisée. Ils permettent des analyses spécifiques puissantes. Cependant, ils sont généralement difficiles pour un concepteur non expérimenté. Ce qui limite leur intégration dans le processus de développement et leur utilisation dans le milieu industriel. En plus, la majorité des ADLs ne permettent pas de raffiner le modèle architectural de façon à aller jusqu’à la génération de code. Pour sa part, UML vise la modélisation en large sous une perspective orientée objet. Il est supporté par plusieurs outils dont certains vont jusqu’à la génération de l’implémentation d’un système. UML favorise une notation flexible et facile à utiliser par les concepteurs ce qui en fait un langage moins formel et moins rigoureux que les ADLs. 8. Références Allen R.J, « A Formal Approach to Software Architecture », PhD Thesis, CMU-CS-97-144, 1997. Allen R.J, Garlan D., « A Formal Basis for Architectural Connection », ACM Transactions on Software Engineering and Methodology, Vol. 6, No. 3, July 1997, p.213–249. Baresi L., Heckel R., Thöne S., Varró D., « Modeling and Analysis of Architectural Styles Based on Graph Transformation », The 6th ICSE Workshop on Component Based Software Engineering: Automated Reasoning and Prediction, May 3-4, 2003. P.C. Clements, “A Survey of Architecture Description Languages”, Proceedings of the eighth Int'l Workshop Software Specification and Design, Mars 1996. Garlan D., Allen R., Ockerbloom J., « Exploiting Style in Architectural Design Environments », Proceedings of SIGSOFT '94 Symposium on the Foundations of Software Engineering, December 1994. Garlan D., Shaw M., « An Introduction to Software Architecture », Carnegie Mellon University Technical Report CMU-CS-94-166, January 1994. LATECE Technical Report, October 2006 Page 55 Garlan D., « An introduction to the Aesop System », http://www.cs.cmu.edu/afs/cs/project/able /www/aesop/html/aesop-overview.ps , 1995. Garlan D., Monroe R.T., Wile D., « Acme: An Architecture Description Interchange Language », Proceedings of CASCON 97, Toronto, Ontario, November 1997, p.169-183. Garlan D., Monroe R.T., Wile D., « Acme: Architectural Description of Component-Based Systems », Foundations of Component-Based Systems, Leavens G.T. and Sitaraman M. (eds), Cambridge University Press, 2000, pp. 47-68. Garlan D., Cheng S.W., Kompanek A., « Reconciling the Needs of Architectural Description with Object-Modeling Notations », Science of Computer Programming Journal, 44 (1), July 2002, p.23-49. Hoare C. A. R., Communicating Sequential Processes, Prentice-Hall, Englewood Cliffs, N.J., 1985. Ivers J., Clements P., Garlan D., Nord R., Schmerl B., Silva J.R.O, «Documenting Component and Connector Views with UML 2.0 », Technical Report, CMU/SEI-2004-TR-008, avril 2004. Le Métayer D., « Describing Software Architecture Styles Using Graph Grammars », IEEE Transactions on Software Engineering, Vol.24, No.7, July 1998. Luckham D.C., Kenney J.J., Augustin L.M., Vera J., Bryan D., Mann W., « Specification and Analysis of System Architecture Using Rapide », IEEE Transactions on Software Engineering, Vol.21, No.4, April 1995, p.336-355. Magee J., Dulay N., Eisenbach S., Kramer J., « Specifying Distributed Software Architectures », the 5th European Software Engineering Conference (ESEC’95), Spain, 26 September 1995. OMG Model Driven Architecture, http://www.omg.org/cgi-bin/doc?omg/03-06-01, June 2003. Medvidovic N., Rosenblum D.S., Redmiles D.F., Robbins J.E., « Modeling Software Architectures in the Unified Modeling Language », ACM Transactions on Software Engineering and Methodology, Vol. 11, N0 .1, January 2002. Medvidovic N., Taylor R.N., « A classification and comparison framework for software architecture description languages », IEEE Transactions on Software Engineering, Vol.26, No.1, p.70-93, January 2000. LATECE Technical Report, October 2006 Page 56 Perez-Martinez J.E., « Heavyweight extensions to the UML metamodel to describe the C3 architectural style », ACM SIGSOFT Software Engineering notes, vol.28, No.3, Mai 2003. Shaw M., Garlan D., “Characteristics of Higher-Level Languages for Software Architecture”, Technical Report, CMUCS-94-210, Carnegie Mellon Univ., Dec. 1994. Shaw M., DeLine R., Klein D.V., Ross T.L., Young D.M., and Zelesnik G., « Abstractions for Software Architecture and Tools to Support Them », IEEE Trans. Software Eng., vol.21, no.4, p.314-335, April 1995. Taylor R.N., Medvidovic N., Anderson K.M., Whitehead Jr.E.J., Robbins J.E., Nies K.A., Oreizy P., Dubrow D.L., « A component- and message-based architectural style for GUI software », IEEE Transactions on Software Engineering, Vol.22, NO.6, JUNE 1996. UML2.0 Superstructure Specification: Adopted Specification, http://www.omg.org/docs/formal/0507-04.pdf , August 2005. UML2.0 Infrastructure Specification: Adopted Specification. http://www.omg.org/docs/formal/0507-05.pdf, March 2006. OCL2.0 Specification: Adopted Specification. http://www.omg.org/docs/ptc/05-06-06.pdf, June 2005. Vestal S., « A Cursory Overview and Comparison of Four Architecture Description Languages », Honeywell technical Report, February 1993. Zarras A., Issarny V., Kloukinas C., Nguyen V. K., « Towards a Base UML Profile for Architecture Description », 1st ICSE Workshop on Describing Software Architecture with UML, Canada, pp. 22-26, 2001. Zelesnik G., The UniCon Language User Manual, School of Computer Science Carnegie Mellon Universtity, Pittsburgh, Juin 1996. http://www.cs.cmu.edu/afs/cs/project/vit/www/unicon/reference- manual/Reference_Manual_1.html LATECE Technical Report, October 2006 Page 57