TD 0 : Quelques rappels

Avant de démarrer les TDs concernant la conception avancée et la programmation il nous faut vous faire quelques rappels essentiels.


Les objectifs de ce TD :

  • Rappeler les notions vues au semestre précédent
  • Rappeler les termes et les notions importantes de chaque diagramme

L'UML, acronyme pour Unified Modeling Language qu'on peut traduire par Langage de Modélisation Objet Unifié, est un outil universel qui permet de structurer un projet et de le matérialiser graphiquement sous forme de diagrammes compréhensibles par les non informaticiens. Aucune connaissance de langage informatique n'est prérequise. Cette modélisation permet dans un second temps de développer le code informatique, le plus souvent à l'aide d'un langage orienté objet (C++, Java par exemple). La description de projets en UML est une étape nécessaire qui permet de gagner beaucoup de temps dans le développement d'une application car la mise au point du code en est moins fastidieuse et le risque d'erreurs de conception ou de réalisation est plus limité. Bien que conçue pour la gestion de projets de grande envergure, l'utilisation de cette méthodologie est bénéfique même pour les projets les plus modestes.

Vous l’aurez compris il s’agit de ce langage que l’on utilise pour réaliser correctement notre Analyse et notre Conception d’un problème donné.

Revoyons donc quelques diagrammes utiles issus de langage !

Le diagramme de cas d'utilisation représente la structure des grandes fonctionnalités nécessaires aux utilisateurs du système. C'est le premier diagramme du modèle UML, celui où s'assure la relation entre l'utilisateur et les objets que le système met en œuvre.

Bien souvent, la maîtrise d'ouvrage et les utilisateurs ne sont pas des informaticiens. Il leur faut donc un moyen simple d'exprimer leurs besoins. C'est précisément le rôle des diagrammes de cas d'utilisation qui permettent de recueillir, d'analyser et d'organiser les besoins, et de recenser les grandes fonctionnalités d'un système. Il s'agit donc de la première étape UML d'analyse d'un système.

Un diagramme de cas d'utilisation capture le comportement d'un système tel qu'un utilisateur extérieur le voit. Il scinde la fonctionnalité du système en unités cohérentes, les cas d'utilisation, ayant un sens pour les acteurs. Les cas d'utilisation permettent d'exprimer le besoin des utilisateurs d'un système. Ils sont donc une vision orientée utilisateur plutôt qu’une vision informatique.

Il ne faut pas négliger cette première étape pour produire un logiciel conforme aux attentes des utilisateurs. Pour élaborer les cas d'utilisation, il faut se fonder sur des entretiens avec les utilisateurs.

Prenons un exemple simple :



Ce diagramme est composé de plusieurs éléments qui possèdent chacun leurs spécificités et leurs règles.

1.2.1 Les acteurs

UML n'emploie pas le terme d'utilisateur, mais d'acteur. Les acteurs d'un système sont les entités externes à ce système qui interagissent (retirer de l’argent, consulter le solde du compte,…) avec lui.

Les acteurs sont donc à l'extérieur du système et dialoguent avec lui. Ces acteurs permettent de cerner l'interface que le système va devoir offrir à son environnement. Oublier des acteurs ou en identifier de faux conduit donc nécessairement à se tromper sur l'interface et donc la définition du système à produire.

Il faut faire attention à ne pas confondre acteurs et utilisateurs (utilisateur avec le sens de la personne physique qui va appuyer sur un bouton) d'un système. D'une part parce que les acteurs incluent les utilisateurs humains, mais aussi les autres systèmes informatiques ou hardware qui vont communiquer avec le système. D'autre part parce qu'un acteur englobe tout une classe d'utilisateurs. Ainsi, plusieurs utilisateurs peuvent avoir le même rôle, et donc correspondre à un même acteur, et une même personne physique peut jouer des rôles différents vis-à-vis du système, et donc correspondre à plusieurs acteurs.

Chaque acteur doit être nommé. Ce nom doit refléter son rôle, car un acteur représente un ensemble cohérent de rôles joués vis-à-vis du système. Il doit être également mettre au singulier !

Il se représente par un petit bonhomme avec son nom ou son rôle inscrit dessous.



Il est également possible de représenter un acteur sous la forme d’un « classeur » dans le cas où cet acteur externe n’est pas une personne et que l’on souhaite le différencier des autres acteurs (téléphone, réseau social,…).



Lorsque l’on définit un acteur il est fortement conseillé de lui ajouter une brève description textuelle mais dans les cas où le nom/rôle de l’acteur est explicite ce n’est pas la peine.



Comment trouver les acteurs du système ?

Pour trouver les acteurs d'un système, il faut identifier quels sont les différents rôles que vont devoir jouer ses utilisateurs (ex. : responsable clientèle, responsable d'agence, administrateur,…). Il faut également s'intéresser aux autres systèmes avec lesquels le système va devoir communiquer comme :
- Les périphériques manipulés par le système (imprimantes, hardware d'un distributeur de billets…) ;
- Des logiciels déjà disponibles à intégrer dans le projet ;
- Des systèmes informatiques externes au système, mais qui interagissent avec lui.

Pour faciliter la recherche des acteurs, on peut imaginer les frontières du système. Tout ce qui est à l'extérieur et qui interagit avec le système est un acteur, tout ce qui est à l'intérieur est une fonctionnalité à réaliser.

Vérifiez que les acteurs communiquent bien directement avec le système par émission ou réception de messages. Une erreur fréquente consiste à répertorier en tant qu'acteur des entités externes qui n'interagissent pas directement avec le système, mais uniquement par le biais d'un des véritables acteurs. Par exemple, l'hôtesse de caisse d'un magasin de grande distribution est un acteur pour la caisse enregistreuse, par contre, les clients du magasin ne correspondent pas à un acteur, car ils n'interagissent pas directement avec la caisse.

Pour trouver les acteurs on peut se poser les questions suivantes :
- Qui ou quoi utilise le système ?
- Qui ou quoi obtient de l’information de ce système ?
- Qui ou quoi fournit des informations au système ?
- Où dans la compagnie le système est-il utilisé ?
- Qui ou quoi supporte et maintient le système ?
- Quels autres systèmes utilisent ce système ?

1.2.2 Le système

Le système est l’entité avec laquelle les acteurs vont interagir. C’est l’entité qu’on cherche à décrire, modéliser avec le diagramme de cas d’utilisation et que l’on chercher à coder à l’issu de la phase UML.

En UML on le représente à l’aide d’un simple cadre. Le nom du système figure à l’intérieur du cadre, en haut.



Ainsi les acteurs de ce système se situeront autour de ce système et non pas à l’intérieur car cela sous-entendrai qu’ils font partie du système !



A noter que par convention les acteurs représentant des personnes, les bonhommes, sont plutôt placés à gauche du système tandis que les autres acteurs qui ne sont pas des personnes (représentés donc par des classeurs) sont plutôt placés à la droite du système.



1.2.3 Les cas d'utilisation (use case)

   1.2.3.1 Définition
Un cas d'utilisation est une unité cohérente représentant une fonctionnalité visible de l'extérieur. Il réalise un service de bout en bout, avec un déclenchement, un déroulement et une fin, pour l'acteur qui l'initie. Un cas d'utilisation modélise donc un service rendu par le système, sans imposer le mode de réalisation de ce service.

Dis de manière plus simple il s’agit d’une action que réalise un acteur en utilisant le système.

Un cas d'utilisation se représente par une ellipse contenant l’action réalisée par l’acteur. L’action doit être sous la forme d’un verbe à l’infinitif suivi d’un complément. Le complément doit être unique, intuitif et auto-explicatif. Le gain des résultats observables doit être défini clairement et sans ambiguïté.



Par extension un cas d’utilisation sera toujours relier à un acteur, à l’acteur qui réalise l’action du cas d’utilisation…



Comme l’ensemble des cas d’utilisation sont réalisées « à travers » le système, tous les cas d’utilisation doivent être regroupés dans le système, dans le cadre.



Pour reprendre le 1er exemple donné on a bien notre système intitulé « Borne de retrait interactive », notre acteur externe au système, le Client et enfin nos deux cas d’utilisation c’est-à-dire les deux actions que peut réaliser le Client « à travers » la Borne :
- Retirer de l’argent ;
- Consulter le solde du compte.
Comme ces deux actions, ces deux cas d’utilisation sont propres à notre système ils sont bien regroupés dans le système.

   1.2.3.2. Comment trouver un cas d’utilisation ?
L'ensemble des cas d'utilisation doit décrire exhaustivement les exigences fonctionnelles du système.

Chaque cas d'utilisation correspond donc à une « fonction métier » du système, selon le point de vue d'un de ses acteurs. Aussi, pour identifier les cas d'utilisation, il faut se placer du point de vue de chaque acteur et déterminer comment et surtout pourquoi il se sert du système c’est-à-dire que cherche à faire l’acteur avec le système ? Par exemple, un distributeur de billets aura probablement un cas d'utilisation Retirer de l'argent et non pas Distribuer de l'argent.

Il faut éviter les redondances et limiter le nombre de cas en se situant à un bon niveau d'abstraction. Trouver le bon niveau de détail pour les cas d'utilisation est un problème difficile qui nécessite de l'expérience.

De par la nature fonctionnelle, et non objet, des cas d'utilisation, et en raison de la difficulté de trouver le bon niveau de détail, il faut être très vigilant pour ne pas retomber dans une décomposition fonctionnelle descendante hiérarchique. Un nombre trop important de cas d'utilisation est en général le symptôme de ce type d'erreur.

Dans tous les cas, il faut bien garder à l'esprit qu'il n'y a pas de notion temporelle dans un diagramme de cas d'utilisation.

1.2.4 Le glossaire

Comme pour les acteurs il peut arriver que certains cas d’utilisation nécessitent une petite description pour être compréhensible par tous. Plus précisément il s’agit de certains mots constitutifs du cas d’utilisation qui nécessitent qu’on leur donne une définition.

La réalisation d’un logiciel ne se fait pas en un claquement de doigt, il faut du temps car plusieurs étapes sont nécessaires pour son élaboration. Ainsi plusieurs personnes vont travailler sur ce logiciel et ce à différents niveaux. Il est donc important qu’à tout moment de la conception du logiciel ses concepteurs puissent comprendre toutes les exigences demandées par l’utilisateur lors de l’élaboration du cahier des charges. Ainsi si certains termes sont ambigus ou peuvent avoir plusieurs sens cela peut mener à un problème de conception. Cela peut notamment être le cas lors de la définition des cas d’utilisation : on constitue des phrases ambiguës et celui qui nous lira après ne comprendra pas ce que l’on a voulu dire.

Pour pallier à cela on crée un glossaire !

Un glossaire peut être vu comme un dictionnaire puisqu’on va y définir les termes qui peuvent poser un problème de compréhension. Ainsi ce glossaire constituera le point d’entrée et le référentiel initial de l’application, du système que l’on cherche à créer et permettra d’éviter les confusions.

Par conséquent si, lors de la définition d’un cas d’utilisation, on pense qu’un mot ou un terme peut porter à confusion il faudra l’ajouter dans le glossaire et lui donner une définition complète. Le glossaire constitue un outil de dialogue indispensable !

1.2.5 Description textuelle des cas d'utilisation

Le diagramme de cas d'utilisation décrit les grandes fonctions d'un système du point de vue des acteurs, mais n'expose pas de façon détaillée le dialogue entre les acteurs et les cas d'utilisation. Bien que de nombreux diagrammes d'UML permettent de décrire un cas, il est recommandé de rédiger une description textuelle, car c'est une forme souple qui convient dans bien des situations.

Comme un cas d’utilisation représente une action que peut réaliser un acteur avec le système ces descriptions textuelles permettront de mieux comprendre comment ces cas d’utilisation sont mis en œuvre. Autrement dit cela permettra de décrire tout ce qui va se passer quand l’acteur réalisera ce cas d’utilisation.

Une description textuelle contient toujours une séquence nominale qui décrit le déroulement normal du cas (tout fonctionne bien).

À la séquence nominale s'ajoutent fréquemment des séquences alternatives (des embranchements dans la séquence nominale) et des séquences d'exceptions (qui interviennent quand une erreur se produit). Ces séquences peuvent aussi porter le nom de « flot » : flot nominal, flot alternatif, flot d’erreur. Ces flots, qui forment des scénarii, peuvent être entourés par deux éléments supplémentaires : les préconditions et les post conditions.

Les préconditions : Elles décrivent dans quel état doit être le système (l'application) avant pour que ce cas d'utilisation puisse être déclenché. Attention néanmoins à ne jamais faire référence à d’autres cas d’utilisation.

Des scénarii : Ces scénarii sont décrits sous la forme d'échanges d'événements entre l'acteur et le système. On distingue le scénario nominal, qui se déroule quand il n'y a pas d'erreur, des scénarii alternatifs qui sont les variantes du scénario nominal et enfin les scénarii d'exception qui décrivent les cas d'erreurs.

Les post conditions : Elles décrivent l'état du système à l'issue des différents scénarii.

La rédaction des scénarii constitue l’étape la plus important de la description textuelle. En effet, comme nous l’avons dit plus haut, ces scénarii permettront de comprendre le cas d’utilisation de manière très clair puisqu’on envisage toutes les possibilités ou du moins les possibilités essentielles au bon fonctionnement du cas d’utilisation et par conséquent du système.

Néanmoins quelques règles sont à respecter.

Il faut voir les scénarii comme une succession d’action à réaliser c’est-à-dire que pour chaque ligne on lui associe une seule action et surtout un numéro qui s’incrémente de 1 à chaque fois qu’on créé une nouvelle ligne.

Comme les scénarii décrivent ce qui passe entre les acteurs et le système ce sera soit les acteurs soit le système qui sera au cœur de l’action décrite. Par conséquent pour chaque action on devra utiliser la voix active et employer le nom des acteurs tels qu’ils ont été définis lors de l’élaboration des cas d’utilisation. Ex :
Au lieu de dire « Le carnet de bord est réalisé par Alexandre et Rémy » on dira « Alexandre et Rémy réalisent le carnet de bord ». La voix active met en jeu le sujet, c’est le sujet qui fait l’action et par conséquent on utilise principalement le présent de l’indicatif.

Lors de la déclaration de flots alternatifs ou de flots d’erreurs il est important de préciser, en première, de quelle cas alternatifs ou d’erreurs il s’agit. On peut considérer cela comme les préconditions de ces flots puisque cela nous dit dans quelles conditions, dans quel état on doit se trouver pour entrer dans ces flots. Lors de la déclaration de ces « préconditions » il ne faudra pas indiquer le numéro de la ligne mais le numéro de la ligne du flot nominale qui a engendré ces flots. Si l’on souhaite créer plusieurs flot alternatifs/erreurs pour une même ligne du flot nominal il suffit, dans les « préconditions » de ces flots de faire suivre le numéro de la ligne, du flot nominal qui a engendré ces flots, par une lettre qui évoluera plus on créera de flots supplémentaires.

Exemple :
Identification du cas d’utilisation
Préconditions
Flot nominal :
1- Action 1
2- Action 2


Flot alternatif :
1- Flot alternatif de la 1ère ligne
1) Action 1 du flot alternatif 1
2) Action 2 du flot alternatif 1


2- a) 1er flot alternatif de la 2ème ligne
1) Action 1 du flot alternatif 2a
2) Action 2 du flot alternatif 2a
3- b) 2ème flot alternatif de la 2ème ligne
1) Action 1 du flot alternatif 2b
2) Action 2 du flot alternatif 2b


Post-conditions
Exigences non fonctionnelles


Ensuite, pour tous les flots, il est important qu’à chaque fois qu’un acteur demande de faire quelque chose au système, ce dernier lui renvoie une réponse pour savoir si l’action demandée a bien été réalisée ou non.

A noter également que les flots alternatifs se terminent toujours par un retour vers le flot nominal (terme jump to) tandis que les flots d’erreur, sauf contradictions, se finissent par la sortie prématurée du scénario sans retour au flot nominal (terme exit). Dans ce dernier cas on indique quand même l’état dans lequel le système se trouve. On peut considérer cela comme les post-conditions en cas d’erreur en sachant qu’elles peuvent être différentes d’un flot d’erreur à un autre.

Exemple :
Identification du cas d’utilisation
Préconditions
Flot nominal :
1- Action 1
2- Action 2
3- Action 3


Flot alternatif :
1- Flot alternatif de la 1ère ligne
1) Action 1 du flot alternatif 1
2) Action 2 du flot alternatif 1
3) Jump to 3- // A la fin de ce flot alternatif on reviendra à la ligne 3 du flot nominal. On saute la ligne 2 !


Flot d’erreur
2- Flot d’erreur de la 2ème ligne
1) Action 1 du flot d’erreur 2
2) Action 2 du flot d’erreur 2
3) Post-conditions du flot d’erreur 2
4) Exit // On sort du scénario, plus aucune ligne du flot nominal ne sera exécutée


Post-conditions
Exigences non fonctionnelles


On peut voir l’exemple précédent sous la forme schématique suivante :



Là où le diagramme de cas d’utilisation permet de représenter les acteurs d’un système et les actions qu’ils peuvent faire, le diagramme de séquence permet de représenter graphiquement des interactions entre les acteurs et le système selon un ordre chronologique dans le cadre d'un scénario.

Ce scénario est souvent la mise en œuvre d’un cas d’utilisation défini dans le diagramme associé. En effet, maintenant que l’on a notre diagramme de cas d’utilisation il nous faut davantage définir tous les objets ou autres acteurs qui interviennent dans la réalisation de ce cas d’utilisation. On reprend ainsi les acteurs définis dans le diagramme de cas d’utilisation mais on peut aussi en ajouter si ceux-ci sont nécessaires pour la bonne réalisation du scénario.

Les acteurs sont toujours représentés par des petits bonhommes tandis que les objets sont représentés par des rectangles.



Chacun de ces acteurs/objets possède, en-dessous de lui, ce que l’on appelle une ligne de vie qui définit la durée de vie d’un objet c’est-à-dire le moment où il est créé jusqu’au moment où il est détruit. Or pendant cette vie, leur vie, il ne réalise pas forcement quelque chose, ils ne sont pas actifs. Ainsi, pour représenter le moment où ils sont actifs on dessine sur leur ligne de vie des rectangles comme celui qui recouvre entièrement celle de l’acteur car en effet seul l’acteur reste toujours actif pendant toute la durée du scénario.

La dimension verticale du diagramme représente le temps, permettant de visualiser l'enchaînement des actions dans le temps, et de spécifier la naissance et la mort d'objets. Plus on descend, plus on avance dans le temps.

La communication entre acteur/objet, acteur/acteur et objet/objet se fait à l’aide de messages symbolisés par des flèches. Le nom du message est marqué au-dessus de la flèche. De manière générale si l’acteur envoie un message on s’attend à ce qu’une réponse lui soit communiquée même si c’est pour lui dire que l’action s’est bien déroulée.

Comme dans les flots pour les cas d’utilisation il est possible de définir des cas alternatifs ou parallèles. Pour cela on entoure toute la partie alternatives d’un grand rectangle en y inscrivant la mention « alt » en haut à gauche. On peut également rajouter des conditions pour définir quand ces actions peuvent être exécutées.

Le diagramme de classes est considéré comme le plus important de la modélisation orientée objet, il est le seul obligatoire lors d'une telle modélisation.

Alors que le diagramme de cas d'utilisation montre un système du point de vue des acteurs, le diagramme de classes en montre la structure interne. Il permet de fournir une représentation abstraite des objets du système qui vont interagir pour réaliser les cas d'utilisation. Il est important de noter qu'un même objet peut très bien intervenir dans la réalisation de plusieurs cas d'utilisation. Les cas d'utilisation ne réalisent donc pas une partition des classes du diagramme de classes. Un diagramme de classes n'est donc pas adapté (sauf cas particulier) pour détailler, décomposer, ou illustrer la réalisation d'un cas d'utilisation particulier.

Il s'agit d'une vue statique, car on ne tient pas compte du facteur temporel dans le comportement du système. Le diagramme de classes modélise les concepts du domaine d'application ainsi que les concepts internes créés de toutes pièces dans le cadre de l'implémentation d'une application. Chaque langage de Programmation orienté objet donne un moyen spécifique d'implémenter le paradigme objet (pointeurs ou pas, héritage multiple ou pas, etc.), mais le diagramme de classes permet de modéliser les classes du système et leurs relations indépendamment d'un langage de programmation particulier.

Les principaux éléments de cette vue statique sont les classes et leurs relations : association, généralisation et plusieurs types de dépendances, telles que la réalisation et l'utilisation.



Une classe est un classeur. Elle est représentée par un rectangle divisé en trois en trois compartiments. Le premier indique le nom de la classe, le deuxième ses attributs et le troisième ses opérations, méthodes.

1.4.1 Les attributs

Les attributs définissent des informations qu'une classe ou un objet doivent connaître. Ils représentent les données encapsulées dans les objets de cette classe. Chacune de ces informations est définie par un nom, un type de données, une visibilité et peut être initialisée. Le nom de l'attribut doit être unique dans la classe.

1.4.2 Les méthodes

Dans une classe, une opération (même nom et mêmes types de paramètres) doit être unique. Quand le nom d'une opération apparaît plusieurs fois avec des paramètres différents, on dit que l'opération est surchargée. En revanche, il est impossible que deux opérations ne se distinguent que par leur valeur retournée.

1.4.3 Les relations entre classes

Une association est une relation entre deux classes (association binaire) ou plus (association n aire), qui décrit les connexions structurelles entre leurs instances. Une association indique donc qu'il peut y avoir des liens entre des instances des classes associées.

   1.4.3.1. Association binaire
Une association binaire est matérialisée par un trait plein entre les classes associées. Elle peut être ornée d'un nom, avec éventuellement une précision du sens de lecture (▸ ou ◂). Quand les deux extrémités de l'association pointent vers la même classe, l'association est dite réflexive.



Ici par exemple cette association traduit le fait qu’une personne travaille pour 1 entreprise et qu’une entreprise est composée de 1 à n personnes.

   1.4.3.2. Navigabilité
La navigabilité indique s'il est possible de traverser une association. On représente graphiquement la navigabilité par une flèche du côté de la terminaison navigable et on empêche la navigabilité par une croix du côté de la terminaison non navigable. Par défaut, une association est navigable dans les deux sens (association binaire).



Par exemple, la terminaison du côté de la classe Commande n'est pas navigable : cela signifie que les instances de la classe Produit ne stockent pas de liste d'objets du type Commande. Inversement, la terminaison du côté de la classe Produit est navigable : chaque objet commande contient une liste de produits.

   1.4.3.3. Héritage
La généralisation décrit une relation entre une classe générale (classe de base ou classe parent) et une classe spécialisée (sous-classe). La classe spécialisée est intégralement cohérente avec la classe de base, mais comporte des informations supplémentaires (attributs, opérations, associations). Un objet de la classe spécialisée peut être utilisé partout où un objet de la classe de base est autorisé.

Dans le langage UML, ainsi que dans la plupart des langages objet, cette relation de généralisation se traduit par le concept d'héritage. On parle également de relation d'héritage. Ainsi, l'héritage permet la classification des objets.

Le symbole utilisé pour la relation d'héritage ou de généralisation est une flèche avec un trait plein dont la pointe est un triangle fermé désignant le cas le plus général.

Les propriétés principales de l'héritage sont :
  • La classe enfant possède toutes les caractéristiques de ses classes parentes, mais elle ne peut accéder aux caractéristiques privées de cette dernière ;
  • Une classe enfant peut redéfinir (même signature) une ou plusieurs méthodes de la classe parent. Sauf indication contraire, un objet utilise les opérations les plus spécialisées dans la hiérarchie des classes ;
  • Toutes les associations de la classe parent s'appliquent aux classes dérivées.
   1.4.3.4. Attributs issus des associations
Les associations représentent, comme on a pu le voir, une relation entre classes. A ce titre une association entre une classe A et B signifie implicitement qu’on trouvera dans la classe A un attribut de type B. Il faut donc éviter les répétitions !



Ainsi avec cet exemple on aura un attribut de type Produit dans Commande !

Une fois le diagramme de classe terminé, certains logiciels de modélisation permettent de générer directement le code associé comme Visual Paradigm ou bien encore Modelio.

';