Rubriques

DéfinitionHaut de la page

Une classe de conception représente l'abstraction d'une ou plusieurs classes dans l'implémentation du système : ce à quoi cela correspond précisément, dépend du langage d'implémentation. Par exemple, dans un langage orienté objet tel que C++, une classe correspond à une classe ordinaire. Dans Ada, une classe peut correspondre à un type balisé défini dans la partie visible du package.

Les classes définissent des objets, qui à leur tour exécutent (implémentent) les cas d'utilisation. Une classe provient des exigences définies par les réalisations de cas d'utilisation sur les objets nécessaires au système. Elle peut également provenir de tout modèle d'objet précédemment développé.

L'environnement d'implémentation détermine si une classe est bonne ou non. La taille appropriée de la classe et de ses objets dépend par exemple du langage de programmation. Ce qui convient quand on utilise Ada peut ne pas convenir quand on utilise Smalltalk. Les classes doivent correspondre à un phénomène particulier dans le langage d'implémentation et elles doivent être structurées pour permettre au mappage de générer le bon code.

Bien que les particularités du langage d'implémentation influent sur le modèle de conception, vous devez faire en sorte que la structure de classes soit facile à comprendre et à modifier. La conception doit être réalisée comme si vous utilisiez des classes et l'encapsulation, même si cela n'est pas pris en charge par le langage d'implémentation.

Opérations Haut de la  page

La seule manière pour un objet d'accéder (ou d'affecter) aux attributs ou relations d'un autre objet est par l'intermédiaire des opérations. Les opérations d'un objet sont définies par sa classe. Un comportement spécifique peut être réalisé par l'intermédiaire des opérations, ce qui peut se répercuter sur les attributs et relations de l'objet et produire d'autres opérations à exécuter. Une opération correspond à une fonction membre en C++ ou, dans Ada, à une fonction ou une procédure. Le choix du comportement attribué à un objet dépend du rôle qu'il a dans les réalisations de cas d'utilisation.

Paramètres Haut de la page

Les paramètres constituent les paramètres formels dans la spécification d'une opération. Chaque paramètre dispose d'un nom et d'un type. Vous pouvez utiliser la syntaxe et la sémantique du langage d'implémentation pour définir les opérations et leurs paramètres, afin qu'ils soient déjà spécifiés dans le langage d'implémentation au démarrage de la programmation.

Exemple :

Dans le système de machine de recyclage, les objets de la classe base de réception conservent la trace du nombre d'éléments d'un certain type qu'un client a remis. Le comportement d'un objet de base de réception comporte l'incrémentation du nombre d'objets retournés. L'opération Insérer Article, qui reçoit une référence de l'objet remis, remplit cet objectif.

Diagramme décrit dans le texte d'accompagnement.

Utilisez la syntaxe et la sémantique du langage d'implémentation pour spécifier les opérations.

Opérations de classe Haut de la page

Une opération dénote presque toujours le comportement de l'objet. Une opération peut aussi dénoter le comportement d'une classe ; dans ce cas, il s'agit d'une opération de classe. Cela peut être modélisé dans l'UML en attribuant un type de comportement à cette opération.

Visibilité de l'opération Haut de la page

Les visibilités suivantes sont disponibles pour une opération :

  • Publique : l'opération est visible pour les éléments de modèle autres que la classe elle-même.
  • Protégée : l'opération n'est visible que pour la classe elle-même, ses sous-classes, ou les amis de la classe (suivant le langage)
  • Privée : l'opération n'est visible que par la classe elle-même et par les amis de la classe
  • Implémentation : l'opération n'est visible qu'à l'intérieur de la classe.

La visibilité publique doit être très peu utilisée, exclusivement quand une autre classe nécessite une opération.

La visibilité protégée doit être la visibilité par défaut ; elle protège l'opération et l'empêche d'être utilisée par les classes externes, ce qui favorise le couplage lâche et l'encapsulation du comportement.

La visibilité privée doit être utilisée quand vous voulez empêcher les sous-classes d'hériter de l'opération. Cela permet de découpler les sous-classes de la super-classe et d'éviter de supprimer ou d'exclure les opérations inutiles.

La visibilité Implémentation est la visibilité la plus restrictive ; elle est utilisée là où seule la classe elle-même peut utiliser l'opération. C'est une variante de la visibilité privée, qui est le plus souvent appropriée.

Etats Haut de la  page

Un objet peut réagir différemment à un message spécifique, selon l'état dans lequel il se trouve ; le comportement d'un objet dépendant de l'état est défini par un diagramme d'état-transition associé. Pour chaque état que l'objet peut avoir, ce diagramme décrit les messages qu'il peut recevoir, les opérations qui peuvent être effectuées, et dans quel état va ensuite se trouver l'objet. Voir Principes et conseils : Diagramme d'état-transition pour plus d'informations.

Collaborations Haut de la page

Une collaboration est un ensemble dynamique d'interactions d'objets, dans lequel un ensemble d'objets communiquent en s'envoyant des messages. L'envoi de messages est une opération directe dans Smalltalk ; dans Ada, cela passe par un appel de sous-programme. Un message est envoyé à un objet destinataire qui appelle une opération au sein de l'objet. Le message indique le nom de l'opération à réaliser, ainsi que les paramètres requis. Lorsque les messages sont envoyés, les vrais paramètres (valeurs des paramètres formels) sont fournis pour tous les paramètres.

Les transmissions de messages entre les objets d'une réalisation de cas d'utilisation, ainsi que le contrôle des objets au fur et à mesure que les opérations sont appelées, sont décrits dans les diagrammes d'interaction. Voir Principes et conseils : Diagramme de séquences et Principes et conseils : Diagramme de communication pour obtenir plus d'informations sur ces diagrammes.

Attributs Haut de la page

Un attribut correspond à une propriété nommée d'un objet. Le nom d'un attribut est un nom décrivant le rôle des attributs par rapport à l'objet. Un attribut peut avoir une valeur initiale quand l'objet est créé.

Vous devez modéliser des attributs uniquement si cette opération permet de rendre l'objet plus compréhensible. Vous devez modéliser la propriété d'un objet en tant qu'attribut uniquement s'il s'agit d'une propriété appartenant à cet objet exclusivement. Sinon, vous devez modéliser la propriété avec une relation d'association ou d'agrégation à une classe dont les objets représentent la propriété.

Exemple :

Diagramme décrit dans le texte d'accompagnement.

Exemple de modélisation d'un attribut. Chaque membre d'une famille a un nom et une adresse. Ici, nous avons identifié les attributs mon nom et adresse personnelle, respectivement de type Nom et Adresse :

Diagramme décrit dans le texte d'accompagnement.

Dans cet exemple, on utilise une association à la place d'un attribut. La propriété mon nom est probablement unique pour chaque membre d'une famille. Nous pouvons donc la modéliser comme un attribut du type Nom. Une adresse est partagée par tous les membres de la famille ; elle sera donc mieux modélisée en utilisant une association entre la classe Membre de la famille et la classe Adresse.

Il n'est pas toujours facile de savoir immédiatement s'il convient de modéliser un concept comme un objet séparé ou comme l'attribut d'un autre objet. La présence d'objets superflus dans le modèle d'objet conduit à la rédaction d'une documentation superflue et à des efforts de développement inutiles. Il vous faudra donc établir certains critères déterminant le degré d'importance d'un concept par rapport au système.

  • Accessibilité. Ce qui doit régir votre choix entre objet et attribut n'est pas l'importance du concept dans la vie réelle, mais le besoin d'y accéder durant le cas d'utilisation. Si les accès à l'unité sont fréquents, modélisez-la comme un objet.
  • Séparation durant l'exécution. Modélisez les concepts traités séparément durant l'exécution des cas d'utilisation comme des objets.
  • Liens vers d'autres concepts. Modélisez les concepts strictement liés à certains autres concepts et n'étant jamais utilisés séparément, mais toujours par l'intermédiaire d'un objet, comme des attributs de l'objet en question.
  • Exigences des relations. Si, pour une raison quelconque, vous devez rattacher une unité à partir de deux directions, vous devrez la ré-examiner pour voir si elle doit être considérée comme un seul objet. Deux objets ne peuvent associer la même instance d'un type d'attribut.
  • Fréquence de l'occurrence. Si une unité apparaît uniquement dans le cadre d'un seul cas d'utilisation, ne la modélisez pas comme un objet. Modélisez-la plutôt comme un attribut de l'objet qui réalise le comportement en question, ou mentionnez-la simplement dans la description de l'objet concerné.
  • Complexité. Si un objet devient trop compliqué en raison de ses attributs, vous pouvez extraire certains des attributs dans des objets séparés. Faites néanmoins cela avec modération, pour éviter d'avoir trop d'objets. D'autre part, certaines unités peuvent être très simples. Par exemple, on considère comme attributs (1) les unités qui sont assez simples pour être directement prises en charge par des types primitifs du langage d'implémentation, tels que les entiers dans C++, et(2) les unités qui sont assez simples pour être implémentées en utilisant des composants indépendants de l'application dans l'environnement d'implémentation, comme Chaîne en C++ et Smalltalk-80.

Vous modéliserez probablement un concept de façon différente pour les différents systèmes. Dans un système, le concept peut être si vital que vous le modéliserez comme un objet. Dans un autre, il peut n'avoir que peu d'importance, et vous le modéliserez comme l'attribut d'un objet.

Exemple :

Par exemple, dans le cas d'une compagnie aérienne, vous pourriez développer un système prenant en charge les départs.

Diagramme décrit dans le texte d'accompagnement.

Un système qui prend en charge les départs. Supposons que le personnel d'un aéroport souhaite bénéficier d'un système prenant en charge les départs. Pour chaque départ, vous devez définir l'heure de départ, la compagnie aérienne et la destination. Vous pouvez le modéliser comme l'objet d'une classe Départ, avec les attributs heure de départ, compagnie aérienne et destination.

Si, au lieu de cela, le système est développé pour une agence de voyage, la situation pourrait être légèrement différente.

Diagramme décrit dans le texte d'accompagnement.

Les destinations des vols constituent un objet, Destination.

L'heure de départ, la compagnie aérienne et la destination seront bien sûr nécessaires. Il y a cependant d'autres exigences, car une agence de voyage doit pouvoir trouver un départ associé à une destination spécifique. Vous devez donc créer un objet séparé pour la Destination. Les objets Départ et Destination doivent naturellement être liés, ce qui est réalisé au moyen d'une association entre leurs classes.

L'argument d'importance de certains concepts est également valable pour déterminer quels attributs sont définis dans une classe. Il est certain que la classe Voiture définira des attributs différents si ses objets apparaissent dans un système d'enregistrement des véhicules motorisés, ou s'ils font partie d'un système de fabrication d'automobiles.

Enfin, les règles définissant ce qui doit être représenté comme des objets et ce qui doit être représenté comme des attributs, ne sont pas des règles absolues. Théoriquement, vous pouvez tout modéliser comme des objets, mais ce n'est pas recommandé. Un principe de base est de considérer un objet comme quelque chose qui à un moment est utilisé indépendamment des autres objets. De plus, il n'est pas nécessaire de modéliser chaque propriété d'objet en utilisant un attribut : seules les propriétés nécessaires à la compréhension de l'objet doivent être modélisées. Vous ne devez pas modéliser les détails qui sont si spécifiques à l'implémentation, qu'ils sont mieux traités par l'implémenteur.

Attributs de classe Haut de la page

Un attribut indique pratiquement toujours les propriétés de l'objet. Un attribut peut également indiquer les propriétés d'une classe ; dans ce cas, il s'agit d'un attribut de classe. Cela peut être modélisé dans l'UML, en attribuant un type de comportement à cet attribut.

Modéliser des unités externes avec des attributs Haut de la page

Un objet peut encapsuler un élément dont la valeur peut changer, sans que l'objet n'exécute aucun comportement. Cela peut être réellement une unité externe, qui n'a pas été modélisée comme un acteur. Par exemple, les frontières du système peuvent avoir été choisies, pour renfermer une certaine forme d'équipement de capteurs. Le capteur peut être encapsulé dans un objet, de manière que la valeur qu'il mesure constitue un attribut. Cette valeur peut ensuite changer continuellement, ou à certains intervalles, sans que l'objet ne soit affecté par aucun autre objet du système.

Exemple :

Vous pouvez modéliser un thermomètre comme un objet : l'objet comporte un attribut qui représente la température et change de valeur en réponse aux variations de température de l'environnement. D'autres objets peuvent demander à connaître la température actuelle en exécutant une opération sur l'objet thermomètre.

Diagramme décrit dans le texte d'accompagnement.

La valeur de l'attribut température change spontanément dans l'objet Thermomètre.

Vous pouvez toujours modéliser une valeur encapsulée qui change de cette façon en tant qu'attribut, mais vous devez indiquer dans la classe de l'objet que cet attribut change spontanément.

Visibilité de l'attribut Haut de la page

La visibilité de l'attribut prend l'une des valeurs suivantes :

  • Publique : l'attribut est visible à l'intérieur et à l'extérieur du package contenant la classe.
  • Protégée : l'attribut est uniquement visible pour la classe, ses sous-classes ou les amis de la classe (suivant le langage)
  • Privée : l'attribut n'est visible que pour la classe elle-même et pour les amis de la classe
  • Implémentation : l'attribut est visible uniquement pour la classe elle-même.

La visibilité Publique doit être très peu utilisée, uniquement quand un attribut est directement accessible par une autre classe. La définition de la visibilité publique est une notation abrégée utilisée pour la définition de la visibilité de l'attribut comme visibilité protégée, privée ou d'implémentation. Elle est associée à des opérations publiques pour obtenir et définir la valeur de l'attribut. La visibilité publique de l'attribut peut être utilisée comme une déclaration à un générateur de codes, indiquant que ces opérations obtenir/définir doivent être automatiquement générées, pour gagner du temps durant la définition de classe.

La visibilité Protégée doit être la visibilité par défaut ; elle protège l'attribut contre toute utilisation par des classes externes, ce qui favorise le couplage libre et l'encapsulation du comportement.

La visibilité Privée doit être utilisée dans les cas où vous voulez empêcher les sous-classes d'hériter de l'attribut. Cela permet de découpler les sous-classes de la super-classe et d'éviter de supprimer ou d'exclure les attributs hérités non utilisés.

La visibilité Implémentation est la visibilité la plus restrictive ; elle est utilisée dans les cas où seule la classe elle-même peut utiliser l'attribut. C'est une variante de la visibilité privée, qui dans la plupart des cas est appropriée.

Structure interne Haut de la  page

Certaines classes peuvent représenter des abstractions complexes ; elles ont alors une structure complexe. Lors de la modélisation d'une classe, le concepteur souhaitera peut-être représenter ses éléments internes et leurs relations, pour s'assurer que l'implémenteur mettra en oeuvre de façon appropriée les collaborations survenant dans cette classe.

Dans UML 2.0, les classes sont définies comme des ../glossary.htm#structured_class -- This hyperlink in not present in this generated websiteclasses structurées, ayant la capacité d'avoir une structure interne et des ports. Ensuite, les classes peuvent être décomposées en collections d'éléments connectés qui pourront à leur tour être décomposés ultérieurement. Une classe peut être encapsulée, en forçant les communications venant de l'extérieur à passer par des ports respectant les interfaces déclarées.

Ainsi, outre l'utilisation des diagrammes de classes, pour représenter les relations entre classes (par exemple : les associations, les compositions et les agrégations) et les attributs, le concepteur peut utiliser un diagramme de structure composite. Ce diagramme fournit au concepteur un mécanisme montrant comment les instances des parties internes jouent leur rôle, à l'intérieur de l'instance d'une classe donnée.

Pour plus d'informations à ce sujet et pour consulter des exemples de diagramme de structure composite, voir Concepts : Classe structurée.

RUP (Rational Unified Process)   2003.06.15