A N A L Y S E, C O N C E P T I O N, E T P R O G R A MMATION O R I E N T E E O B J E T RAPPORT DE PROJET LOGICIEL DE GESTION DE COMPAGNIE DE TRANSPORT MARITIME CE LI NE HE NRY CO MB ES P IERRE LUCE L3 IN FOR MA TI QUE D EC EMBR E 2010 I.
RESUME Ce document présente les points clés du développement d un logiciel à l aide des technologies «orientée objet». A travers un projet de travaux pratique servant de support, nous présenterons les phases d analyse et de conception utilisant le langage UML pour modéliser le métier et concevoir une solution répondant aux spécifications, et nous verrons aussi son implémentation grâce au langage C++. A chaque choix que nous avons dû effectuer où plusieurs solutions s offraient à nous, nous les justifions et développons nos raisons.
INTRODUCTION Au premier semestre de la Licence 3 d Informatique à l Université de Limoges, nous avons eu a réalisé un logiciel de gestion pour une compagnie de transport maritime. Il s agissait d effectuer l analyse d un cahier des charges, de concevoir une solution et de l implémenter pour obtenir un programme fonctionnel, dans le cadre du cours d Analyse et Programmation Orientée Objet. Fort de notre apprentissage des langages UML et C++, nous les avons utilisé respectivement pour la modélisation et pour l implémentation. Dans un premier temps, nous vous présenterons l analyse effectuée et le modèle conçu pour le logiciel, tandis que dans une deuxième partie, nous aborderons les choix architecturaux et l implémentation retenue.
TABLE DES MATIERES Résumé... 2 Introduction... 3 PREMIERE PARTIE : ANALYSE ET CONCEPTION DU LOGICIEL 5 I. Analyse du Cahier des Charges... 5 II. Modélisation et Conception... 6 Gestion des passagers... 6 Gestion des Navires... 6 Gestion des trajets... 7 Gestion des membres d equipages... 8 Conclusion... 8 SECONDE PARTIE : ARCHITECTURE ET IMPLEMENTATION 10 I. Le modèle MVC... 10 II. Une première implémentation de la vue : la console... 12 III. La vue définitive et la bibliothèque Qt4... 12 Construction de l interface... 13 Intégration des interfaces... 13 IV. Design Patterns utilisés... 14
PREMIERE PARTIE : ANALYSE ET CONCEPTION DU LOGICIEL I. ANALYSE DU CAHIER DES CHARGES Le cahier des charges fournit comme consigne au projet est relativement précis sur la description du modèle métier de l entreprise. Les fonctionnalités attendues sont plus vagues, mais la plupart découlent directement du modèle et sont implicites. Les opérations particulières sont explicitées et clairement exprimées. Il s agit donc de gérer les opérations de type «CRUD» (Create, Retrieve, Update, Delete) sur un certain nombre d objets métiers : les navires, les trajets, les passagers, les membres d équipage Ainsi que de permettre l achat des billets, l affectation des équipages, l édition de plusieurs documents. Voici, présenté sous forme d un diagramme de cas d utilisation, l ensemble des fonctionnalités attendue : FIGURE 1: DIAGRAMME DE CAS D'UTILISATION
II. MODELISATION ET CONCEPTION Il s agissait dans un premier temps de comprendre la définition et l interaction des différents objets métiers de la compagnie maritime. Une lecture du sujet nous a rapidement permis de les trouver, et de les organiser sur un diagramme de classe. Néanmoins, la conception la plus sémantiquement correcte n est pas nécessairement la plus fonctionnelle, ni la plus pratique à l implémentation comme à l utilisation. Nous vous présentons ici notre diagramme de classe finale en plusieurs parties pour plus de clarté. GESTION DES PASSAGERS FIGURE 2: DIAGRAMME DE CLASSE DE LA GESTION DES PASSAGERS L organisation ci-dessus est presque triviale à la lecture du sujet, mise à part dans la partie concernant la gestion des différentes catégories de passagers. Nous avions dans un premier temps choisi de créer une classe par catégorie de passagers, héritant de la classe «Passager» et porteuse de l information tarifaire. Néanmoins, cette solution manque de flexibilité : il est impossible d ajouter de nouvelles catégories ou de changer les tarifs sans modifier le code, et cette opération est loin d être improbable. Nous avons donc choisi de déléguer l information de tarif à une classe spécialisée CategoriePassager, dont une instance est conservée pour chaque Passager. GESTION DES NAVIRES FIGURE 3: DIAGRAMME DE CLASSE DE LA GESTION DES NAVIRES
Ici il peut paraitre surprenant de ne pas utiliser d héritage pour différencier les navires de fret des navires mixtes. Effectivement, il y a peu de chance qu un nouveau type de navire apparaisse. Néanmoins, l absence d héritage se justifie par un autre problème : la persistance des données. Elle est en effet rendue plus difficile en présence d un arbre d héritage, même simple. L utilisation d une base de donnée impliquera par exemple la nécessité de passer par un ORM (Object Relational Mapping) suffisamment évolué pour gérer ces cas. Nous avons donc fait le choix de conserver l information de type dans une chaine de caractère, et de condenser les informations particulières aux navires mixtes dans une seule classe Navire. GESTION DES TRAJETS FIGURE 4: DIAGRAMME DE CLASSE POUR LA GESTION DES TRAJETS Cette partie de la conception peut se diviser en deux groupes : - Le «squelette» : constitué des classes Port, TypeTrajet, et TypeTraverse, il modélise une traversée «type», un modèle, sur lequel sera basé le deuxième groupe de classe - Le «réel» : les classes Trajet et Traverse représente les traversée concrète. Ainsi, la traversé du Samedi 11 décembre entre Sein et Ouessant en passant par Molène, partant à 8h34, serait représenté par le diagramme d objet suivant :
FIGURE 5 : DIAGRAMME D'OBJETS REPRESENTANT UNE TRAVERSEE On peut donc, en partant d une traversée donnée, retrouver toutes les informations nécessaires, et on peut facilement, à partir d un type de traversée, créer une nouvelle traversée concrète. GESTION DES MEMBRES D EQUIPAGES FIGURE 6 : DIAGRAMME DE CLASSES POUR LA GESTION DES MEMBRES D'EQUIPAGE Il a été décidé ici de ne pas faire d héritage non plus, encore une fois pour faciliter la persistance. Nous aurions pu faire une sous-classe «officier» pour les capitaines et seconds, mais nous avons préféré donner un «rôle» au membre d équipage. Cela permettrait en outre de pouvoir préciser, si besoin dans le futur, s il est mécanicien, navigateur, etc CONCLUSION Nous avons donc retenu un modèle simple, sans pour autant renier les apports de la conception objet. En effet, l utilisation de l héritage dans le seul but de factoriser les attributs est, à notre sens, une «fausse bonne idée», qui rend plus difficile la persistance. En revanche, son utilisation pour du polymorphisme est à privilégier.
FIGURE 7 : DIAGRAMME DE CLASSE COMPLET
SECONDE PARTIE : ARCHITECTURE ET IMPLEMENTATION I. LE MODELE MVC Afin de faciliter le travail en équipe et la répartition des tâches, ainsi que les évolutions futures du logiciel, nous avons opté pour une architecture dite «Modèle Vue Contrôleur». Cette façon de structurer un programme sépare en trois couches distinctes le «modèle», ensemble des classes décrivant les objets métiers, la «vue», c est à dire l interface d utilisation, et les «contrôleurs», qui sont les classes liant la vue aux modèles en réalisant des opérations métiers et en renvoyant le résultat. Ainsi un changement de «vue» n implique aucun changement dans le code. FIGURE 8 : DIAGRAMME DE SEQUENCE REPRESENTANT UNE OPERATION THEORIQUE DANS UNE ARCHITECTURE MVC Notre code source se divise donc en trois types de classes, réparties dans trois répertoires : src/vue, src/controleur et src/modele, dont les noms sont explicites. Voici le diagramme de composant décrivant les relations physiques entre les fichiers de définition et d implémentation des classes.
FIGURE 9 DIAGRAMME DE COMPOSANTS
II. UNE PREMIERE IMPLEMENTATION DE LA VUE : LA CONSOLE Lors de la réalisation d un prototype, le plus rapide moyen d obtenir une interaction avec l utilisateur est d utiliser la console en ligne de commande fournie avec tous les systèmes d exploitation. Facilement manipulable de base avec C++, elle n offre néanmoins que des possibilités ergonomiques limitées. La création des différentes vues étant une tâche assez répétitive, nous avons cherché à accélérer le processus en factorisant une partie des opérations. En effet, tous les menus auront un comportement commun : 1. Ils affichent une liste d options 2. Demandent et enregistrent une saisie utilisateur 3. Exécutent l option choisie Nous avons donc mis à profit les avantages de la conception orientée objet et notamment du polymorphisme, en mettant en place l architecture suivante : La classe TemplateVue est abstraite et expose deux méthodes : rendu() qui affiche les différentes options du menu, et choix() qui effectue la saisie de l utilisateur et exécute le traitement associé. Les options sont ajoutées dans le constructeur de la classe concrete grâce à la méthode ajouteroption(string). La correspondance option-traitement se fait dans la méthode traitersaisie(int) qui doit donc être redéfinie, par exemple sous forme d un switch/case. Il est donc possible de créer rapidement de nouveaux menus, de FIGURE 10 : SYSTEME DES VUES nouvelles «pages» dans le logiciel. Les différentes méthodes étant définie virtual, elles sont surchargeables dans les classes héritant de TemplateVue, offrant ainsi la possibilité de personnaliser l affichage des menus. Ainsi, un prototype est rapidement réalisé pour permettre le test des couches inférieures et de la logique métier. III. LA VUE DEFINITIVE ET LA BIBLIOTHEQUE QT4 L ergonomie proposée par une interface en ligne de commande étant limitée, nous avons ressenti le besoin de fournir à l utilisateur une expérience plus agréable. Tout programme digne de ce nom ayant pour cible des non-informaticiens possède donc depuis maintenant 30 ans une interface graphique utilisateur (GUI), le plus souvent sous
la forme de fenêtre manipulable, possédant des tableaux et des champs de formulaire, interagissant grâce au clavier et à la souris. La réalisation de ces interfaces pouvant être longue et fastidieuse, nous avons choisis d utiliser une bibliothèque spécialisée : Qt 4. Open-source et multiplateformes, elle dispose d une importante documentation, d une large communauté de programmeurs et de précieux outils de développement. Les librairies qu elle propose ne concernent pas uniquement l interface graphique, mais propose aussi des classes représentant des données (Date, heure ) plus complètes que les standards (quand elles existent). CONSTRUCTION DE L INTERFACE L outil QtDesigner livré avec la bibliothèque propose la conception d interfaces graphique à l aide d un éditeur «WYSIWYG» (What You See Is What You Get : ce que tu vois est ce que tu obtiendras) très pratique, permettant la construction de fenêtres complexes en relativement peu de temps. Ce logiciel fonctionne sur un principe simple de «glisser-déposer» d éléments, d une table de propriété pour chacun des objets composant l interface (boutons, tables ) et dispose de beaucoup d exemples. Il est possible d éditer aussi de façon sommaire la gestion des événements : elle se fait sous Qt grâce à l association de signaux émis par un élément, et de slots, méthode d un objet recevant le signal. Par exemple, le signal clicked() de l objet ajouternavirebutton sera associé à la méthode traiterajoutnavire() de la fenêtre courante grâce au code : connect(ajouternavirebutton,signal(clicked()),this,slot(traiterajoutnavire())); Ce code peut être partiellement généré par QtDesigner. Ainsi, plus de temps est passé sur l implémentation des fonctionnalités métiers plutôt que sur un travail technique fastidieux. INTEGRATION DES INTERFACES QtDesigner génère au final un fichier *.ui, lequel sera transformé à la compilation en un banal fichier C++ *.h, qui définira la classe représentant la fenêtre que l on a créé. Si l on souhaite modifier le comportement de la fenêtre (en ajoutant des évènements par exemple), on doit alors créer une sous-classe en héritant, et appeler celle-ci dans notre programme. La principale difficulté réside dans la compilation, qui passe par une étape intermédiaire : il est nécessaire de construire le fichier makefile avec l utilitaire qmake fourni avec la bibliothèque. La compilation se déroule donc en trois étapes : 1. qmake project (écrit un fichier *.pro) 2. qmake (écrit le fichier makefile d après le *.pro, et compile les *.ui en *.h)
3. make (compile) IV. DESIGN PATTERNS UTILISES Le pattern le plus utilisé est ici le Singleton, c est-à-dire le patron de conception qui permet de s assurer de l unicité de l instance d une classe à travers tout le programme. Il s agit, sommairement, de déléguer la construction d un objet à une méthode statique délivrant toujours la même instance. Il est utilisé principalement pour deux types de classes : - Les contrôleurs : une seule instance suffit, et est même nécessaire s ils gèrent le stockage des données métiers. - Les fenêtres : ainsi, les modifications entrainées sur une fenêtre sont répercutées en même temps sur les autres fenêtres de la même classe. De plus, le gain mémoire est intéressant si on utilise des objets de grande taille ne nécessitant pas d être présent en plusieurs exemplaires.
CONCLUSION Ce travail d analyse puis de programmation a été une bonne expérience pour plusieurs raisons. Tout d abord, ce fut l occasion de mettre en application une fois de plus les méthodes d analyse orientée objet, dans le cadre d un sujet complet et proche de la réalité. Ensuite, l implémentation en C++ nous a permis d approfondir notre connaissance de ce langage, et notamment de nous initier à la création d interface graphique, dont nous avions déjà l expérience en Java. Enfin, tout exercice donne l occasion d améliorer ses bonnes pratiques, et ce fut là aussi le cas.