Concept: Classe structurée
Une classe structurée est composée de plusieurs parties ayant une notation "imbriquée" explicite. Elle est utilisée pour modéliser les hiérarchies de conteneurs qui sont des classes composées de "composants".
Relations
Eléments connexes
Description principale

Définition

Selon UML ([UML04]), une classe est un sous-type à la fois d'un classificateur encapsulé et d'une métaclasse de classe, ce qui veut dire qu'elle a une structure interne et des ports. Un composant est défini aussi par UML comme un sous-type d'une classe. Dans le contexte RUP, nous faisons donc référence aux composants et aux classes comme étant des classes structurées.

Composant

Une instance d'une classe structurée est composée d'un objet ou d'un ensemble d'objets qui correspondent à chaque composant. Une instance est détruite lorsque la classe structurée à laquelle elle appartient est détruite.

L'exemple ci-dessous montre deux vues possibles de la classe Voiture :

Dans la figure (a), Voiture a une association de composition dont le nom de rôle est arrière avec la classe Roue et une association de composition dont le nom de rôle est m avec la classe Moteur. Toute instance de la classe Moteur peut être liée à un nombre quelconque d'instances de la classe Roue.

Dans la figure (b), on peut voir la même chose. Toutefois, dans la figure (b), il est précisé que :

  • arrière et m appartiennent à la structure interne de la classe Voiture. Cela permet de préciser des détails seulement valables pour les instances de Roue et de Moteur dans le contexte de la classe Voiture, mais non valables pour toutes les classesRoue et Moteur en général.

  • dans le contexte de la classe Voiture, l'instance jouant le rôle de m peut être reliée seulement à deux instances avec le rôle arrière. De plus, les instances avec les rôles m et arrière peuvent être liées seulement si elles sont les rôles de la même instance de la classe Voiture.

  • Autrement dit, il existe des contraintes supplémentaires pour les instances des classes Roue et Moteur, lorsqu'elles jouent leur rôle respectif à l'intérieur d'une instance de la classe Voiture. Ces contraintes ne sont pas applicables aux instances de Roue et de Moteur en général. Il se peut que d'autres instances Roue et Moteur soient arbitrairement liées, comme indiqué dans la figure (a).

Diagramme décrit dans le texte d'accompagnement.

Exemple : Composants qui jouent leur rôle dans une classe structurée

Connecteur

Un connecteur est une instance de la relation entre deux composants dans une classe structurée. Il s'agit d'un lien qui permet la communication. Les connecteurs peuvent être implémentés par des associations ordinaires ou par des relations transitoires, telles que des paramètres de procédure, des variables, des valeurs globales ou d'autres mécanismes.

Le "câblage" interne d'une classe structurée est formé par des connecteurs d'assemblage et des connecteurs de délégation :

  • Dans l'implémentation d'une classe structurée, les connecteurs d'assemblage sont reliés à des ports de composants différents. Le message envoyé à un port d'une classe structurée est reçu sur un port connecté d'une autre classe structurée. Plusieurs composants peuvent être câblés entre eux via leurs ports. Un composant n'a pas besoin de savoir quoi que ce soit sur les autres composants, sauf qu'ils existent et qu'ils répondent aux contraintes sur les ports connectés. La communication entre les classes structurées est modélisée par leurs ports.


  • Un connecteur de délégation connecte un port externe d'une classe structurée avec un port de l'un de ses composants internes. Le message reçu par un port externe est transmis sur le port du composant interne ; un message envoyé par le port interne est transmis au port externe qui le transmet aux classes structurées auxquelles il est relié.

Port

Un port est une caractéristique structurelle d'une classe structurée. L'encapsulation peut être augmentée en forçant les communications depuis l'extérieur des classes structurées à passer par des ports obéissant aux interfaces déclarées, ce qui donne une précision supplémentaire à la spécification et à l'interconnexion de cette classe structurée.

Les interfaces requises et fournies d'un port précisent tout ce qui est nécessaire pour des interactions par le biais de ce point d'interaction. Si toutes les interactions d'une classe structurée avec son environnement sont réalisées par les ports, les éléments internes de la classe structurée sont complètement isolés de l'environnement. Ceci permet qu'une telle classe structurée soit utilisée dans tout contexte qui répond aux contraintes indiquées par ses ports.

Il n'y a pas d'obligation quant à la façon d'implémenter un port. Il peut être implémenté en tant qu'objet explicite, ou tout simplement il peut être un simple concept virtuel qui n'apparaît pas explicitement dans l'implémentation.

Vous trouverez ci-dessous plusieurs exemples de ports :

Exemple 1

Diagramme décrit dans le texte d'accompagnement.

Port d'un moteur utilisé par une voiture et par un bateau

La figure ci-dessus montre une classe Moteur avec un port p et deux interfaces :

  • Une interface fournie, propulsion, qui spécifie les services que le moteur offre à ce port (par exemple, les opérations et les réceptions accessibles par les communications arrivant à ce port).
  • Une interface requise, puissance, qui spécifie les services que le moteur attend de l'environnement.

Sur le port p, la classe Moteur est entièrement encapsulée ; elle peut être spécifiée sans connaissance de l'environnement dans lequel le moteur sera installé. Tant que l'environnement obéit aux contraintes imposées par les interfaces fournies et requises du moteur, celui-ci fonctionnera correctement.

Pour illustrer cela, deux utilisations de la classe Moteur sont représentées dans l'exemple ci-dessous :

  • La classe Voiture connecte le port p du moteur à un ensemble de roues au moyen d'un essieu axe.
  • La classe Bateau connecte le port p du moteur à une hélice au moyen d'un arbre.

Tant que l'interaction entre le Moteur et le composant relié à son port p obéit aux contraintes spécifiées par les interfaces fournies et requises, le moteur fonctionnera comme prévu, qu'il s'agisse d'un moteur de voiture ou d'un moteur de bateau.

De plus, même si Moteur a d'autres ports déclarés, comme le port c pour consommation de carburant, les roues d'une voiture et l'hélice d'un bateau accéderont toujours au Moteur via le port p. Le port c est intéressant dans le cas d'une jauge à carburant, quel que soit la sorte de carburant utilisée ou la sorte de jauge carburant que possèdent les voitures ou les bateaux.

Exemple 2

Cet exemple de ports est basé sur Java Logging API ([JAV03]), package qui fournit les classes et les interfaces des fonctionnalités de connexion de base de la plateforme de Java 2, parmi lesquelles :

  • L'enregistreur automatique Logger, qui est le dispositif principal auquel les applications font des appels d'enregistrement. Il est utilisé afin d'enregistrer des messages concernant un système spécifique ou un composant d'une application.
  • Le niveau Level, qui donne une indication sur l'importance et l'urgence du message enregistré
  • Le filtre Filter, qui effectue un contrôle fin des messages enregistrés, plus poussé que le contrôle des niveaux d'enregistrement
  • Le gestionnaire Handler, qui prend les messages de l'enregistreur automatique et les exporte vers des destinations différentes (une mémoire, des flux de données de sortie, des consoles, des fichiers et des interfaces de connexion)
  • Le programme de mise en forme Formatter, qui fournit un support afin de mettre en forme les enregistrements chronologiques

Ces classes et interfaces sont concernées par deux sortes de collaborations. Certaines classes et interfaces sont utilisées pour écrire dans le journal tandis que d'autres servent à le gérer. La figure ci-dessous montre deux collaborations différentes que les clients et les administrateurs ont avec le journal, modélisées en tant que collaborations UML :

  • Collaboration d'écriture (Writing), où le rôle LogClient se connecte au rôle LogWriter afin d'écrire dans le journal.
  • Collaboration d'administration, où le rôle LogAdministrator se connecte au rôle LogController afin d'accéder au journal et d'en changer les paramètres.

Diagramme décrit dans le texte d'accompagnement.

Différentes collaborations que les clients et administrateurs peuvent avoir avec le journal

Une représentation UML 2.0 possible pour la modélisation des services d'enregistrement et ses collaborations serait l'utilisation d'un composant avec des ports et des interfaces déclarées, comme on peut le voir sur l'illustration ci-dessous :

Diagramme décrit dans le texte d'accompagnement.

Le package Java Logging API implémenté en tant que composant avec des interfaces fournies regroupées dans des ports

Dans la spécification de Java Logging API, certains des services d'enregistrement ont été implémentés en tant que classes et d'autres en tant qu'interfaces. Dans cet exemple, nous avons modélisé chacun de ces services comme des interfaces fournies et qui pourraient être réalisées par des parties à l'intérieur du composant. Les deux sortes de comportement liées aux collaborations pour l'écriture et l'administration dont nous avons parlé ci-dessus pourraient être représentées par des interfaces regroupées de façon logique en ports. Nous avons donc :

  • Les interfaces Logger et Level regroupées dans le port LogWriter. Ces interfaces sont accessibles par les clients du journal pour écrire dans ce dernier.
  • Les interfaces Handler, Filter et Formatter regroupées dans le port LogController. Les administrateurs de journal accèdent à ces interfaces afin de changer les paramètres du journal.

Cette alternative de modélisation conduit à une séparation des préoccupations et regroupe les interfaces de façon logique dans des ports différents. Vous pouvez nous consulter pour d'autres précisions sur la spécification des composants et l'interconnexion avec le monde extérieur.

Modélisation

Pendant la conception, les classes et composants peuvent être décomposés en séries de parties connectées qui peuvent à leur tour être décomposées.

Un diagramme de structure composite peut servir à montrer comment une classe structurée est décomposée. La figure ci-dessous est un exemple de diagramme de structure composite pour le bureau de location dans un système de vente de billets. Cette classe se décompose en trois parties :

  • Une interface vente de billets
  • Un guide des performances qui recherche les performances en fonction de la date et d'autres critères
  • Un ensemble de bases de données qui contiennent les informations sur des performances et des billets.

Chaque partie interagit par le biais d'une interface bien définie et déterminée par ses ports. Le bureau entier interagit avec l'extérieur à travers un port. Les messages de ce port sont envoyés à la classe vendreBillets, mais la classe bureau de location est cachée pour les clients.

Diagramme décrit dans le texte d'accompagnement.

Exemple : Diagramme de structure composite pour un système de billets.

Représentation UML 1.x

Notez que la classe structurée est un nouveau concept dans UML 2.0.

La majeure partie de ce que le processus RUP définit comme une capsule peut être représentée en utilisant une classe structurée comme notation (voir  Produit : Capsule et  Instructions relatives aux produit : Capsule pour plus d'informations sur ce sujet).

Si votre outil ne prend en charge qu'UML 1.5, vous trouverez une représentation alternative dans  Produit : Capsule et  Instructions relatives au produit : Capsule.

Voir aussi Les différences entre UML 1.x et UML 2.0 pour plus d'informations.