Tâche: Identifier les éléments de conception
Cette tâche explique comment identifier les sous-systèmes, les classes, les interfaces, les événements et les signaux.
Objet
  • Analyser les interactions entre les classes d'analyse pour identifier les éléments de modèle de conception
Relations
Description principale

La Tâche : Analyse des cas d'utilisation produit des classes d'analyse, qui représentent des éléments conceptuels pouvant adopter un comportement. En conception, les classes d'analyse évoluent vers un certain nombre de types différents d'éléments de conception :

  • des classes, pour représenter un ensemble de responsabilités à granularité plutôt fine ;
  • des sous-systèmes, pour représenter un ensemble de responsabilités à granularité grossière (ils sont composés éventuellement d'un autre ensemble de sous-systèmes, mais en dernier ressort d'un ensemble de classes) ;
  • des classes actives, qui représentent les fils de contrôle dans le système ;
  • des interfaces, pour représenter les déclarations abstraites de responsabilités fournies par une classe ou un sous-système.

De plus, en conception, il faut également identifier :

  • les événements, à savoir les spécifications d'occurrences intéressantes dans le temps et dans l'espace qui exigent habituellement (si elles sont remarquables) une réponse du système ; et
  • les signaux, qui représentent les mécanismes asynchrones utilisés pour communiquer certains types d'événements dans le système.

Ces distinctions plus fines nous permettent d'examiner différents aspects de la conception :

  • Les événements, et les signaux utilisés pour les communiquer, nous permettent de décrire les déclencheurs asynchrones de comportement auxquels le système doit répondre.
  • Les classes et les sous-systèmes nous permettent de regrouper les responsabilités associées en unités, lesquelles peuvent être développées de manière relativement indépendante. Les classes remplissent un ensemble atomique de responsabilités associées, tandis que les sous-systèmes sont des blocs de construction composites, formés à leur tour de classes ou d'autres sous-systèmes. Les sous-systèmes permettent de représenter les produits d'une équipe de développement en une seule unité intégrale de fonctionnalité. En tant que telles, elles sont utilisées à la fois comme unités de contrôle et de gestion de la configuration et comme éléments de conception logique.
  • Les classes actives sont utilisées pour représenter les fils de contrôle dans le système, ce qui nous permet de modéliser l'accès concurrent. Les classes actives sont souvent utilisées en combinaison avec d'autres classes qui sont généralement passives (mais pas nécessairement). Une telle combinaison peut alors permettre, tout comme une collaboration, de modéliser un comportement complexe.

    Dans les systèmes en temps réel, les capsules sont utilisées à la place des classes actives, offrant une sémantique plus forte pour simplifier la conception et accroître la fiabilité des applications concurrentes. Les capsules partagent certains aspects des classes et des sous-systèmes : il s'agit en effet de collaborations encapsulées de classes qui, ensemble, représentent un fil de contrôle dans le système. A la différence du sous-système, qui est (généralement) pris en charge par une équipe de développeurs, une capsule est prise en charge par un seul concepteur ; cependant, un sous-système peut contenir des capsules. 

  • Les interfaces nous permettent d'examiner et d'enregistrer les "coutures" du système, pour définir précisément la manière dont les parties constitutives du système vont interopérer.
  • Dans les systèmes en temps réel, nous devons utiliser les protocoles pour définir précisément les messages qui peuvent être envoyés et reçus sur le port d'une capsule.

En procédant à des distinctions et en traitant séparément chaque problème représenté par ces concepts, nous simplifions le processus de conception et clarifions notre solution.

Si la traçabilité doit être maintenue entre les modèles système, elle doit être documentée lors de cette tâche. Pour plus d'informations sur la documentation de la traçabilité entre le modèle de conception et les autres modèles système, voir Instructions : Modèle de conception.

 Représentation UML 1.x

Selon UML 1.5, un sous-système est un type particulier de package qui ne possède que des interfaces comme éléments publics. Les interfaces constituent une couche d'encapsulation qui permet à la conception interne du sous-système de rester invisible pour les autres éléments de modèle. Le concept de sous-système permet de distinguer ce dernier des packages "ordinaires", qui sont des conteneurs d'éléments de modèle sans sémantique ; le sous-système représente une utilisation particulière de packages possédant des propriétés de comportement semblables à celles des classes.

Dans le processus RUP, les capsules sont représentées à l'aide de la notation UML 1.5. Une grande partie peut être représentée dans UML 2.0 en utilisant le Concept: classe structurée.

Reportez-vous aux Différences entre UML 1.x et UML 2.0 pour plus d'informations.

Etapes
Identification des événements et des signaux
Objet Identifier les événements internes et externes et les signaux auxquels doit répondre le système. 

Les événements sont des occurrences internes et externes qui engendrent une action dans le système. Les événements et leurs caractéristiques peuvent permettre de guider l'identification des éléments de conception clés, tels que les classes actives.

Il est possible d'extraire une liste initiale d'événements externes à partir du modèle de cas d'utilisation et des interactions des acteurs avec les cas d'utilisation. Les événements internes peuvent provenir du texte des flux de cas d'utilisation, ou être identifiés au fil de l'évolution de la conception.

Les caractéristiques importantes des événements sont les suivantes :

  • Interne ou externe - L'événement est-il interne ou externe ?
  • Priorité - L'événement doit-il causer la suspension d'autres processus pour pouvoir être traité ?
  • Fréquence - A quelle fréquence se produit l'événement ?
  • Distribution de la fréquence - L'événement se produit-il à intervalles réguliers ou de manière sporadique ?
  • Exigences en termes de réponse - A quelle vitesse le système doit-il réagir à l'événement (il faudra éventuellement faire la distinction entre la moyenne et le pire des cas) ?
  • Type - S'agit-il d'un événement d'appel, temporel, de signal ou de changement (voir Concept : Evénements et signaux pour en connaître les définitions) ?

Les caractéristiques des événements doivent être enregistrées selon les besoins pour guider l'identification des éléments de conception qui les traitent. L'enregistrement de ces caractéristiques tend à être plus important dans les systèmes réactifs (commandés par les événements), mais il peut s'avérer utile dans d'autres systèmes, comme ceux qui utilisent des accès concurrents et/ou des messages asynchrones.

Les événements de communication asynchrones peuvent être modélisés sous forme de signaux pour exprimer les données contenues ou les relations entre les signaux, comme la généralisation. Dans certains systèmes, en particulier dans les systèmes réactifs, il est important d'associer les signaux reçus par des unités externes à des mécanismes spécifiques, tels que des interruptions ou des messages d'interrogation spécifiques.

Identification des classes, des classes actives et des sous-systèmes
Objet Affiner les classes d'analyse en éléments de modèle de conception appropriés 

Identifiez les classes. Lorsque la classe d'analyse est simple et qu'elle représente déjà une seule abstraction logique, elle peut être directement mappée un à un à une classe de conception. Habituellement, les classes entité restent relativement intactes lors du passage à la conception. Ces classes étant aussi généralement persistantes, déterminez si la classe de conception doit être persistante et faites-en la remarque dans la description de classe.

Lors de leur identification, les classes doivent être regroupées dans des Produits : Packages de conception, à des fins d'organisation et de gestion de la configuration. Voir Instructions relatives au produit : Package de conception pour plus d'informations sur les décisions relatives au regroupement par packages.

Identifiez les classes actives. Abordez les exigences liées aux accès concurrents du système sous l'angle des objets d'analyse identifiés : le système doit-il répondre à des événements générés de manière externe ? Si oui, quelles classes d'analyse sont "actives" lorsque l'événement se produit ? Les événements externes du modèle de cas d'utilisation sont représentés par des stimuli provenant d'acteurs qui interagissent avec un cas d'utilisation. Examinez les réalisations de cas d'utilisation correspondantes pour voir quels sont les objets qui interagissent lorsqu'un événement se produit. Commencez par regrouper les objets dans des ensembles autonomes d'objets collaborants ; ces regroupements constituent une première division dans un groupe susceptible de former une classe active composite.

Si les événements possèdent des attributs importants qui doivent être enregistrés, envisagez de les modéliser en tant que classes, <<signaux>> stéréotypés. Dans les systèmes en temps réel, ces ensembles d'objets identifiés doivent être regroupés dans des capsules, qui ont une très forte sémantique d'encapsulation.

Les instances de classes actives représentent des unités d'exécution "logiques" indépendantes. Ces unités d'exécution "logiques" ne doivent pas être confondues avec ou littéralement mappées aux unités d'exécution du système d'exploitation (même si le moment viendra où nous les mapperons à ces unités). Elles représentent au contraire des unités d'exécution conceptuelles indépendantes dans l'espace de solution. Leur identification à ce stade de la conception a pour but de permettre le partitionnement de la solution en unités indépendantes selon les "coutures" naturelles du système liées aux accès concurrents. La division du travail ainsi obtenue simplifie conceptuellement les problèmes de gestion de l'accès concurrent, puisque les unités d'exécution indépendantes peuvent être traitées séparément, à moins qu'elles ne partagent des classes passives sous-jacentes.

En général, une classe active doit être envisagée à chaque fois qu'il existe des accès concurrents ou des conflits entre les accès concurrents dans le domaine concerné. Une classe active doit servir à représenter un objet concurrent ou une activité concurrente externes dans l'ordinateur. Elle donne ainsi la possibilité de suivre et de contrôler les activités concurrentes.

Un autre choix naturel consiste à utiliser les classes actives comme des représentants internes ou des unités physiques externes connectés à un ordinateur, puisque ces entités physiques sont concurrentes par nature. Ces classes de "pilote de périphérique" servent non seulement à suivre et à contrôler les unités physiques correspondantes, mais également à isoler le reste du système des spécificités de ces unités. Ainsi, le reste du système peut ne pas être affecté lorsque la technologie des unités évolue.

Communément, les classes actives servent également à représenter les activités concurrentes logiques. Une activité logique désigne un "objet" concurrent conceptuel, tel que, par exemple, une transaction financière ou un appel téléphonique. Bien que que ces activités ne se manifestent pas directement en tant qu'entités physiques (même si elles ont lieu dans le monde physique), elles ont souvent des raisons d'être traitées comme telles. Par exemple, il peut être nécessaire de suspendre momentanément une transaction financière particulière afin d'éviter un conflit d'accès concurrents, ou de l'abandonner en raison de défaillances dans le système. Ces objets conceptuels devant être manipulés en tant qu'unités, il convient de les représenter comme des objets qui possèdent leurs propres interfaces offrant les capacités fonctionnelles appropriées.

Le contrôleur d'objets actifs est un exemple particulier de ce type d'objet conceptuel. Son but est de gérer en permanence un ou plusieurs autres objets actifs. Il s'agit en principe de porter chaque objet à l'état opérationnel souhaité, de le maintenir dans cet état malgré les différentes perturbations, telles qu'une défaillance partielle, et de synchroniser son opération avec celle d'autres objets. Ces contrôleurs d'objets actifs évoluent souvent à partir des objets de contrôle identifiés lors de la Tâche : Analyse des cas d'utilisation.

En raison de leur capacité à résoudre les conflits d'accès concurrents de manière simple et élégante, les classes actives sont également très utiles en tant que gardiennes des ressources partagées. Dans ce cas, une ou plusieurs ressources requises par plusieurs activités concurrentes sont encapsulées dans une classe active. En vertu de leur sémantique intégrée d'exclusion mutuelle, de telles gardiennes protègent automatiquement ces ressources des conflits d'accès concurrents.

Pour les systèmes en temps réel, vous devez utiliser les capsules à la place des classes actives : partout où vous avez identifié la nécessité d'une classe active, conformément à la méthode heuristique décrite ci-dessus, vous devez y substituer une capsule.

Identifiez les sous-systèmes. Lorsque la classe d'analyse est complexe, incarnant un comportement qu'une classe de conception unique ne peut gérer seule, elle doit être mappée à un sous-système de conception. Le sous-système de conception sert à encapsuler ces collaborations de façon à ce que ses clients ignorent totalement la conception interne du sous-système, même lorsqu'ils utilisent les services qu'il fournit.

Un sous-système est modélisé sous la forme d'un composant UML qui ne contient que des interfaces comme éléments publics. Les interfaces constituent une couche d'encapsulation qui permet à la conception interne du sous-système de rester invisible pour les autres éléments de modèle. Le concept de sous-système permet de distinguer ce dernier des packages, qui sont des conteneurs d'éléments de modèle sans sémantique.

La décision de créer un sous-système à partir d'un ensemble de classes d'analyse collaborantes repose en grande partie sur le fait de savoir si la collaboration pourra être ou sera développée séparément par une équipe de conception indépendante. Si les collaborations peuvent être entièrement contenues dans un package avec les classes collaborantes, un sous-système peut offrir une forme d'encapsulation plus solide que celle d'un simple package. Le contenu et les collaborations à l'intérieur d'un sous-système sont totalement isolés derrière une ou plusieurs interfaces ; de cette façon, le client du sous-système ne dépend que de l'interface. Le concepteur du sous-système est donc complètement isolé des dépendances externes ; le concepteur (ou l'équipe de conception) doit définir la façon dont l'interface est réalisée, mais il peut modifier la conception interne du sous-système sans affecter les dépendances externes. Dans les grands systèmes avec des équipes très indépendantes, ce degré de découplage ainsi que l'exécution architecturale des interfaces formelles sont de solides arguments pour choisir des sous-systèmes plutôt que de simples packages. Voir aussi Instructions relatives au produit : Sous-système de conception pour plus d'informations sur les facteurs qui motivent l'utilisation de sous-systèmes en tant qu'éléments de conception.

Identification des interfaces des sous-systèmes
Objet Identifier les éléments de conception qui formalisent les coutures du système. 

Les interfaces définissent un ensemble d'opérations réalisées par un discriminant. Dans le modèle de conception, elles servent essentiellement à définir les interfaces pour des sous-systèmes. Certes, elles peuvent être utilisées pour des classes également, mais il suffit généralement de définir les opérations publiques sur une classe pour en définir son "interface". Les interfaces sont importantes pour les sous-systèmes, car elles permettent d'effectuer la distinction entre la déclaration du comportement (l'interface) et la réalisation de ce comportement (les classes spécifiques du sous-système qui réalisent l'interface). Ce découplage permet d'accroître l'indépendance des équipes de développement qui travaillent sur différentes parties du système, tout en gardant des définitions précises des "contrats" qui lient ces différentes parties.

Pour chaque sous-système, identifiez un ensemble d'interfaces candidates. A l'aide des collaborations regroupées identifiées lors de l'étape précédente, identifiez la responsabilité qui est "activée" lorsque la collaboration est initiée. Ensuite, pour préciser cette responsabilité, déterminez quelles sont les informations qui doivent être fournies par le "client" et celles qui sont renvoyées lorsque la collaboration est achevée. Ces ensembles d'informations deviennent les paramètres d'entrée et de sortie et la valeur de retour du prototype pour une opération que le sous-système va réaliser. Spécifiez un nom pour cette opération, à l'aide des conventions de dénomination définies dans le Produit : Instructions relatives au projet. Répétez cette étape jusqu'à ce que soient définies toutes les opérations que le sous-système réalisera.

Ensuite, regroupez les opérations selon leurs responsabilités associées. Les plus petits groupes sont préférables aux plus grands. En effet, dans un groupe, lorsque le nombre d'opérations est plus petit, la cohésion de l'ensemble de responsabilités communes a plus de chance d'être forte. Ayez également toujours en vue les possibilités de réutilisation ; recherchez des similitudes qui pourraient faciliter l'identification des fonctionnalités associées réutilisables. Toutefois, ne passez pas trop de temps à chercher le regroupement idéal de responsabilités. Souvenez-vous qu'il s'agit seulement d'un premier classement que vous améliorerez de manière itérative tout au long de la phase d'élaboration.

Recherchez des similitudes entre les interfaces. A partir de l'ensemble d'interfaces candidates, recherchez des noms, responsabilités et opérations semblables. Lorsque les mêmes opérations existent dans plusieurs interfaces, refactorisez ces dernières en extrayant les opérations communes vers une nouvelle interface. Ne négligez pas non plus les interfaces existantes, en les réutilisant dans la mesure du possible. Le but est de maintenir la cohésion des interfaces tout en supprimant les opérations redondantes entre elles. Cette étape facilitera la compréhension des interfaces et leur évolution dans le temps.

Définissez des dépendances d'interface. Les paramètres et la valeur de retour de chaque opération d'interface ont chacun un type particulier : ils doivent réaliser une interface particulière ou doivent être des instances d'un type de données simple. Lorsque les paramètres sont des objets qui réalisent une interface particulière, définissez des relations entre cette interface et les interfaces dont elle dépend. Définissez des dépendances entre les interfaces qui fournissent des informations de couplage utiles à l'architecte logiciel, car les dépendances d'interface définissent les principales dépendances entre les éléments du modèle de conception.

Mappez les interfaces aux sous-systèmes. Après avoir identifié les interfaces, créez des associations de réalisation entre le sous-système et les interfaces qu'il réalise. Une réalisation depuis le sous-système vers une interface indique qu'un ou plusieurs éléments du sous-système réalisent les opérations de cette interface. Plus tard, une fois le sous-système conçu, ces réalisations interface/sous-système seront précisées, lorsque le concepteur du sous-système définira les éléments spécifiques qui réaliseront les opérations de l'interface. Ces réalisations précisées ne sont visibles que pour le concepteur ; pour le client du sous-système, seule la réalisation interface/sous-système est visible.

Définissez le comportement spécifié par les interfaces. Les interfaces définissent souvent une machine d'état implicite pour les éléments qui réalisent l'interface. Si les opérations sur l'interface doivent être appelées dans un ordre particulier (par exemple, il faut ouvrir une connexion à une base de données avant de pouvoir l'utiliser), vous devez définir une machine d'état qui illustre les états visibles publiquement (ou induits) que doit prendre en charge tout élément de conception qui réalise l'interface. Cette machine d'état aidera l'utilisateur de l'interface à mieux comprendre cette interface, et le concepteur des éléments qui réalisent l'interface à leur donner le bon comportement.

Regroupez les interfaces en packages. Le propriétaire des interfaces est l'architecte logiciel ; les changements apportés aux interfaces sont toujours importants pour l'architecture. Pour gérer cette situation, les interfaces doivent être regroupées en un ou plusieurs packages dont l'architecte logiciel est le propriétaire. Si chaque interface est réalisée par un seul sous-système, les interfaces peuvent être placées dans le même package avec le sous-système. Si les interfaces sont réalisées par plus d'un sous-système, elles doivent être placées dans plusieurs packages en possession de l'architecte logiciel. Ainsi, les interfaces peuvent être gérées et contrôlées indépendamment des sous-systèmes.

Identification des protocoles de capsules

Objet

Identifier les éléments de conception qui formalisent les coutures du système (conception en temps réel uniquement).

Dans les systèmes commandés par les événements, les protocoles sont semblables aux interfaces : ils identifient le "contrat" qui lie les capsules entre elles en définissant un ensemble de signaux correspondants, utilisés pour communiquer entre les unité d'exécution de contrôle indépendantes. Tandis que les interfaces servent essentiellement à définir la messagerie synchrone à l'aide d'une fonction d'appel, les protocoles, eux, servent essentiellement à définir la communication asynchrone à l'aide d'une technique de messagerie par signaux. Les protocoles permettent d'effectuer la distinction entre la déclaration du comportement (l'ensemble de signaux) et la réalisation de ce comportement (les éléments du sous-système qui réalisent l'interface). Ce découplage permet d'accroître l'indépendance des équipes de développement qui travaillent sur différentes parties du système, tout en gardant des définitions précises des "contrats" qui lient ces différentes parties.

Pour chaque capsule, identifiez un ensemble de signaux d'entrée et de sortie. A l'aide des collaborations regroupées identifiées au cours d'étapes antérieures, identifiez la responsabilité qui est "activée" lorsque la collaboration est initiée. Ensuite, pour préciser cette responsabilité, déterminez quelles sont les informations qui doivent être fournies par le "client" et celles qui sont renvoyées lorsque la collaboration est achevée. Ces ensembles d'informations deviennent les paramètres d'entrée du prototype pour un signal que la capsule va réaliser par l'un de ses ports. Spécifiez un nom pour ce signal, à l'aide des conventions de dénomination définies dans le Produit : Instructions relatives au projet. Répétez cette étape jusqu'à ce que soient définis tous les signaux que la capsule réalisera.

Ensuite, regroupez les signaux selon leurs responsabilités associées. Les plus petits groupes sont préférables aux plus grands. En effet, dans un groupe, lorsque le nombre de signaux est plus petit, la cohésion de l'ensemble de responsabilités communes a plus de chance d'être forte. Ayez également toujours en vue les possibilités de réutilisation ; recherchez des similitudes qui pourraient faciliter l'identification des fonctionnalités associées réutilisables. Toutefois, ne passez pas trop de temps à chercher le regroupement idéal de responsabilités. Souvenez-vous qu'il s'agit seulement d'un premier classement que vous améliorerez de manière itérative tout au long de la phase d'élaboration. Donnez au protocole un nom significatif, décrivant le rôle qu'il joue dans les collaborations de capsule.

Recherchez des similitudes entre les protocoles. A partir de l'ensemble de protocoles candidats, recherchez des noms, responsabilités et signaux semblables. Lorsque les mêmes signaux existent dans plusieurs protocoles, refactorisez ces derniers en extrayant les signaux communs vers un nouveau protocole. Ne négligez pas non plus les protocoles existants, en les réutilisant dans la mesure du possible. Le but est de maintenir la cohésion des protocoles tout en supprimant les signaux redondants entre eux. Cette étape facilitera la compréhension des protocoles et leur évolution dans le temps.

Mappez les protocoles aux sous-systèmes. Après avoir identifié les protocoles, créez des ports sur les capsules qui les réalisent. Les ports d'une capsule définissent ses "interfaces", c'est-à-dire le comportement qui peut lui être demandé. Plus tard, une fois la capsule conçue, le comportement spécifié par les ports sera décrit par la machine d'état pour cette capsule.

Définissez le comportement spécifié par les protocoles. Les protocoles définissent souvent une machine d'état implicite pour les éléments qui réalisent l'interface. Si les signaux d'entrée sur l'interface doivent être reçus dans un ordre particulier (par exemple, il faut recevoir un signal "système prêt" avant de pouvoir recevoir un signal d'erreur particulier), vous devez définir une machine d'état qui illustre les états visibles publiquement (ou induits) que doit prendre en charge tout élément de conception qui réalise le protocole. Cette machine d'état aidera l'utilisateur des capsules à mieux les comprendre, et le concepteur de ces capsules à donner le bon comportement à leurs éléments.

Regroupez les protocoles en packages. Le propriétaire des protocoles est l'architecte logiciel ; les changements apportés aux protocoles sont toujours importants pour l'architecture. Pour gérer cette situation, les protocoles doivent être regroupés en un ou plusieurs packages dont l'architecte logiciel est le propriétaire. Ainsi, les protocoles peuvent être gérés et contrôlés indépendamment des capsules qui les réalisent.


Propriétés
Plusieurs occurrences
Commandé par les événements
En cours
Facultatif
Planifié
Réitérable
Plus d'informations