POURQUOI CE BLOG, POUR QUI ?


POURQUOI CE BLOG, POUR QUI ?
Ce Blog s'adresse à tous ceux qui sont passionnés par les sciences informatiques , Professionnels,Etudiants,Amateurs ...
Les sujets exposés dans la suite se rapporteront essentiellement sur l'analyse informatique,la programmation,le développement ainsi que à l'architecture IT.
QUI SUIS JE ?
Je suis Kangulungu Lubilanji, Consultant-Freelance sur les technologies .NET,C#,ASP.NET ... Contactez moi pour plus d'informations.

La Programmation OO: Chapitre 10. UML 2

Chapitre 10. UML 2
Ce chapitre est centré sur quelques diagrammes UML 2, les plus important pour la conception et le développement de programmes OO, tels le diagramme de classe, le diagramme de séquence et le diagramme d'états-transitions. Par leur proximité avec le code (malgré leur exposition graphique) et leur côté visuel (vu leur expression graphique), ils constituent un excellent support pédagogique à la pratique de l'OO. Ils sont devenus aujourd'hui incontournables pour la réalisation et la communication d'applications informatiques complexes .

Diagramme UML 2, UML(Unified Modelling Langage) est depuis quelques années, le standard pour la représentation graphique de la succession des phases, de l'analyse à l'installation sur site, que comprend un projet informatique . Les diagrammes UML ont pour mission d'accompagner les développements de ce projet,  en permettant aux personnes impliquées une autre perception, plus globale, plus intuitive, plus malléable, et plus facilement communicable, de ce qu'ils sont en train d'accomplir. UML est le moyen graphique de garantir que « ce qui se conçoit et se programme bien s'énonce clairement ».

UML 2, permet, au moyen de ses 13 diagrammes, de représenter le cahier des charges du projet, les classes et la manière dont elles s'agencent entre elles. Afin d'accompagner le projet tout au long de sa vie, il permet, également, de scruter le programme quand celui-ci s'exécute, soit en suivant les envois de messages, soit en suivant à la trace un objet particulier et ses changements d'états. Il permet finalement, d'organiser le fichier qui constitue le projet, ainsi que de penser leur stockage et leur exécution dans les processeur. Il y a donc un diagramme pour chaque phase du projet. Certains pensent que le graphisme UML est à  ce point puissant qu'il peut servir à la modélisation de n'importe quelle situation complexe (par exemple, le fonctionnement d'un moteur automobile ou des institutions européennes...), que celle-ci se prête ou non, par la suite, à un développement informatique. Je reste sceptique quant à l'exploitation d'UML en dehors du monde informatique.

Représentation graphique standardisée, l'avantage d'une représentation graphique standardisée est que tous les développeurs l'abordent, l'appréhendent et la comprennent d'une seule manière. Une flèche terminée par une pointe particulière, et reliant deux rectangles, signifiera la même chose, précise au niveau code, pour tous les programmeurs, mais sera également compréhensible, en partie, pour les personnes, qui, bien qu'impliquées dans le projet, ne mettront pas directement la main à la pâte logicielle.

Question lisibilité, on conviendra aisément qu'il est beaucoup plus facile de comprendre les interdépendances entre 10 classes lorsque celle-ci sont représentées comme autant de rectangle sur un tableau, un écran ou une page, que de feuilleter un long et pénible listing contenant la définition de ces même classes.

Eu égard à la programmation, UML apparaît, devant la diversité des langages de programmation OO, comme une espèce d'espéranto graphique de ces langages, reprenant tous les mécanismes de base l'OO, même si leur traduction dans ces langages diffère. Cela permet aux personnes impliquées dans le développement logiciel de restreindre de plus en plus leur apport à la seule conceptualisation et analyse, en se libérant des contraintes syntaxiques propres aux langages et en différant de plus en plus les détails techniques liés à l'implémentation. Là où un langage choisit d'implémenter l'héritage par : public (C++), d'autre par : (C#), certains par extends (Java), on en oublie, UML se borne à le traduire par une flèche pointant de la sous-classe vers la superclasse, quoi de plus clair et de plus compréhensible.

UML 2 entre le coup de pouce au tableau noir et un vrai langage de programmation, alors que la plupart des utilisateurs d'UML le voient aujourd'hui comme un complément et une assistance graphique à  l'écriture de code, un grand nombre de ses avocats espèrent le voir évoluer vers un véritable langage de programmation, capable d'universaliser et de chapeauter tous ceux qui existent aujourd'hui. En substance, UML pourrait devenir,  en lieu et place des langages de programmation, ce que ceux-ci devinrent en remplacement à l'assembleur. Les codes seraient purement et simplement produits par une nouvelle génération de compilateur et les diagrammes s'exécuteraient sans programmation additionnelle. L'informatique n'a de cesse de se caractériser par cette succession de montées en abstraction : portes électroniques, circuits booléens, instructions élémentaires, assembleur, langages de programmation, langage de modélisation (UML).

Programmer par cycles courts en superposant les diagrammes, les créateurs, et tout ceux qui font la promotion d'UML en général, accompagnent celle-ci d'une offre en matière méthodologique : RUP (Rational  Unfied Process) ou la programmation dite extrême ou agile. Quelques éléments communs à  ces nouvelles propositions méthodologiques sont les suivants. Il est capital de travailler par cycle court, cycle reprenant la succession des phases classiques des projets informatiques : cahier de charge, analyse, modélisation, développement déploiement, et débouchant systématiquement sur un code exécutable tous les mois ou les deux mois au maximum.
Les informaticiens se sont rendus compte depuis longtemps que leurs clients n'ont pas toujours les idées très claires sur ce qu'ils veulent réellement au départ du projet et sur les possibilités mirobolantes qui leur seront révélées au fur et à mesure de l'avancement des projets.
L'utilisation des diagrammes doit se superposer dans le temps, tous les diagrammes doivent néanmoins pouvoir être repris à tout moment du projet. C'est la raison de cette succession de cycles qui, chacun, voient toutes les phases classiques d'analyse et de développement  se dérouler. Le développement doit montrer une grande flexibilité et capacité d'adaptation (d'ou le terme « agile ») et il faut pouvoir revenir sur des décisions, mêmes prises au tout début de la conception si des problèmes imprévus se produisent en fin de parcours (par exemples des problèmes de temps d'exécution). Il est clair qu'un cycle court aide à cette adaptation, car cela permet tant au client qu'aux développeurs de repérer des problèmes à tout moment, y compris très tôt dans la réalisation.

Diagramme de classe
Une classe, se décrit par ses trois compartiments : noms, attributs et méthodes.

Association entre classe, considérons l'association « dirigée » entre classe 01 et 02
La présence de cette association, ici dans le sens d'01 vers 02 (en l'absence de flèche, l'association serait considérée bi-directionelle ; nous pourrions de plus ajouter un « 1 » sur l'extrémité droite de la flèche car un seul objet 02 est associé à un objet 01), exige que, dans le code de la classe 01, un message soit envoyé vers 02, comme montré dans le code C# ci-après.
 class O1{
        private int unAttribut;
        private int unAutreAttribut;
        private O2 lienO2;
        public O1(O2 lienO2) {
            this.lienO2 = lienO2;
        }

        public void jeTravaillePour01() {
            lienO2.jeTravaillePour02();  /* l'envoie de message */
        }
        public int uneAutreMethode(int a)
        {
            return a;
        }
    }
    class O2
{

        private int unAttribut;
        private int unAutreAttribut;
        public O2() {  }
        public void jeTravaillePour02()
        { }
    }
public class UML 2c{
       public static void Main(){
        O2 unObjet2 = new O2();
        O1 unObjet1 = new (
unObjet2); /* On passe ici le référent de l'objet O2 lors de construction                       

                                                               de l'objet O1 */

        

unObjet1.

jeTravaillePour01();

       }

}


Association entre classes, il y a entre deux classes, dirigée ou non, lorsqu'une des deux classes sert de type à un attribut de l'autre, et que dans le code ce cette dernière apparaît un envoi de message vers la première. Sans cette envoi de message, point n'est besoin d'association. Plus simplement on peut représenter l'association comme un « tube à message » fonctionnant dans un sens ou dans les deux.


Rôle et cardinalité, comme le montre la figure ci-après d'autre information peuvent figurer sur un diagramme de classe UML, afin de caractériser plus finement l'association entre les classes.

Dans cette figure, les relations sont toutes bi-directionnelles. Les « rôles » sont les noms donnés, aux deux pôles de l'association, à la classe qui recevra le message par la classe qui lui envoie. Ainsi, le code des classes O1 et O2 qui est généré à partir de ce diagramme UML pourrait être le suivant, le nom des rôles se substituant  au nom des attributs référents.
class O1{
   O2 lienO2 ;
}
class O2{
  O1 lienO1 ;
}
Une information de type « cardinalité » peut également se trouver aux deux pôles de l'association, signifiant le nombre d'instance de la première classe en interaction avec le nombre d'instance de la seconde. Cette cardinalité peut rester imprécise, comme dans la figure ci-dessus, ou plus précise, par exemple « 1...3 », si l'on considère qu'il n'y aura que de un à trois objets entrant dans une interaction avec un autre. Dans la figure ci-dessus chaque objet O2 sera associé à un certain nombre, non défini ici, d'objet O3(il est possible d'utiliser un diagramme d'objet de manière à préciser la nature des objets repris par cette cardinalité). Le code ci-dessous transformera son référent O3 en un tableau de référent class O2{
  O3[] lesLienO3 ;
  /* ou ArrayList<O3> lesLiensO3 ; */
}
Le tableau s'impose d'emblée si la cardinalité est précise et supérieure à 1. Dans le cas d'une cardinalité laissée imprécise, type 1..*, il est possible, en C#, d'utiliser une liste extensible (par exemple ArrayList) typée par la classe des objets que cette liste contiendra. L'utilisation d'un tableau en général exige de connaître le nombre d'éléments que celui-ci contiendra.

En présence d'une relation à la cardinalité multiple comme ci-dessous ,

 il est possible de préciser ou de désambiguïser cette cardinalité en recourant à un troisième diagramme UML, très rarement utilisé, sinon à cela : le diagramme d'objet, qui s'apparente à une version instancié du diagramme de classe. Rappelons que lors de l'exécution du programme, ce sont les objets qui occupent la mémoire pour s'occuper des traitements. Néanmoins, comme tout ce qu'ils font, y compris les envois de message, est repris dans leur classe, le diagramme de classe suffit le plus souvent à décrire leur comportement. Dans ce diagramme d'objet, en lieu et place de classes, chaque objet apparaîtra, ainsi que le ou les objets avec lesquels il se trouve en interaction.
Finalement, un diagramme de classe peut marquer la différence entre plusieurs référent pointant pourtant vers une même classe, comme illustré ci-dessous en présence de code correspondant
class Musicien {
     Instrument unPremierInstrument ;
     Instrument unDeuxièmeInstrument ;
     /* plutôt que Instrument[] lesInstruments = new Instrument[2] ; */
}
La multiplicité des référents plutôt qu'une même association avec un cardinalité multiple (dans le cas présent une relation 1-2 pourrait sembler faire l'affaire) tient au rôle différent que sont appelés à jouer les deux référents. Ainsi, le premier instrument pourrait être un instrument solo que le musicien utilise pour l'essentiel et le deuxième, un instrument d'accompagnement, nettement moins sollicité. Les messages qui leur sont envoyés seront suffisamment différents  pour qu'ils deviennent nécessaire d'en faire deux attributs séparés. Si une seule association était maintenue, c'est bien évidement un tableau de deux éléments qu'il faudrait utiliser.

Dépendance entre classes, en UML, un lien de dépendance (dans le diagramme de classe, le trait d'association se transforme en un trait en pointillés) entre deux éléments signifie, simplement, que toute modification dans l'un risque d'entraîner une modification de celui qui en dépend. Comme pour une association un envoi de messages entre les deux classes pourra avoir lieu. Cependant, ce lien ne dure que le temps de l'exécution de la méthode, et ne s'apparente plus à une propriété structurelle de la classe appelante. Ce lien de dépendance entre classes est, en conséquence, moins fréquemment rencontré que le lien, permanent et plus effectif, d'association. On retrouve ce lien de dépendance dans le diagramme UML, le diagramme de composant, entre fichier dans lesquels sont stockés des éléments logiciels dépendants. On comprend mieux encore dans le cas des fichiers la nature du lien de dépendance. En effet, lorsque l'on modifie un fichier, il est fréquent qu'il faille modifier tous ceux qui en dépendent. Par l'exemple si l'on modifie le contenu d'une base de données, il faudra également vérifier que tous les programmes qui s'interface avec cette dernière soient toujours valides.

Composition, si l'on transforme un lien d'association entre les deux classes en lien de composition (dit encore d'agrégation forte ou d'agrégation par valeur), et observons-en les conséquences sur le code. Le lien de composition entre deux classes entraîne les instances correspondantes à s'imbriquer l'une dans l'autre dans la mémoire, pile ou tas. La disparition du composite entraînera systématiquement la disparition des composants et la cardinalité ne pourra prendre que la valeur « 1 » du coté composite. Le lien d'agrégation faible, dit simplement d'agrégation, ne se comporte pas, une fois traduit en code, de manière différente au lieu d'association. Dès lors, parler d'agrégation plutôt que d'association revient simplement à particulariser la sémantique de cette relation et à augmenter la fidélité à la réalité qu'elle dépeint. Si les objets sont physiquement imbriqués les uns dans les autres, comme les atomes dans une molécule, on choisira le lien de composition. Sinon, et tant que subsiste malgré tout une situation d'appartenance entre deux objets, on parlera d'agrégation.
Ainsi, on peut dire d'un enfant qu'il est agrégé dans une famille, mais qu'il est simplement associé a son père.
Il aura été, pendant une première période de son existence, un objet « composant » de sa mère (jusqu'au jour où l'enfant naîtra) On ne sera pas surpris d'apprendre qu'une et une seule mère peut porter l'enfant. Les « mères porteuses », c'est un autre chose. 
Pour les adeptes de la bricole informatique, les composants hardware, sont agrégés dans l'ordinateur. Pour les autres ce sont des composants de l'ordinateur qui l'accompagnerons d'office à la poubelle. Lors de l'agrégation, la classe « agrégeante » peut indiquer une multiplicité supérieur à 1, alors que lors d'une composition, la classe « composite » ne peut indiquer qu'une multiplicité inférieure ou égale à 1, pour la simple raison qu'un objet ne peut s'imbriquer physiquement dans deux objets à la fois.

Transformons le diagramme UML précédent en sa nouvelle version, dans laquelle la première association se transforme en composition et la deuxième en agrégation. Et voyons l'effet résultant. De manière à différencier les mécanismes de vie et de mort des objets découlant de ces différents types de relations, dans l'exemple qui suit, la classe O1 sera reliée à la classe O3 par un lien d'agrégation, et à la classe O2 par un lien de composition (le losange est vide pour l'agrégation et plein pour la composition). Attention à l'emplacement du losange du côté de la classe contenante et non contenue.

Composition, bien que le lien d'agrégation et de composition servent à reproduire, tous deux, une relation de type  « un tout et ses parties », le lien de composition rend, de surcroît, l'existence des objets tributaires de l'existence de ceux qui les contiennent. L'implantation de cette relation dans les langages de programmation dépendra de la manière très différente dont les langages de programmation gèrent l'occupation mémoire pendant l'exécution d'un programme.

Classe d'association :

class Performance{
   Musicien unMusicien ;
   Instrument unInstrument ;
}

Classe d'association, dans la figure ci-dessus, la classe Performance est une classe d'association qui fait le lien entre un et un seul musicien et un et un seul instrument, et cela bien qu'un musicien puisse être associé à plusieurs instruments et réciproquement. Elle se rattache par un trait pointillé à la liaison entre le deux classes qu'elle associe. il y aura un objet performance bien particulier pour toute association entre un objet musicien et un objet instruction. Chaque objet de la classe d'association possédera un référent vers un objet particulier de chacune des classes associées, comme dans le code ci-dessus. D'autres classes d'association typique sont l'emprunt d'un livre par un lecteur dans une bibliothèque, la réservation d'un billet de spectacle par un client donné ou l'emploi d'une personne dans un société.

Les paquetages, il est également possible de représenter les paquetages et leur liens de dépendance ou d'imbrication. Un paquetage sera dépendant d'un autre lorsqu'une classe ou un fichier contenu dans le premier s'avère dépendant d'une classe ou d'un fichier contenu dans le deuxième.

Les avantages des diagrammes de classe, l'existence des diagrammes facilite grandement l'interaction entre des personnes impliquées dans un projet, personnes qui peuvent intervenir à différents niveaux de la conception : des décideurs aux programmeurs, et dont le goût pour la programmation peut largement varier.
Ils sont une preuve éclatante que l'orienté objet permet au monde qui nous environne d'être la principale source d'inspiration pour le portrait logiciel que l'on cherche à en tirer. L'OO rapproche la programmation du monde réel et, chemin faisant, l'éloigne des instructions élémentaires des processeurs. Le diagramme de classe ouvre la voie à une programmation complètement automatisée, à partir de la seule élicitation des acteurs du problème et des interactions qu'il entretiennent entre eux. Il est aussi l'ultime étape de cette montée en abstraction qui n'a de cesse de caractériser les développement logiciels.
Finalement , ces diagrammes permettent une appréhension globale du développement , qui est impossible quand seul le code est disponible. Différent solutions architecturales et algorithmiques peuvent être rapidement évaluées, et surtout comparées, grâce aux diagrammes de classe. Ces derniers sont souvent incontournables dans des projets informatiques  de plus en plus lourds et complexes ; utilisés dès le début, ils les accompagnent du long, et peuvent être discutés à différents stades de leur développement, documentés et uniformisés. De part sa composition naturelle en classe,l'OO offre à l'informatique une manière de simplifier ses développements. Les diagrammes de classe accompagnent cette offre, la rendant plus attrayante encore, par son détachement accru de l'écriture logicielle et du fonctionnement intime du processeur.

Un diagramme de classe simple à faire, mais qui décrit une réalité complexe, l'analyse par UML favorise une approche éclatée, classe par classe, au pire une classe se devant de connaître l’interface de quelques autres, l'exécution qui en résulte peut elle, au contraire, impliquer bien plus d'objets, et de manière assez tortueuse. Rien de grave à cela, puisque vous avez laissé la main au seul processeur. Toute la partie compliquée de création, de localisation des objets et de transmission des messages, allant jusqu'au droit de vie et de mort pour chaque objet lui incombe.
On décompose le problème, on le pense acteur par acteur, même si le jeu d'interaction d'acteurs qui s'ensuit se révèle complexe, au point parfois de vous surprendre. La chronologie des messages et des effets de ces derniers n'est jamais attaqué de front. On pense les envois de messages et ce qui conditionne ceux-ci, de manière logique, au cas par cas. S'il y a une succession de messages, c'est que l'ensemble des conditions se trouve vérifiée, mais ce déroulement n'aura jamais fait l'objet d'une étude exhaustive préalable. C'est un peu comme des musiciens d'orchestre qui répéteraient; deux par deux, de manière à apprendre à jouer ensemble. Quand ils se trouvent, tous dans la fosse d'orchestre, pour la première fois, la musique qu'ils produisent individuellement s'harmonise, prend corps. Il ne faut pas programmer les classes comme un tout, en se préoccupent de ce qu'elles peuvent faire pour nous, mais plutôt de les programmer en pensant à ce que celles-ci pourront faire d'elles mêmes et entre elles. C'est la clé de la pratique OO, sans véritable équivalent dans la pratique procédurale.

Diagramme de séquence, ces diagrammes peuvent accompagner le développement d'un projet, à un stade plus avancé que les diagrammes de classes. En effet ces derniers permettent de visualiser le programme lors de son exécution. Quand celui-ci s'exécute en effet, ce sont les objets qui s'agitent, en se sollicitant mutuellement par envoie de messages, et ce sont précisément ces envois de message qui constituent l'essentiel de ces diagrammes. Quand l'objet o1 issu de la classe01, lors de l'exécution de sa méthode jeTravaillePour01(), envoie le message jeTravaillePour02() à l'objet o2 issu de la classe02.

Le temps s'écoule de haut en bas,  la succession aussi. La présence des rectangles ainsi que des numéros de message (1, 1.1...), indiquent la succession et l"emboîtement des appels de méthodes correspondants. Dans le cadre de l’exécution d'un programme fonctionnant uniquement de manière séquentielle, on comprend bien la raison de l'emboîtement des rectangles. Il faut bien que la méthode jeTravaillePour02 termine son exécution afin que la méthode jeTravaillePour01 puisse reprendre la sienne, d'ou le premier rectangle englobant le deuxième et l'addition successive de « . » dans la numérotation des messages.
Ainsi, les flèches qui décochent les messages auront des terminaisons différentes, selon que ces messages sont synchrones (l'expéditeur est bloqué en attendant que le destinataire en ait fini avec sa méthode) ou asynchrones (l'expéditeur et le destinataire peuvent travailler en parallèle). Par défaut, les messages sont considérés comme synchrones, S'exécutant sur processeur unique et sans multithreading. Dans pareil cas, lorsqu'une des instructions d'un corps d'instructions consiste en l'envoi d'un message vers un autre objet, le flot d'instructions du premier objet, expéditeur du message, s'interrompt le temps que le flot d'instructions du deuxième objet, destinataire du message, déclenché par l'envoi de message se termine. Le petit bonhomme dans le diagramme représente le point de départ de la séquence de message. Pour un programme dont on représenterait l'entièreté du diagramme de séquence; le petit bonhomme représenterait le main. Cependant, un diagramme de séquence peut démarrer au départ de n'importe quel appel de méthode.

Diagramme d'états-transitions, certains objets peuvent présenter un  comportement tel pendant l'exécution du code qu'ils méritent une attention toute particuliere. Le diagramme d'états-transitions permet de se concentrer sur les évolutions possible d'un unique objet du code, en termes de changements d'états. La figure ci-dessous aide à comprendre de quoi est fait ce diagramme. Il représente l'objet  « Personne » dans ses différents situations professionnelles. Sont représentés les états et les transitions possibles entre ces états. Certaines transitions sont gardées par des conditions comme le passage à la retraite à plus de 60 ans.
Le disque plein marque la naissance de l'objet; le disque plein dans une circonférence, sa disparition.

1 commentaire:

Selendri a dit…

Bonjour,

Quel logiciel de modélisation, utilisez-vous ?

Cordialement,