Conception Orientée Objet

Slides:



Advertisements
Présentations similaires
La programmation orientée objet avec Java L3-MIAGE Plan
Advertisements

ACTIVE DIRECTORY. Qu'est-ce un service d'annuaire ?: Un service d'annuaire peut être comparé à un agenda téléphonique, celui- ci contient au départ des.
Qualité en Développement Laurent Henocque Enseignant Chercheur ESIL/INFO France
Le struts validator – framework de validation
Algorithmes et structures de données avancés
Conception Orientée Objet Laurent Henocque Enseignant Chercheur ESIL/INFO France
Urbanisation de Systèmes d'Information
UML - Présentation.
C.
Programmation Orientée Objet (POO)
INTRODUCTION.
ESIEE Paris © Denis BUREAU I N Initiation à la programmation avec le langage Java.
Leçon 3 : Héritage IUP 2 Génie Informatique
Introduction à la POO: Les classes vs les objets
1 ARCHITECTURE DACCÈS la méthode générale modèle de données définitions module daccès / modules métiers construction des modèles les modules daccès, les.
Principes de programmation (suite)
Etude des Technologies du Web services
Programmation orientée objet
Principes de la technologie orientée objets
Initiation à la conception de systèmes d'information
Chap 4 Les bases de données et le modèle relationnel
IFT1025, Programmation 2 Jian-Yun Nie
Introduction au paradigme objet Concepts importants surcharge (overload) redéfinition (override) Définition d’une classe Définition des attributs.
© 2007 P. Van Roy. All rights reserved. FSAB1402: Informatique 2 Le Langage Java et les Exceptions Peter Van Roy Département dIngénierie Informatique,
RDF(S)
POO : Objets et classes (Rappels)
Langage Oriente Objet Cours 2.
Structures de données IFT-2000
Structures de données IFT-10541
Introduction au paradigme orienté-objet (suite)
CSI3525: Concepts des Languages de Programmation
Types de données abstrait et mécanismes d'encapsulation
Leçon 1 : notion dobjet IUP Génie Informatique Besançon Méthode et Outils pour la Programmation Françoise Greffier Université de Franche-Comté.
Programmation non procédurale Le projet ECOLE 2000
99 Réutilisation du code grâce à l'héritage. 9-2 Objectifs À la fin de ce cours, vous serez capables de : Définir l'héritage Utiliser l'héritage pour.
Structures de données IFT-2000 Abder Alikacem L’héritage en C++ Département d’informatique et de génie logiciel Édition Septembre 2009.
Patrons de conceptions de créations
1. Représentation des informations
Héritage et composition
Travaux Pratiques Représentation des connaissances
Paradigmes des Langages de Programmation
INTRODUCTION.
Les principes de la modélisation de systèmes
Cours 61 6 La sécurité, Portée, Visibilité Programmer avec sécurité.
La Modélisation Orientée Objet Concevoir un programme : modélisation du problème à résoudre Notion de programme : machine de Turing Pouvoir d’expression.
11/04/ L'héritage Cours 7 Cours 7.
Algorithmique et programmation (1)‏
Programmation objet La base.
Créer des packages.
1 BDs Orientées Objets Witold LITWIN. 2 Pourquoi ? F Les BDs relationnelles ne sont pas adaptées aux applications CAD/CAM, cartes géo... F le problème.
© 2005 P. Van Roy. All rights reserved. FSAB1402: Informatique 2 Le Langage Java Peter Van Roy Département d’Ingénierie Informatique, UCL
Tutorat en bio-informatique
Introduction à la programmation objet en C++
5ième Classe (Mercredi, 19 octobre) Prog CSI2572.
Tutorat en bio-informatique Le 14 novembre Au programme… Les objets –Propriétés (attributs) –Constructeurs –Méthodes.
C++ L’HERITAGE Fayçal BRAÏKI DUT INFORMATIQUE.
PHP objet Jérôme CUTRONA 10:13:27 Programmation Web
François CARCENAC,Frédéric BONIOL ONERA-DTIM Zoubir MAMMERI IRIT
Le polymorphisme.
Les classes Introduction aux Langages Orientés Objets
La programmation par objets Principes et concepts Etude de Smalltalk.
Cours 4 (14 octobre) Héritage. Chapitre III Héritage.
Héritage Conception par Objet et programmation Java
Chapitre 2 Rappels objet et Présentation des diagrammes UML
Campus-Booster ID : Copyright © SUPINFO. All rights reserved La programmation objet, un fondement de la programmation évènementielle.
Introduction à la Programmation Orientée Objet
INTRODUCTION AUX BASES DE DONNEES
Introduction Module 1.
Transcription de la présentation:

Conception Orientée Objet Laurent Henocque http://laurent.henocque.free.fr/ Enseignant Chercheur ESIL/INFO France http://laurent.henocque.perso.esil.univmed.fr/ mis à jour en Octobre 2006

Licence Creative Commons Cette création est mise à disposition selon le Contrat Paternité-Partage des Conditions Initiales à l'Identique 2.0 France disponible en ligne http://creativecommons.org/licenses/by-sa/2.0/fr/ ou par courrier postal à Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.

Objectifs Donner une compréhension des enjeux de la conception orientée objet, et des connaissances actuelles sur le sujet

Plan Panorama du concept d'objet en Informatique Principes généraux de détermination des classes Principes de l'utilisation des objets A propos de réutilisabilité Conception des interfaces de programmation en C++ Types de classes

Panorama du concept d'objet

Un modèle de la réalité les mêmes réactions que la réalité représentée, la même modularité que le monde réel.

Modèle de la réalité (2) Chaque objet se comporte "comme" son homologue réel en termes de : persistance de son état réactions aux perturbations externes communication avec les autres objets

Persistance La persistance d’un l'état est obtenue de façon élémentaire : par stockage de données pertinentes dans une structure (les types struct en C et record en Pascal). La structure est donc l'élément fondamental dans la représentation informatique de l'objet : un espace clos et contigu où figurent toutes les informations relatives à un objet.

Encapsulation des données La démarche consistant à décrire un tel espace est nommée encapsulation des données. Une structure est également décrite comme un agrégat de données hétérogènes. Le type tableau au contraire constitue un agrégat de données d’un même type (homogène).

Réactions La réaction aux perturbations externes est simulée par des fonctions que l'on peut appliquer à l'objet. L'existence chez différents objets de fonctionnalités sémantiquement voisines, et pour autant différentes dans leur réalisation, conduit à rejeter un modèle informatique de premier niveau dans lequel les fonctions sont distinguées par leur seul nom et sont globales comme c'est le cas dans les langages traditionnels non orientés objets

Difficultés Le nommage des fonctions globales nécessite de donner des noms différents à des fonctions homologues, et donc à multiplier dans un programme le nombre des symboles. Les fonctions globales ne permettent pas avec une grande finesse le contrôle d'éventuelles restrictions au graphe d'appel du programme.

Polymorphisme On accepte de donner le même nom à des fonctions dont les arguments diffèrent. Ainsi, un programmeur peut utiliser un nom unique pour l'associer à un concept d'opération unique, utilisable dans différents contextes

Avantages du polymorphisme Les programmes gagnent en abstraction, car des concepts non pertinents en sont retirés, Il n'est pas nécessaire de définir une règle de nommage des fonctions homologues (par exemple "bouge_caillou", ou bien "CaillouBouge"). L'écriture des programmes est facilitée.

Encapsulation de fonctions Dans ce modèle, sont associées logiquement à la structure (de données) représentant un objet les seules fonctions qui simulent (ou implantent) des réactions de cet objet au monde extérieur. Ces fonctions sont alors appelées des méthodes. La déclaration d'une méthode omet la mention du paramètre désignant l'objet auquel elle s'applique, appelé Objet Support

Opérations et Méthodes Par définition, toutes les méthodes de même nom constituent des implantations appropriées du même concept, qui porte le nom d' opération. Chaque méthode d'une classe implante une opération donnée pour cette classe

Polymorphisme et méthodes Aucun langage de programmation ne permet de distinguer deux fonctions par le seul type de leur valeur de retour.

Objets Une structure qui encapsule à la fois des données et des méthodes est appelée un objet. A ce titre, certaines bases de données dites "objet" n'en méritent pas le nom puisqu'elles ne sont qu'orientées "structure". Notons que le terme d'objet est défini sans qu'il ne soit question d'héritage.

Communication L'envoi d'un message d'un objet à un autre suppose qu'une méthode du premier appelle une méthode du deuxième. Dans le cas "synchrone", la réponse est fournie par la valeur de retour de la fonction appelée Dans le cas asynchrone, le réponse est fournie par un message en retour.

Messages / Méthodes L'encapsulation permet de contrôler les possibilités de communications inter objets, L'appel réciproque et récursif de méthodes entre deux (ou plus) objets dans le cas asynchrone peut conduire à des situations de bouclage

La classe (1) La partie "structure" de l'objet, contenant ses données, doit être dupliquée pour chaque objet de même type. Par contre, les méthodes de ces objets ne nécessitent pas d'être décrites plusieurs fois.

La Classe (2) On distingue donc entre la réalisation particulière d'un objet, une instance, et l'ensemble des informations nécessaires pour construire et "animer" ces instances : leur classe. Le modèle utilisé pour générer pour chaque objet une structure physique de données est appelé le prototype. On peut donc parler de “classe” sans qu'il ne soit question d'héritage.

Le type abstrait : un point de vue formel sur la classe Le concept de type abstrait est introduit pour la spécification de systèmes. Un type abstrait consiste en une description formelle (i.e. logique) des états accessibles aux objets de ce type, et des transitions qui peuvent survenir entre états. Toutes les propriétés des instances d’un type abstrait sont démontrables comme on démontre un théorème. Une telle description spécifie donc sans ambiguïté la sémantique d’un ensemble d’objets, indépendamment des perspectives de sa réalisation informatique.

des Types abstraits aux langages Le type abstrait est un modèle formel des objets qu'il décrit, et peut être appelé une classe. Cette classe comporte assez d'informations pour générer un prototype. Les transitions correspondent à des fonctions membres qui modifient les instances. Mais elle ne possède pas de réalisation physique en soi. Elle n'est qu'un cadre général de réalisation. C'est l'approche des langages comme C++ et Simula

Nécessité de réaliser le type abstrait Une classe décrit essentiellement un prototype des objets de cette classe, et les méthodes applicables aux objets de cette classe. Pour des raisons techniques l'implantation des langages orientés objet nécessite que certaines classes engendrent une structure de données permettant de stocker des pointeurs vers des méthodes de la classe. Ces méthodes sont alors appelées virtuelles.

Table de virtuelles La table de virtuelles "concrétise" la classe

C++/Java C++ demande de déclarer les fonctions virtuelles Toutes les méthodes sont virtuelles en Java.

Variations autour des classes une classe est elle même un objet, instance d'une métaclasse, et ce à l'infini tout objet peut servir de prototype à la construction d'un autre objet tous les types de données sont des objets (en Smalltalk, même un caractère est un objet, qui communique par envoi de messages avec ses voisins) l'objet classe peut contenir des informations partagées par toutes les instances de la classe (cela existe en Java, et partiellement en C++)

Objets et Classification Dans la pensée occidentale un modèle du monde par lequel les propriétés des objets découlent logiquement de la place qu'ils occupent dans une classification dont l'adéquation est mesurée au faible nombre d'exceptions qu'elle engendre. Ce modèle s'intéresse avant tout aux propriétés des objets (appelées propositions en logique) plus qu'à leurs éventuelles relations. Par exemple : si on sait qu'un "objet" est un mammifère, on sait alors qu'il allaite ses petits et qu'il ne vole pas (en général). Une classification des concepts nous indique également que tous les mammifères, et tous les oiseaux, sont des animaux.

Vision logique de la classe Les règles "A" sont descriptives de la classe Les règles "B" sont des règles d'héritage

Exemple de hiérarchie

Principes d'utilisation de l'héritage

B hérite de, ou possède un A

Une difficulté Lorsque B hérite de A, la structure de données décrite par A sera présente d'office dans toute structure de type B. La relation d'héritage de classes présente donc un caractère incrémental qui peut être utilisé comme une facilité d'écriture. (Définissant B comme héritant de A, on réalise l'économie de la description de A dans B, au prix peut être de quelques retouches permises par le langage).

Mauvais exemples Faire en sorte que la classe "Cercle" hérite de "Point" le cercle réutilise le point par héritage comme centre Faire en sorte que la classe "Ellipse" hérite de "Cercle" ellipse réutilise le diamètre comme un de ses demi-axes

Point et Cercle Un point peut être vu comme un cercle dégénéré de diamètre nul. La seule relation logique qui peut unir ces deux classes est Point => Cercle. Dans ce cas, toutes les instances de Point, si elles héritent de Cercle, vont comporter un champ appelé "diamètre" qui leur est inutile. La bonne approche est peut être de ne pas considérer d'héritage entre les deux classes.

Principe S'il est possible de dire que "tout A est un B", alors B ne doit pas hériter de A, et A peut, le cas échéant, hériter de B.

Principe pour les données membres S'il est possible de dire que tout A peut posséder un B, ou S'il est vrai que tout A possède exactement un B, alors B est une donnée de A

Deux situations pour l'héritage Héritage pour extension on ajoute des données membres. Cette situation est toujours présente quand on implante une interface Héritage pour spécialisation on restreint les domaines des attributs de la classes on durcit les invariants de classe (intégrité)

Deux autres situations Héritage pour surcharge: on substitue le code d'une fonction par une autre, en application du polymorphisme Héritage pour réutilisation pure (héritage privé) : on réutilise le code de la classe mais pas son interface

Champs, accesseurs et aspects

Masquage de données Un programme ne doit pas exposer les données membres de ses classes. Cette information peut varier au cours des évolutions de la classe et ne doit pas être divulguée

Champs, accesseurs, modifieurs Un champ (ou attribut, propriété, donnée membre) est PRIVE Accesseur : fonction permettant de lire la valeur d'un champ Modifieur : fonction permettant d'altérer l'état de l'objet

Conventions de nommage Si une classe possède une propriété Xy L'attribut (privé) est appelé "_xy" L'accesseur (non Booleén) est "getXy()" L'accesseur (Booléen) est "isXy()" Le modifieur est nommé "setXy(...)"

Exemple

Aspects D'autres langages plus évolués (plus anciens) règlent le problème du masquage de l'information d'une autre façon: Deux fonctions, les aspects de lecture et d'écriture, sont attachées potentiellement à chaque attribut. Si elles sont présentes, elles sont appelées automatiquement de façon invisible à chaque lecture/écriture

Compatibilité ascendante Toutes les versions futures d'une classe devront pouvoir être utilisées pour compiler des programmes clients anciens.

Exemple d'évolution

Exemple de divergence

Principes de Conception par Contrat

Conception par contrat Ces idées ont été inspirées par Bertrand Meyer La spécification des invariants de classe, et des pré et post conditions est préalable au codage proprement dit

Principe de substitution de Liskov Une instance d'une classe peut être substituée par une instance d'une sous classe sans que la compilation ne soit altérée le programme ne soit altéré dans son comportement. Toutes les clauses du contrat satisfaites par les superclasses sont satisfaites par les sous classes

Impact sur les invariants de classe Les invariants de classe sont vérifiés par les sous classes class A{ int integrity(){...}; }; class B : public A { int integrity(){ A::integrity(); ... }

Impact sur les préconditions Les préconditions des fonctions membres ne peuvent pas être durcies par les sous classes Sinon, une fonction appelant la fonction abstraite pourrait provoquer un échec avec une nouvelle sous classe.

Exemple de Cercle et Ellipse On a vu la possibilité de définir conceptuellement Cercle comme une sous classe de Ellipse. La fonction resize(float x, float y) demande un traitement particulier. Il n'est pas possible de durcir la précondition dans Cercle pour avoir "x==y" Que fait on?

Ellipse et Cercle (2) Par exemple: void Cercle::resize(float x, float y){ float aux=max(x,y); Ellipse::resize(aux,aux); assert(integrity());//_x==_y }

Impact sur les post conditions Les post conditions ne peuvent pas être assouplies par les sous classes Sinon, les données retournées, ou l'état de l'objet, pourraient ne plus satisfaire les conditions du programme appelant après substitution

Le principe Open/Closed La vision moderne de ce principe énoncé par Meyer est la suivante: L'interface de programmation d'une classe est: Open = ouverte aux extensions ajout de fonctions membres Closed = fermée aux modifications pas de durcissement de l'invariant de classe ni des préconditions

Le couplage faible Ce principe de conception demande que les composants logiciels (classes) soient le plus indépendant(e)s possibles. en termes de connexions en termes de création mutuelle On vise ainsi à permettre une maintenance facile du code

Cohésion forte Ce principe stipule que des éléments associés au sein d'une classe soient fortement dépendants Si ce n'est pas le cas, il convient de les séparer (exemple des itérateurs)

Conception des interfaces de programmation

Le problème Encore une fois, pour garantir une bonne compréhension collective des sources développés, il est préférable de renvoyer à des notions très communément partagées. Le développement du logiciel open source a multiplié les besoins de normalisation des interfaces de programmation Ex en Java : notion de Bean

L'objet vu comme une machine. Cette métaphore guide la définition des interfaces homme machine. On voit une machine, et on observe son état sans agir sur elle On agit sur une machine, sans nécessairement observer son état

Le capteur informatique Une fonction dont la valeur de retour est une information sur l'état de l'objet ne doit sous aucun prétexte modifier l'état de l'objet. Une telle fonction est appelée un accesseur.

Signature des accesseurs en C++ data accesseur_i (args) const {…} Le mot clef "const" garantit que la fonction est sans effet sur l'objet support Garantir qu'elle est sans effet sur des objets distants caractéristiques d'un état demande de la rigueur

Le bouton de commande Lorsqu'on désire modifier l'état d'un objet, on le fait au travers d'une procédure. La règle ici est qu'une telle procédure ne peut en aucun cas renvoyer une valeur décrivant l'état de l'objet après, ou pire encore, avant la modification. On appelle une telle fonction un modifieur.

Signature des modifieurs en C++ void modifieur _i (args) {…} "Void" garantit que la fonction ne renvoie pas d'information sur l'état de l'objet.

Identification des modifieurs Une fonction est un modifieur s'il existe des situations où un accesseur change de valeur de retour après son appel.

Pourquoi être strict Exemple de C (et C++) i++ + i++ n'est pas équivalent à 2*i++

Un accesseur/modifieur présente le même défaut Supposons qu'une fonction d'accès présente un effet de bord. E1 = (p->value() + p->value()) sera différent de E2 = (2 * p->value())

Avantages des modifieurs "void" Absence des risques évoqués précédemment Le calcul d'un état coûte potentiellement des ressources Les appels de modifieurs sont fréquemment faits en ignorant la valeur de retour Le calcul de cette valeur est alors fait inutilement (exemple de char* strcpy(char*) en C) Il doit exister un accesseur retournant l'état On ne pourra pas retirer le calcul de la valeur de retour, et les interfaces sont "fermées".

Les modifieurs retournant "this" Il est souvent utile toutefois de faire en sorte que les modifieurs retournent leur objet support Cela permet d'enchainer des cascades d'appels, et justement de faire suivre le modifieur de l'accesseur voulu... Container c; c.modif_f(params).modif_g(params).accesseur_h();

On veut quand même retourner un état Exemple:

Conversions implicites en C++ En C++, on peut avoir des modifieurs "this" et l'accès à l'état de l'objet

Cas particulier des opérateurs Les opérateurs redéfinis en C++ sont souvent des modifieurs/accesseurs, dans la mesure où ils participent à des expressions complexes. L'usage fait que leur "danger" d'utilisation est connu (ex. de "++")

Fonctions d'usage Les accesseurs "const" et modifieurs "void" ou "this" forment le squelette des interfaces de programmation. Doit en s'en contenter? NON. Une API peut mettre à disposition une collection de fonctions d'usage qui combinent si besoin est modifieurs et accesseurs Les opérateurs en font partie.

Interfaces de programmation

Etat logique / état physique On doit veiller à ce que les modifieurs d'une classe soient de vrais modifieurs: leur appel modifie les données membre de l'objet d'une manière qui altère la sémantique attachée à l'objet. Exemple : insertion dans la liste

Que faire sinon? Si un modifieur altère l'état physique (les données) sans agir sur l'état logique, c'est le signe que la classe doit être séparée. C'est l'exemple des itérateurs

Principe On définit les classes de manière à avoir identité entre état logique et état physique.

Masquage de données Les conditions d'implantation d'une classe doivent être cachés aux utilisateurs données membres, classes auxiliaires

Types de classes

Héritage Classe abstraite Classe concrète Classe "nœud"

Fonctionnalités Classe de service par exemple l'interface "displayable" Classes de définition d'interfaces abstraites l'abstraction Pile par exemple Les classes poignée Les classes "type de base" vérifié

Poignées

Interfaces abstraites

Fin du document