Un modèle de
conception peut être subdivisé en unités plus petites pour faciliter sa compréhension. En divisant le modèle de
conception en packages et en sous-systèmes, puis en montrant comment ces groupes sont liés les uns aux autres, il est
plus facile de comprendre la structure d'ensemble du modèle. Remarquez qu'un sous-système de conception est modélisé comme un composant qui réalise une
interface ou plus ; pour plus d'informations, voir Produit : Sous-systèmes de conception et Instructions relatives au produit : Sous-systèmes de conception. Les packages de
conception servent uniquement au regroupement.
Une classe contenue dans un package peut être publique ou privée. Une classe
publique peut être associée à une autre classe. Une classe privée
peut uniquement être associée à des classes contenues dans le package.
L'interface d'un package est constituée des classes publiques du package. L'interface package (les classes publiques)
isole et implémente les dépendances sur les autres packages. De cette façon, le développement parallèle est simplifié
car vous pouvez établir les interfaces plus tôt et les développeurs n'ont besoin de connaître que les changements des
interfaces des autres packages.
Vous pouvez segmenter le modèle de conception pour plusieurs raisons :
-
Pour utiliser les packages et les sous-systèmes comme des unités d'organisation, de configuration ou de
distribution lorsqu'un système est terminé.
-
L'allocation des ressources et les compétences des diverses équipes de développement peuvent impliquer la
répartition du projet entre plusieurs groupes se trouvant sur des sites différents. Les sous-systèmes dont
l'interface est bien définie sont un moyen de répartir le travail entre les équipes d'une manière contrôlée et
coordonnée, permettant la réalisation simultanée de la conception et de l'implémentation.
-
Les sous-systèmes peuvent être utilisés pour structurer le modèle de conception de manière à refléter les types
d'utilisateur. Beaucoup des demandes de changements proviennent des utilisateurs ; les sous-systèmes garantissent
alors que les modifications n'affectent que les parties du système correspondant au type d'utilisateur associé à la
modification.
-
Sous certaines applications, une partie des informations ne doit être accessible que pour un groupe restreint de
personnes. Les sous-systèmes permettent de maintenir le secret là où il est requis.
-
Si vous construisez un système de prise en charge, vous pouvez, en utilisant des sous-systèmes et des packages, lui
donner une structure similaire à celle du système qui va être pris en charge. De cette façon, vous pouvez
synchroniser la maintenance des deux systèmes.
-
Les sous-systèmes sont utilisés pour
représenter les produits existants et les services que le système utilise (par exemple les produits COTS et les
bibliothèques), comme l'expliquent les sections suivantes.
Lorsque les classes frontière sont distribuées aux packages, deux stratégies peuvent être appliquées ; il faut choisir
l'une d'entre elles en fonction de la probabilité que les interfaces du système changent beaucoup ou non dans le futur.
-
S'il est probable que l'interface du système soit remplacée ou subisse des changements considérables, elle doit
être séparée du reste du modèle de conception. Lorsque l'interface utilisateur est modifiée, seulement ces packages
sont affectés. Basculer d'une interface en mode ligne à une interface en mode fenêtre est un exemple de changement
majeur.
Si le but premier est de simplifier les changements majeurs de l'interface, les classes frontière doivent être placées
dans un ou plusieurs packages séparés.
-
Si aucune modification majeure n'est prévue, les changements apportés aux services du système devraient être le
principe à suivre, plutôt que les changements apportés à l'interface. Les classes frontière doivent alors être
regroupées avec les classes entité et les classe de contrôle auxquelles elles sont liées fonctionnellement. De
cette façon, il sera facile de voir les classes frontière affectées en cas de modification d'une classe entité ou
d'une classe de contrôle.
Pour simplifier les changements apportés aux services du système, les classes frontière sont regroupées sous la forme
de packages avec les classes auxquelles elles sont liées fonctionnellement.
Les classes frontière obligatoires qui ne sont pas liées fonctionnellement à des classes entité ou des classes de
contrôle doivent être placées dans des packages séparés avec les classes frontière qui appartiennent à la même
interface.
Si une classe frontière est associée à un service optionnel, regroupez-la avec les classes qui fournissent le service
dans un sous-système séparé. Le sous-système se mappera à un composant optionnel qui sera fourni quand la
fonctionnalité optionnelle sera demandé.
Un package doit être défini pour chaque groupe de classes liées fonctionnellement. Il existe plusieurs critères
pratiques pour évaluer si deux classes sont liées fonctionnellement. Ces critères sont décrits ci-dessous, par ordre
décroissant d'importance :
-
Si les modifications dans le comportement et/ou la structure d'une classe implique des changements dans l'autre
classe, les deux classes sont liées fonctionnellement.
Exemple
Si un attribut est ajouté à la classe entité Commande, cela impliquera sûrement une mise à jour de la classe
de contrôle administrateur de commande. Elles appartiennent donc au même package traitement des
commandes.
-
Il est possible de voir si une classe est liée fonctionnellement à une autre en prenant une classe - une classe
entité par exemple - et en observant ce qui se passe si on la retire du système. Toutes les classes qui deviennent
superflues à cause de cette suppression sont d'une façon ou d'une autre liées à cette classe. Par superflue, on
entend ici que la classe est utilisée seulement par la classe supprimée ou qu'elle dépend d'elle.
Exemple
Il y a un package traitement des commandes qui contient les deux classes de contrôle administrateur de
commande et enregistrement de la commande, dans le système de traitement du dépôt. Ces deux
classes de contrôle modélisent des services concernant le traitement des commandes dans le dépôt. Tous les
attributs et les relations sont conservés dans la classe entité commande, qui n'existe que pour le
traitement des commandes. Si la classe entité est supprimée, l'administrateur de commande et
l'enregistrement de la commande deviennent inutiles, car ils ne sont nécessaires que s'il y a une
commande. La classe entité commande doit donc être inclus dans le même package que les deux classes
de contrôle.
L'administrateur de commande et l'enregistrement de la commande appartiennent au même paquet que la
commande, parce qu'ils deviennent inutiles si la commande est supprimée du système.
-
Deux objets peuvent être fonctionnellement liées s'ils interagissent avec un grand nombre de messages ou s'ils ont
une intercommunication complexe.
Exemple
La classe de contrôle exécuteur de tâche envoie et reçoit des messages de la part de l'interface
transporteur. Cela indique aussi qu'ils devraient être inclus dans le même package traitement de la
tâche.
-
Une classe frontière peut être fonctionnellement liée à une classe entité particulière si la fonction de la classe
frontière est de présenter la classe entité.
Exemple
La classe frontière forme de la palette, dans le système de traitement du dépôt, présente à
l'utilisateur une instance de la classe palette. Chaque palette est représentée par un numéro
d'identification sur l'écran. Si les informations sur la palette changent, par exemple si on attribue un nom
à la palette, la classe frontière peut être, elle aussi, obligée de changer. La forme de la palette
devrait donc être dans le même package que la palette.
-
Deux classes peuvent être liées fonctionnellement si elles interagissent avec, ou si elles sont affectées par les
changements d'un même acteur. Si deux classes n'impliquent pas le même acteur, elles ne devraient pas être dans le
même package. Cette dernière règle peut, bien sûr, être ignorée pour des raisons plus importantes.
Exemple
Il y a un package traitement de la tâche dans le système de traitement du dépôt, qui inclut, entre
autres, la classe de contrôle exécuteur de tâche. C'est le seul package lié à l'acteur transporteur,
le transporteur physique qui peut transporter une palette dans le dépôt. L'acteur interagit avec la classe de
contrôle exécuteur de tâche par la classe frontière interface du transporteur. Cette classe frontière
devrait donc être incluse dans le package traitement de la tâche.
L'interface transporteur et l'exécuteur de tâche appartiennent au même package car ils sont tous deux
affectés par les changement de l'acteur transporteur.
-
Deux classes peuvent être liées fonctionnellement s'il existe des relations entres elles (associations, agrégations
etc.) Bien sûr, on ne peut se fier à ce critère les yeux fermés, mais il peut être utilisé quand aucun autre
critère n'est applicable.
-
Une classe peut être fonctionnellement liée à la classe qui crée ses instances.
Les deux critères suivants déterminent quand deux classes ne doivent pas être placées dans le même package :
-
Deux classes liées à des acteurs différents ne devraient pas être placées dans le même package.
-
Une classe optionnelle et une classe obligatoire ne devraient pas être placées dans le même package.
Tout d'abord, les éléments d'un même package doivent tous avoir la même "optionalité" : il ne peut y avoir de modèle
optionnel dans un package obligatoire.
Exemple
La classe entité obligatoire type d'article a, entre autres choses, un attribut appelé rassortir les
contraintes. La fonction "rassortir"est cependant optionnelle pour le système. Article devrait donc être
divisé en deux classes entité où la classe optionnelle se rapporte à la classe obligatoire.
Un package obligatoire ne doit pas dépendre d'un package optionnel.
Il est établit qu'un package ne peut pas être utilisé par deux acteurs différents. Un changement dans le comportement
d'un acteur ne devrait pas, en effet, affecter les autres acteurs. Il existe des exceptions à cette règle, comme pour
les packages qui constituent les services optionnels. Les packages de ce type ne doivent pas être divisés, quel que
soit le nombre d'acteurs qui les utilisent. Il faut donc diviser toutes les classes et tous les packages utilisés par
plusieurs acteurs, à moins que le package soit optionnel.
Toutes les classes d'un même package doivent être liées fonctionnellement. Si vous avez suivi les critères de la
section "Etablir les packages des classes liées fonctionnellement", les classes d'un package seront liées entre elles
fonctionnellement. Toutefois, une classe peut contenir "trop" de comportements ou de relations ne lui appartenant pas.
Une partie de la classe devrait alors être "enlevée" pour devenir une nouvelle classe ou être ajoutée à une autre
classe, qui appartiendra sûrement à un autre package.
Exemple
Le comportement d'une classe de contrôle A se trouvant dans un package, ne doit pas trop dépendre d'une classe
B, d'un autre package. Pour isoler le comportement spécifique de B, la classe de contrôle A doit
être divisée en deux classes de contrôle, A' et A". Le comportement spécifique de B est placé dans
la nouvelle classe de contrôle A", qui est elle-même placée dans la même package que B. La nouvelle
classe A" se voit attribuer une relation avec l'objet original A', comme la généralisation.
Pour isoler le comportement spécifique de B, la classe de contrôle A, qui manque d'homogénéité, est
divisée en deux classes de contrôle, A' et A''.
Si une classe d'un package et associée à une classe d'un autre package, alors ces packages dépendent l'un de l'autre.
Les dépendances des packages sont modélisées en utilisant une relation de dépendance entre les packages. Les relations
de dépendance nous aident à évaluer les conséquences des changements : un package duquel beaucoup de packages dépendent
est plus difficile à modifier qu'un package dont aucun package ne dépend.
Beaucoup de ces dépendances seront découvertes pendant la spécification des packages, elles sont donc amenées à changer
pendant le travail. La description d'une relation de dépendance peut inclure des informations concernant les relations
de classe ayant causé cette dépendance. Il est difficile de tenir ces informations à jour. Cela ne devrait donc être
fait que si les informations sont pertinentes et intéressantes.
Exemple
Dans le système de traitement du dépôt il existe une relation de dépendance entre le package traitement de la
commande et le package traitement de l'article. Cette association a été créée car la classe entité
commande dans le traitement de la commande a une association avec la classe entité type d'article
dans l'autre package.
Le package traitement de la commande dépend du traitement de l'article, car il existe une association
entre deux classes des packages.
Le couplage de packages est à la fois bon et mauvais : il est bon car il implique une réutilisation mais il est mauvais
car les dépendances qu'il entraîne rendent le système plus difficile à modifier et à faire évoluer. Certains principes
généraux peuvent être suivis :
-
Les packages ne devraient pas être couplés transversalement (c'est à dire co-dépendants): par exemple, deux
packages ne devraient pas dépendre l'un de l'autre.
Lorsque cela se produit, les packages doivent être réorganisés pour supprimer les couplages transversaux.
-
Les packages des couches inférieures ne doivent pas dépendre des packages des couches supérieures. Les packages ne
doivent dépendre que des packages appartenant à la même couche ou à la couche juste inférieure.
Lorsque cela se produit, la fonctionnalité doit être à nouveau segmentée. Une solution est de définir les
dépendances en terme d'interfaces et de les organiser dans la couche inférieure.
-
En général, les dépendances ne devraient pas sauter de couches, à moins que le comportement de dépendance ne soit
commun à toutes les couches. La solution est de simplement faire transiter les appels d'opération entre les
couches.
-
Les packages ne doivent pas dépendre des sous-systèmes. Ils ne doivent dépendre que d'autres packages ou
d'interfaces.
|