Upload
others
View
5
Download
0
Embed Size (px)
Citation preview
Foutse Khomh
© Vachon, 2008; Guéhéneuc, 2009; Moha, 2012; Khomh, 2010 - 2014
Département de génie informatique et de génie logiciel École Polytechnique de Montréal
LOG8430 : Architecture logicielle et
conception avancée
Conception architecturale
2/59
Conception architecturale
1. Introduction 2. Modéliser l’architecture avec UML 3. Éléments architecturaux 4. Styles architecturaux
1. Architecture pipeline 2. Architecture avec référentiel de données 3. Architecture MVC 4. Architecture multi-couches 5. Architecture n-niveaux
5. Développer un modèle architectural
3/59
1. Introduction
Qu’est-ce qu’une architecture logicielle ? – L’architecture d’un logiciel est la structure des
structures (modules) d’un système – Elle inclut
• Les composants logiciels • Les propriétés externes visibles de ces composants • Les relations entre ces composants Cf. [Bass, Clements, and Kazman (1998) ]
4/59
1. Introduction
Contrairement aux spécifications produites par l’analyse fonctionnelle – le modèle d'architecture ne décrit pas ce que
doit réaliser un système informatique mais plutôt comment il doit être conçu de manière à répondre aux spécifications.
– L’analyse fonctionnelle décrit le « quoi faire » alors que l’architecture décrit le « comment le faire »
5/59
Introduction
Qu’est que la description d’une architecture logicielle ? – La définition de l’architecture logicielle consiste à:
• Décrire l’organisation générale d’un système et sa décomposition en sous-systèmes ou composants
• Déterminer les interfaces entre les sous-systèmes • Décrire les interactions et le flot de contrôle entre les sous-
systèmes • Décrire également les composants utilisés pour implanter les
fonctionnalités des sous-systèmes – Les propriétés de ces composants – Leur contenu (e.g., classes, autres composants) – Les machines ou dispositifs matériels sur lesquels ces modules
seront déployés
6/59
Introduction
Pourquoi développer une architecture logicielle ? – Pour permettre à tous de mieux comprendre le
système – Pour permettre aux développeurs de travailler
sur des parties individuelles du système en isolation
– Pour préparer les extensions du système – Pour faciliter la réutilisation et la réutilisabilité
7/59
Introduction
Utilité d’une architecture logicielle [Garlan 2000] – Compréhension : facilite la compréhension des grands systèmes
complexes en donnant une vue de haut-niveau de leur structure et de leurs contraintes. Les motivation des choix de conception sont ainsi mis en évidence
– Réutilisation : favorise l’identification des éléments réutilisables, parties de conception, composants, caractéristiques, fonctions ou données communes
– Construction : fournit un plan de haut-niveau du développement et de l’intégration des modules en mettant en évidence les composants, les interactions et les dépendances
8/59
Introduction
Utilité d’une architecture logicielle [Garlan 2000] – Évolution : met en évidence les points où un système peut être
modifié et étendu. La séparation composant/connecteur facilite une implémentation du type « plug-and-play »
– Analyse : offre une base pour l’analyse plus approfondie de la conception du logiciel, analyse de la cohérence, test de conformité, analyse des dépendances
– Gestion : contribue à la gestion générale du projet en permettant aux différentes personnes impliquées de voir comment les différents morceaux du casse-tête seront agencés. L’identification des dépendance entre composants permet d’identifier où les délais peuvent survenir et leur impact sur la planification générale
9/59
2. Modéliser avec UML
Les vues (structurelles) d’une architecture logicielle – Vue logique. Description logique du système décomposé
en sous-systèmes (modules + interface) • UML : diagramme de paquetages
– Vue d’implémentation. Description de l’implémentation (physique) du système logiciel en termes de composants et de connecteurs
• UML : diagramme de composants
– Vue de déploiement. Description de l’intégration et de la distribution de la partie logicielle sur la partie matérielle
• UML: diagramme combiné de composants et de déploiement
10/59
Rappel : vues d’un système
Vue structurelle (modèle statique)
Vue des cas d’utilisation (modèle fonctionnel des exigences)
Vue du comportement et des interactions (modèle dynamique)
Diagramme de classes
Diagramme de cas d’utilisation
Diagramme combiné de
déploiement/ composants
Diagramme d’activités
Diagramme d’états Diagramme de
communication
Diagramme de séquence
Diagramme de composants
comportement comportement
comportement
interaction
interaction
Diagramme de packages
11/59
Modéliser l’architecture avec UML
Diagramme de paquetages
12/59
Modéliser l’architecture avec UML
Diagramme de composants
13/59
Modéliser l’architecture avec UML
Diagramme combiné de déploiement/composants
14/59
3. Éléments architecturaux
Deux ou plusieurs composants interagissent via un connecteur Chaque élément architectural possède une structure et/ou
comportement pouvant être décrit par un modèle UML approprié
Comp_A
Comp_B
port
connecteur
configuration
interface fournie
interface requise
Classe_C dépendance
composant
«realisation»
15/59
Éléments architecturaux
Composant – Encapsule un traitement et/ou des données – Encapsule un sous-ensemble de fonctionnalités
et/ou de données du système – Restreint l’accès à ce sous-ensemble au moyen
d’une interface définie explicitement – Possède des dépendances explicitement
définies pour exprimer les contraintes requises par son contexte d’exécution ou sa réalisation
compA
16/59
Éléments architecturaux
Composant – Unité autonome servant de bloc de construction pour le système – Les composants implémentent typiquement des services
spécifiques à l’application – La manifestation concrète d’un composant est appelé artéfact
(instance du composant déployée sur le matériel) • N’importe quel type de code sur n’importe quel support numérique • Code source, fichiers binaires, scripts, fichiers exécutables, bases de
données, applications, etc.
Order Order.jar
«manifestation»
17/59
Éléments architecturaux
Interface de composant – Permet à un composant d’exposer les moyens à utiliser
pour communiquer avec lui – Types d’interfaces
• Interface offerte : définit la façon de demander l’accès à un service offert par le composant
• Interface requise : définit le type de services (aide) requis par le composant
– Une interface est attachée à un port du composant • Port = point de communication du composant • Plusieurs interfaces peuvent être attachées à un même port
18/59
Éléments architecturaux
Dépendances entre composants – Dépendance = relation entre deux composants – Types de dépendances
• Un composant peut dépendre d’un autre composant qui lui fournit un service ou une information
• Un composant peut dépendre d’une classe qui implémente une partie de son comportement. Dépendance de réalisation
• Un composant peut dépendre d’un artefact (code source, fichier .jar, etc.) qui l’implante concrètement. Dépendance de manifestation
19/59
Éléments architecturaux
Connecteur – Dans les systèmes complexes, les interactions peuvent constituer
un enjeu encore plus important que les fonctionnalités des composants individuels
– Définition : élément architectural qui définit le type d’interactions entre les composants et les règles gouvernant ces interactions
– Un connecteur relie les ports de deux ou plusieurs composants – Un connecteur décrit un mécanisme de connexion indépendant de
l’application • Représente un concept abstrait, paramétrable et indépendant des
composants spécifiques qu’il relie – Les attributs du connecteur décrivent ses propriétés
comportementales • E.g. sa capacité, le temps de latence, le type d’interaction (binaire/n-
aire, asymétrique/symétrique, détails du protocole), etc.
20/59
Éléments architecturaux
Connecteur – Un connecteur peut avoir un ou plusieurs rôles
• Communication :rôle le plus fréquent • Coordination : contrôle du calcul, de la transmission des données, etc.
Orthogonal aux autres rôles • Conversion : permet l’interaction entre composants développés
indépendamment dans des langages différents par exemple • Facilitation : permet l’interaction entre composants conçus pour
interragir ensemble. Synchronisation, accès contrôlées aux données partagées, etc.
– Selon le(s) rôles qu’il doit remplir et le type de communication souhaitée entre deux composants, choix d’un type
• Procedure call (comm + coord) , Data access (comm + conv), Event, Stream, Linkage, Distributor, Arbitrator, Adaptor (conv)
21/59
Éléments architecturaux Type de connecteur Rôle Attributs
Valeurs d’attributs
Software Architecture: Foundations, Theory, and Practice; R. N. Taylor, N. Medvidovic, and E. M. Dashofy; © 2008 John Wiley & Sons, Inc.
22/59
Exemple d’un diagramme de composants
23/59
Choix d’une architecture
Choix d’une architecture – Dépend des exigences fonctionnelles et non
fonctionnelles du logiciel – Choix favorisant la stabilité : l’ajout de nouveaux
éléments sera facile et ne nécessitera en général que des ajustements mineurs à l’architecture
– Influencé par certains « modèles connus » de décomposition en composants (styles architecturaux) et de mode d’interactions (e.g., orienté objet)
24/59
4. Style architecturaux
Un style architectural – Est un patron décrivant une architecture logicielle
permettant de résoudre un problème particulier – Définit
• Un ensemble de composants et de connecteurs (et leur type) • Les règles de configuration des composants et connecteurs
(topologie) • Une spécification du comportement du patron • Des exemples de systèmes construits selon ce patron
– Constitue un modèle éprouvé et enrichi par l’expérience de plusieurs développeurs
• Compréhensibilité, maintenance, évolution, réutilisation, performance, documentation, etc.
25/59
Architecture pipeline
Convient bien aux systèmes de traitement et de transformation de données Composants = filtre ; Connecteur = canal
– Filtre • Traite indépendamment et asynchrone • Reçoit ses données d’un ou plusieurs canaux d’entrée, effectue la transformation/traitement
des données et envoie les données de sortie produites sur un ou plusieurs canaux de sorties • Fonctionnent en concurrence. Chacun traite les données au fur et mesure qu’il les reçoit
– Canal • Unidirectionnel au travers duquel circulent un flot de données (stream). • Synchronisation et utilisation d’un tampon parfois nécessaire pour assurer la bon
fonctionnement entre filtre producteur et filtre consommateur – Exemples : application de traitement de texte, de traitement de signaux. Compilateur
(analyse lexicale, syntaxique, sémantique)
canal de communication
Filtre
synchro
26/59
Architecture pipeline
Système de traitement du son Encodeur pour
sortie de microphone
Filtrer l’écho
Filtrer le bruit
Retirer les fréquences non vocales
Égaliser les les intervalles dynamiques
Compresser Transmettre Recevoir Décompresser
Encoder la sortie des haut-parleurs
Encodeur de bruit ambiant
27/59
Architecture pipeline
Avantages – Bon pour traitement en lot (batch) – Très flexible – Analyse facilitée : performance,
synchronisation, goulot d’étranglement, etc.
– Se prête bien à la décomposition fonctionnelle d’un système
Inconvénients – Mauvais pour le traitement interactif
D’un point de vue conception – Diviser pour régner : les filtres
peuvent être conçus séparément – Cohésion : les filtres sont un type de
cohésion fonctionnelle – Couplage : les filtres n’ont qu’une
entrée et une sortie en général – Abstraction : les filtres cachent
généralement bien leurs détails internes
– Réutilisabilité : les filtres peuvent très souvent être réutilisés dans d’autres contextes
– Réutilisation : il est souvent possible d’utiliser des filtres déjà existants pour les insérer dans le pipeline
28/59
Architecture avec référentiel de données (shared data) Utilisée dans le cas où des données sont partagées et
fréquemment échangées entre les composants – Deux types de composants : référentiel de données et accesseur de
données • Les référentiels constituent le medium de communication entre les
accesseurs – Connecteur : relie un accesseur à un référentiel
• Rôle de communication, mais aussi possiblement de coordination, de conversion et de facilitation
A A A A A
Référentiel1
Référentiel2
29/59
Architecture avec référentiel
Variantes – Style tableau noir : les référentiels sont des agents
actifs. Lorsqu’ils reçoivent une données, ils informent tous les accesseurs concernés
– Style référentiel : les référentiels sont passifs. Simple vocation de stockage. Les composants accède aux référentiels comme ils le désirent
– Exemples : application de bases de données, systèmes Web, systèmes centrés sur les données (e.g. système bancaire, système de facturation ,etc.), environnement de programmation
30/59
Architecture avec référentiel Environnement de programmation
Débogueur Éditeur syntaxique
Compilateur
Référentiel
Arbre syntaxique
Table de symboles
Analyseur syntaxique
Analyseur sémantique
Optimiseur
Analyseur lexical
Générateur de code
31/59
Architecture avec référentiel
Avantages – Avantageux pour les applications impliquant des
tâches complexes sur les données, nombreuses et changeant souvent. Une fois le référentiel bien défini, de nouveaux services peuvent facilement être ajoutés
Inconvénients – Le référentiel peut facilement constituer un
goulot d’étranglement, tant du point de vue de sa performance que du changement
32/59
Architecture Modèle-Vue-Contrôleur (MVC) Séparer la couche interface utilisateur des autres parties du
système (car les interfaces utilisateurs sont beaucoup plus susceptibles de changer que la base de connaissances du système)
Composé de trois types de composants – Modèle : rassemble des données du domaine, des connaissances
du système. Contient les classes dont les instances doivent être vues et manipulées
– Vue : utilisé pour présenter/afficher les données du modèle dans l’interface utilisateur
– Contrôleur : contient les fonctionnalités nécessaires pour gérer et contrôler les interactions de l’utilisateur avec la vue et le modèle
33/59
Architecture Modèle-Vue-Contrôleur
View
Contrôleur
Modèle
créer et mettre à jour
modifier
notifier changements
Reçoit les événements des acteurs
Vus par les acteurs
Consulter l’état (i.e. les données)
E.g. Génère le code html pour le
browser
E.g. Interprète les transmissions http
« post » du browser
Le sous-système gérant l’information.
34/59
Architecture Modèle-Vue-Contrôleur
Modèle : noyau de l’application – Enregistre les vues et les contrôleurs qui en dépendent – Notifie les composants dépendants des modifications aux données
Vue : interface (graphique) de l’application – Crée et initialise ses contrôleurs – Affiche les informations destinées aux utilisateurs – Implante les procédure de mise à jour nécessaires pour demeurer
cohérente – Consulte les données du modèle
Contrôleur : partie de l’application qui prend les décisions – Accepte les événement correspondant aux entrées de l’utilisateur – Traduit un événements (1) en demande de service adressée au modèle ou
bien (2) en demande d’affichage adressée à la vue – Implémente les procédures indirectes de mise à jour des vues si nécessaire
35/59
Architecture Modèle-Vue-Contrôleur
Avantages : approprié pour les systèmes interactifs, particulièrement ceux impliquant plusieurs vues du même modèle de données. Peut être utilisé pour faciliter la maintenance de la cohérence entre les données distribuées
Inconvénient : goulot d’étranglement possible
D’un point de vue conception – Diviser pour régner : les
composants peuvent être conçus indépendamment
– Cohésion : meilleure cohésion que si les couches vue et contrôle étaient dans l’interface utilisateur.
– Couplage : le nombre de canaux de communication entre les 3 composants est minimal
– Réutilisabilité : la vue et le contrôle peuvent être conçus à partir de composants déjà existants
– Flexibilité : il est facile de changer l’interface utilisateur
– Testabilité : il est possible de tester l’application indépendamment de l’interface
36/59
Plan de séance
Résumé de la séance précédente
Style architecturaux (suite)
Conception détaillée
Résumé de la séance
37/59
Résumé
38/59
Résumé
39/59
Résumé
40/59
Résumé
41/59
Plan de séance
Résumé de la séance précédente
Style architecturaux (suite)
Conception détaillée
Résumé de la séance
42/59
Architecture multi-couches
Composants : chaque composant réalise un service – Une couche offre un service (serveur) aux couches externes (client) – Service créé indépendamment du logiciel ou spécifiquement – Met à profit la notion d’abstraction, les couches externes sont plus
abstraites (haut niveau) que les couches internes
Connecteurs : dépendent du protocole d’interaction souhaité entre couches – Système fermé : une couche n’a accès qu’aux couches adjacentes.
Les connecteurs ne relient que les couches adjacentes – Système ouvert : toutes les couches ont accès à toutes les autres.
Les connecteurs peuvent relier deux couches quelconques
Exemples : souvent utilisé pour les systèmes implémentant des protocoles de communication (TCP/IP)
43/59
Architecture multi-couches
Chaque couche est un composant avec une interface bien définie utilisée par la couche juste au dessus (i.e., externe)
La couche supérieure (externe) voit la couche inférieur (interne) comme un ensemble de services offerts
Un système complexe peut être construit en superposant les couches de niveau d’abstraction croissant
Il est important d’avoir une couche séparée pour l’IU Les couches juste au dessous de l’IU offrent les fonctions applicatives définies par les
cas d’utilisation Les couches les plus basses offrent les services généraux E.g., communication réseau, accès à la base de données
Encrypter/décrypter un fichier 1. Entrée d’un mot de passe 2. Obtention d’une clef d’accès 3. Encryptage/décryptage du fichier 4. Fonctions d’encryptage/décryptage
44/59
Architecture multi-couches Système fermé
– Reference Model of Open Systems Interconnection (OSI model)
Application
Présentation
Session
Transport
Réseau
Ligne de données
Physique
Identifier et authentifier une connexion
Transformation des données (encryption,etc.)
Interface matérielle du réseau
Transmission des data frames sans erreurs
Transmission des routing packets
Transmission (point à point) fiable des données
45/59
Architecture multi-couches
Application
Swing
AWT
X11
46/59
Architecture multi-couches
Interface utilisateur
Logique applicative
Accès au système
d’exploitation Accès à la base de données
Communication réseau
Application programs
Screen display facilities
User account management
File system
Kernel (handling processes
and swapping
47/59
Architecture multi-couches
D’un point de vue conception – Diviser pour régner : les couches
peuvent être conçues séparément – Cohésion : si elles sont bien
conçues, les couches présenter une cohésion par couche
– Couplage : des couches inférieures bien conçues ne devraient rien savoir à propos des couches supérieures et les seules connexions autorisées entre couches se font via les API
– Abstraction : on n’a pas à connaître les détails d’implémentation des couches inférieures
– Réutilisabilité : les couches inférieures peuvent être conçues de façon à offrir des solutions génériques réutilisables
– Réutilisation : on peut souvent réutiliser des couches développées par d’autres et qui proposent le service requis
– Flexibilité : il est facile d’ajouter de nouveaux services construits sur les services de plus bas niveau
– Anticipation du changement : en isolant les composants dans des couches distinctes, le système devient résistant
– Portabilité : tous les services relatifs à la portabilité peuvent être isolés
– Testabilité : les couches peuvent être testées indépendamment
– Conception défensive : les API des couches constituent des endroits stratégiques pour insérer des assertions de vérification
48/59
Architecture n-niveaux
Pour les systèmes distribués – Comparable à une architecture par couches… dont les couches
seraient distribuées ! • N.b. L’architecture multi-couche est généralement utilisée pour décrire
la structure interne (non distribuée) d’un composant qui peut lui-même appartenir à une architecture (distribuée) n-partie
– Par abus de langage, la notion de tier a pris le sens de couche distribuée
– Composants : chaque niveaux est représenté par un composant qui joue le rôle de client et/ou de serveur
– Connecteurs : relient un client à un serveur. Connexion asymétrique. Doit supporter les communication distantes (e.g., requêtes RPC, HTTP, TCP/IP)
– Exemples • Client-serveur, Trois niveaux, Quatre niveaux
49/59
Architecture n-niveaux
Architecture 2-niveaux (client-serveur ou client lourd)
Architecture 3-niveaux (client léger)
Architecture 4-niveaux Client Bases de
données
Navigateur Web
Serveurs de
base de données
Logique applicative requête
de service requête de service de B.D.
Logique Applicative
(calculs, business)
Présentation (partie web)
Client Serveur requête de service
50/59
Architecture n-niveaux
Architecture client-serveur – Exemple typique : un système d’informations utilisant
une base de données centrale. (cas spécial de l’architecture avec référentiel)
• Clients : reçoivent les données de l’utilisateur, initient les transactions, etc.
• Serveur : exécute les transactions, assure l’intégrité des données
– Architecture pair-à-pair = une généralisation de l’architecture client-serveur
• Les composants peuvent tous à la fois être client et serveur • Conception plus difficile: flot de contrôle plus complexe dû à la
possibilité de deadlocks…
51/59
Architecture n-niveaux Architecture client-serveur
Client1
Client2
Client3
Serveur
<<communication>> chercher adresse
<<communication>> Échanger msg
<<communication>> Échanger msg
<<communication>> Échanger msg
<<communication>> chercher adresse
netscape:WebBrowser
iexplo:WebBrowser
lynx:WebBrowser
diro:WebServer
www.cmu.edu:WebServer
52/59
Architecture n-niveaux
Architecture 3-niveaux – Organisation en trois couches
• Couche interface: Composé d’objets interfaces (boundary objects) pour interagir avec l’utilisateur (fenêtres, formulaires, pages Web, etc.)
• Couche logique applicative : Comporte tous les objets de contrôle et d’entités nécessaire pour faire les traitements, la vérification des règles et les notifications requises par l’application
• Couche de stockage : réalise le stockage, la récupération et la recherche des objets persistants
– Avantage sur l’architecture client-serveur • Permet le développement et la modification de différentes
interfaces utilisateurs pour la même logique applicative
53/59
Architecture n-niveaux
Architecture 3-parties
Base de données
corporative
Dépôt de données
Marché de données
Client X
Client Windows
Serveur de B.D. Unix
Serveur de B.D. Unix
Réseau
Serveur Windows NT
Logique applicative
54/59
Architecture n-niveaux
Architecture 3-niveaux À noter que la tendance veut que la partie cliente soit – De plus en plus mince, i.e., le
client ne fait qu’afficher un contenu HTML
– La logique applicative est alors responsable de créer les pages Web à afficher par le client
– Il faut dissocier logique applicative et présentation des données
Interface gestionnaire
Base de données clients
Gestion des dossiers
55/59
Architecture n-niveaux
Architecture 4-niveaux – Architecture dont la couche logique applicative est décomposée en
• Couche Présentation (JSP, servlets) – Présentation du contenu statique: Contenu HTML ou XML affiché par le
client – Présentation du contenu dynamique : contenu organisé et créé
dynamiquement par le serveur web (pour ensuite être affiché en HTML/XML par le client)
• Couche Logique applicative (calculs purs) : réalise le cœur des traitements de l’application
– Avantage sur l’architecture 3-niveaux • Permet de supporter un grand nombre de formats de présentation
différents (propres à chaque client), tout en réutilisant certains des objets de présentation entre les clients. Réduction des redondances…
• Bien adaptée pour les applications Web devant supporter plusieurs types de clients
56/59
Architecture n-niveaux Architecture 4-niveaux
Interface ATM
Gestion opérations bancaires
Présentation Serveur
Interface Web
Interface employé de la banque
Accès base de données comptes clients
Java Server Pages - Partie cliente - Partie serveur
Serveur Clients Serveur de base de données
<<build>>
<<submit>>
<<submit>>
<<build>>
<<build>>
<<submit>>
57/59
Architecture n-niveaux
D’un point de vue conception – Diviser pour régner : de façon
évidente, client et serveur peuvent être développées séparément
– Cohésion : le serveur peut offrir des services cohésifs au client
– Couplage : un seul canal de communication existe souvent entre client et serveur
– Réutilisation : il est possible de trouver une bibliothèque de composants, interfaces, etc. pour construire les systèmes
• Toutefois, les systèmes client-serveur dépendent très souvent de nombreuses considérations liées intimement à l’application
Flexibilité : il est assez facile d’ajouter de nouveaux clients et serveurs
Portabilité : on peut développer de nouveaux clients pour de nouvelles plateformes sans devoir porter le serveur
Testabilité : on peut tester le client et le serveur indépendamment
Conception défensive : on peut introduire des opérations de vérification dans le code traitant les messages reçus de part et d’autre
58/59
Développer un modèle architectural Commencer par faire une esquisse de l’architecture
– En se basant sur les principaux requis des cas d’utilisation ; décomposition en sous-systèmes
– Déterminer les principaux composants requis – Sélectionner un style architectural
Raffiner l’architecture – Identifier les principales interactions entre les composants et les interfaces
requises – Décider comment chaque donnée et chaque fonctionnalité sera distribuée
parmi les différents composants – Déterminer si on peut réutiliser un cadriciel existant (réutilisation) ou si on
peut en construire un (réutilisabilité). Considérer chacun des cas d’utilisation et ajuster l’architecture pour
qu’il soit réalisable Détailler l’architecture et la faire évoluer
59/59
Plan de séance
Résumé de la séance précédente
Style architecturaux (suite)
Conception détaillée
Résumé de la séance
3
Conception détaillée
1. Introduction2. Patrons GRASP3. Patrons de conception4. Étude de cas5. Anti-patrons
4
1. Introduction
Conception architecturale– Décomposition sous forme de sous-systèmes et modules– Attribution des fonctionnalités aux composants– Allocation physique des composants aux ressources
Conception détaillée– “Élaboration de propositions pour une solution particulière et
modélisation de l’interaction détaillée entre ces composants" Software Engineering Institute report (Budgen, 1989)
– Détails internes de chaque module: méthodes d’interface, paramètres des méthodes, format des E/S, structures de données et algorithmes utilisés
5
1. Introduction
Après avoir identifié les exigences et créer un modèle de domaine– Ajouter ensuite les méthodes aux classes logicielles– Définir les messages entre les objets pour répondre aux
exigences– Penser à utiliser des solutions éprouvées (ex. patrons de
conception)
6
Introduction But de la phase de conception
– Construire les diagrammes qui décrivent les communications entre les objets et leurs responsabilitésrespectives
– 2 principaux types de diagrammes :• Diagrammes de classes• Diagrammes d'interaction (séquence et/ou collaboration)
– Cette phase nécessite principalement la connaissance des :
• Principes d'assignation de responsabilités• Patrons de conception
7
Patrons
« Un patron décrit un problème devant être résolu, une solution, et le contexte dans lequel cette solution est considérée. Il nomme une technique et décrit ses coûts et ses avantages. Il permet, à une équipe, d’utiliser un vocabulaire commun pour décrire leurs modèles » Johnson 97.
« Un patron est une solution à un problème dans un contexte » Lea 97
Les patrons fournissent des solutions à des problèmes courants de conception
8
Historique
Inspirés des patrons introduits en 1977 par Christopher Alexander, architecte en bâtiment
Les patrons OO ont été introduits par K. Beck et W. Cunningham (1987)– Patrons pour des interfaces utilisateurs
Gamma, Helm, Johnson et Vlissides « Design Patterns : Elements of reusable object oriented software », 1994 . Patterns GoF (Gang of Four)
Patrons GRASP: Livre de Larman 1997, « Applying UML and Patterns »
9
Aspects essentiels d’un patron
Un patron a un nom évocateurNom : « Singleton »
Un patron résout un problèmeProblème : une classe ne peut avoir qu’une
et une seule instance
Un patron fournit une solution Solution : il faut créer une méthode statique de la classe qui retourne l’instance unique
10
Rôles des patrons
Famille de solutions éprouvées
Réduire la complexité
Guider le concepteur à travers des architectures utiles
Capitaliser la connaissance d’experts sur la façon de concevoir
Fournir un vocabulaire commun
11
Conception détaillée
1. Introduction2. Patrons GRASP3. Patrons de conception4. Étude de cas5. Anti-patrons
12
Patrons GRASP
General Responsability Assignment Software Patterns, ou patrons généraux d’affectation des responsabilités
GRASP signifie en anglais « saisir »
« Un patron GRASP est une description des principes fondamentaux de la conception objet et de l’affectation des responsabilités exprimés sous forme réutilisable » Larman
Les patrons GRASP décrivent des principes fondamentaux d'assignation des responsabilités à des objets
13
Patrons GRASP
Approche basée sur des patrons d’affectation de responsabilités– Pour maîtriser les bases de la conception orientée objet (COO)– Pour comprendre l’affectation des responsabilités en COO
Permet d'appliquer un raisonnement de conception de façon méthodique, rationnelle et explicable
Guide pour assigner correctement les responsabilités aux différentes classes lors du passage vers la conception
14
Patrons GRASP
Ces patrons sont, pour la plupart, directement issus du bon sens du concepteur
Les patrons GRASP Vs GoF– GRASP pour les notions de base concernant
l’affectation des responsabilités – GoF pour les notions plus avancées
15
Patrons GRASP
9 patrons d'assignation de responsabilités :
– Expert en information : donner la responsabilité à l'objet le mieux en mesure d'y satisfaire
– Créateur : donner la responsabilité de créer un objet à un autre objet directement impliqué dans une relation avec l'objet créé
– Faible couplage : assigner les responsabilités de façon à ce que le couplage reste faible
– Forte cohésion : assigner les responsabilités de façon à ce que la cohésion reste élevée
– Contrôleur : assigner la responsabilité de gérer les messages d'événements du système à une classe spécialisée du modèle
16
Patrons GRASP
9 patrons d'assignation de responsabilités :
– Polymorphisme : Lorsqu’un comportement varie selon le type, affecter la responsabilité aux types pour lesquels le comportement varie avec des opérations polymorphes
– Indirection : affecter la responsabilité à un objet qui sert d’intermédiaire pour éviter le couplage direct
– Fabrication pure : affecter un ensemble très cohésif de responsabilités à une classe « comportementale » artificielle
– Protection des variations : identifier les points de variation ou d’instabilité prévisibles et affecter les responsabilités afin de créer une « interface » stable
17
Conception détaillée
1. Introduction2. Patrons GRASP3. Patrons de conception4. Étude de cas5. Anti-patrons
18
Catégories de patrons de conception Création Fabrique abstraite (Abstract
Factory) Monteur (Builder) Fabrique (Factory Method) Prototype (Prototype) Singleton (Singleton)
Structuraux Adaptateur (Adapter) Pont (Bridge) Objet composite (Composite) Décorateur (Decorator) Façade (Facade) Poids-mouche (Flyweight) Proxy (Proxy)
Comportementaux– Chaîne de responsabilité (Chain
of responsibility)– Commande (Command)– Interpréteur (Interpreter)– Itérateur (Iterator)– Médiateur (Mediator)– Mémento (Memento)– Observateur (Observer)– État (State)– Stratégie (Strategy)– Patron de méthode (Template
Method)– Visiteur (Visitor)
19
Conception détaillée
1. Introduction2. Patrons GRASP3. Patrons de conception4. Étude de cas5. Anti-patrons
20
Conception d'un éditeur WYSIWYG, appelé Lexi
Une représentation d’un document dans cetéditeur occupe une grande zone centralerectangulaire
Le document peut mélanger librement texte et graphiques dans une variété de formats (choix de polices pour le texte et format d’images pour le graphique)
Le document sera entouré des menus déroulants et des ascenseurs de défilements habituels
Étude de cas
21
Étude de cas
1. Structure du document2. Formatage3. Opérations utilisateur 4. Décoration de GUI5. Multiple look & feels6. Multiple systèmes de
fenêtrage7. Vérification d’orthographe
et césure de mots
7 problèmes de conception
22
1. Structure du document Arrangement hiérarchique de formes
Représenté sous formes de lignes, colonnes, figures, polygones, tables, caractères …
GUI devra permettre des manipulations comme un groupe– Ex: faire référence à une table comme un tout
On veut traiter du texte et des graphiques de façon uniforme
Pas de distinction entre des éléments simples ou des groupes– Ex: Le 10ème élément de la ligne 5 pourrait être un caractère
atomique ou une figure complexe comprenant des sous-parties imbriquées
23
1. Structure du document
En particulier, cette structure doit permettre :
– de maintenir la structure physique du document (organisation du texte et des graphiques en lignes, colonnes, figures, tables, etc.)
– de créer et de présenter le document visuellement
– d’établir un mécanisme de correspondance entre positions d'affichage et les éléments de la représentation interne (pour l'utilisation de la souris)
– traiter uniformément le texte et le graphique, les éléments composés et les éléments simples
24
Exercice Quel patron de conception suggérez-vous pour
représenter cette structure de document ?
Donner le diagramme de classe correspondant à cette étude de cas et une esquisse du code Java
25
Quel patron de conception ? Création Fabrique abstraite (Abstract
Factory) Monteur (Builder) Fabrique (Factory Method) Prototype (Prototype) Singleton (Singleton)
Structuraux Adaptateur (Adapter) Pont (Bridge) Objet composite (Composite) Décorateur (Decorator) Façade (Facade) Poids-mouche (Flyweight) Proxy (Proxy)
Comportementaux– Chaîne de responsabilité (Chain
of responsibility)– Commande (Command)– Interpréteur (Interpreter)– Itérateur (Iterator)– Médiateur (Mediator)– Mémento (Memento)– Observateur (Observer)– État (State)– Stratégie (Strategy)– Patron de méthode (Template
Method)– Visiteur (Visitor)
26
Structure
Le Patron Composite
Intention : Composer des objets en des structures arborescentes pour représenter des hiérarchiescomposant/composé. Traiter, de façon uniforme, les objets individuels et les combinaisons de ceux-ci
27
Composition récursive Construire des éléments plus complexes à partir
de plus simples
Implications:– Chaque objet a besoin d’une classe correspondante– Toutes ces classes doivent avoir des interfaces
compatibles afin de traiter les objets uniformément
28
Classe Glyph
Les glyphes savent comment se dessiner eux-mêmes Les glyphes connaissent l’espace qu’ils occupent Les glyphes connaissent leurs enfants et parents
public abstract class Glyph {
Point p;
// aspect
public abstract void draw(Window w);
public abstract Rectangle getBounds();
// positionnement
public abstract boolean intersects(Point p);
// structure
public abstract void insert(Glyph g, int i);
public abstract void remove(Glyph g);
public abstract Glyph child(int i);
public abstract Glyph parent();
}
29
Classe Glyph Une classe abstraite pour tous les objets (primitifs
et composés) qui peuvent apparaître dans un document
30
Classe Glyph Une classe abstraite pour tous les objets (primitifs
et composés) qui peuvent apparaître dans un document
31
public class Character extends Glyph {
char c;
public void draw(Window w) {
DrawEngine.drawText(p.getX(), p.getY(), c);
}
}
Exemple de code
32
public class Row extends Glyph {
private Vector<Glyph> children = new Vector<Glyph>();
public void draw(Window w) {
for (int i = 0; i < children.size(); ++i) {
Glyph g = (Glyph) children.elementAt(i);
g.draw(w);
}
}
public Glyph child(int i) {
return children.get(i);
}
public void insert(Glyph g, int i) {
children.add(i,g);
}
public void remove(Glyph g) {
children.remove( g );
}
Exemple de code
33
2. Formatage Comment construire une structure physique
particulière– Et maintenir une séparation entre les données et la vue?
Document correctement formaté
Plusieurs responsabilités– Découper le texte en lignes– Découper les lignes en colonnes– Modifier les largeurs des marges– Modifier les indentations des lignes– Poser des tabulations– Faire des espacements simples ou doubles
Problème restreint à la répartition d’une collection de glyphes en lignes
34
2. Formatage Découpage d’un document en lignes
– Plusieurs algorithmes différents• Balance entre qualité de formatage et vitesse de
réalisation– Algorithmes complexes
L’algorithme de formatage doit être bien encapsulé– Indépendance vis-à-vis de la structure du document
• Pouvoir ajouter un nouvel algorithme de formatage sans modifier les glyphes existants
• Pouvoir ajouter un nouveau type de glyphe sans modifier l’algorithme de formatage
Changer dynamiquement l’algorithme de formatage (au moins à la compilation)
35
Exercice Quel patron de conception suggérez-vous pour
représenter cette structure de document ?
Donner le diagramme de classe correspondant à cette étude de cas et une esquisse du code Java
36
Quel patron de conception ? Création Fabrique abstraite (Abstract
Factory) Monteur (Builder) Fabrique (Factory Method) Prototype (Prototype) Singleton (Singleton)
Structuraux Adaptateur (Adapter) Pont (Bridge) Objet composite (Composite) Décorateur (Decorator) Façade (Facade) Poids-mouche (Flyweight) Proxy (Proxy)
Comportementaux– Chaîne de responsabilité (Chain
of responsibility)– Commande (Command)– Interpréteur (Interpreter)– Itérateur (Iterator)– Médiateur (Mediator)– Mémento (Memento)– Observateur (Observer)– État (State)– Stratégie (Strategy)– Patron de méthode (Template
Method)– Visiteur (Visitor)
37
Structure
Le Patron Strategy
Intention : “Définit une famille d’algorithmes, encapsulechacun d’entre eux, et les rend interchangeables. Le modèle Strategy permet aux algorithmes d’évoluerindépendamment des clients qui les utilisent.”
38
– Objet Composition : lorsque créé contient les glyphes qui déterminent le contenu, mais la structure (telle que row, column)
– Lorsque Compose() est appelé, il itère sur tous les glyphes et les compose (formate en insérant de nouveaux glyphes de lignes et de colonnes)
2. Formatage Responsabilités Opérations
Quoi formater void SetComposition(Composition)
Quand formater virtual void Compose()
Permet de récupérer le contexte car pas passé en paramètre
39
– Des lignes et colonnes sont insérées par le Compositor, i.e. l’algorithme de justification
– Initialement, une composition non formatée contient seulement les glyphes enfants visibles
– Après exécution de Compositor, il contiendra également les glyphes structurels invisibles qui définissent le format
2. Formatage
Généré conformément aux stratégies de Compositor et n’affectent pas les contenus des glyphes terminaux
40
Forte séparation entre le code qui supporte la structure physique du document et le code pour les différents algorithmes de formatage
Ajout facile de nouvelles sous-classes Compositor sans toucher aux classes de Glyphe et inversement
On peut changer l’algorithme de justification à l’exécution en ajoutant une opération DefCompositor à l’interface de Composition
2. Formatage
41
Exemple de codepublic class Composition extends Glyph {
private Vector<Glyph> leaf_glyphs;
public void performComposition(Compositor c){
for (int i = 0; i < leaf_glyphs.size(); ++i) {
Glyph g = (Glyph) leaf_glyphs.elementAt(i);
insert(g, i);
}
c.setContext(this);
c.compose();
} }public abstract class Compositor {
Composition composition;
public void setContext(Composition comp){
this.composition = comp;
}
public abstract void compose();
}
public class SimpleCompositor
extends Compositor {
public void compose() {
...
}
}
public class TexCompositor
extends Compositor {
public void compose() {
...
}
}
42
3. Opérations utilisateur Opérations
– Créer nouveau, ouvrir, sauvegarder, couper, coller, imprimer, formater du texte, quitter, …
Mécanismes d’interface (Interface Utilisateur)– Cliquer, pointer dans le document– Menus déroulants, boutons, accélérateurs de clavier …
Découpler les opérations des mécanismes IU– Effectuer une même opération depuis différents mécanismes – Réutiliser un même mécanisme pour différentes opérations
Opérations sont implémentées dans plusieurs classes ≠– Découpler la connaissance de ces classes de l’IU
Support pour le undo/redo multi-niveaux– Toutes les opérations ne sont pas réversibles
43
Exercice Quel patron de conception suggérez-vous pour
représenter cette structure de document ?
Donner le diagramme de classe correspondant à cette étude de cas et une esquisse du code Java
44
Quel patron de conception ? Création Fabrique abstraite (Abstract
Factory) Monteur (Builder) Fabrique (Factory Method) Prototype (Prototype) Singleton (Singleton)
Structuraux Adaptateur (Adapter) Pont (Bridge) Objet composite (Composite) Décorateur (Decorator) Façade (Facade) Poids-mouche (Flyweight) Proxy (Proxy)
Comportementaux– Chaîne de responsabilité (Chain
of responsibility)– Commande (Command)– Interpréteur (Interpreter)– Itérateur (Iterator)– Médiateur (Mediator)– Mémento (Memento)– Observateur (Observer)– État (State)– Stratégie (Strategy)– Patron de méthode (Template
Method)– Visiteur (Visitor)
45
Structure
Le Patron Command
Intention : Encapsuler une requête dans un objet de façon àpermettre de supporter facilement plusieurs requêtes, dedéfinir des queues de requêtes et de permettre desopérations annuler
46
Un bouton ou menu déroulant est juste un Glyph– mais a des actions command associées aux entrées
utilisateur– Ex: MenuItem extends Glyph, Button extends Glyph, …
On pourrait avoir…PageFwdMenuItem extends MenuItemPageFwdButton extends Button
On pourrait avoir…– Un appel de fonction dans MenuItem
Mais, préférable d’avoir…– Un attribut MenuItem qui est un objet command
Commands
47
Hiérarchie de Command
48
Hiérarchie de Command
public class MenuItem implements Glyph {
public void clicked() {
commande.execute();
}
}
public class PasteCommand
implements Command {
public void execute() {
// do the paste
}
}
public class CopyCommand
implements Command {
public void execute() {
// do the copy
}
}
49
Undo/Redo Historique de commandes
Inverser la dernière commande
Inverser de nouveau
Avancer le marqueur
Refaire
UNDO REDO
50
Undo/Redo Ajouter une méthode unexecute() à Command
– Renverse les effets d’une précédente opération execute()en utilisant toute information undo d’ execute() stockédans l’objet Command
Ajouter une opération pour tester la réversibilitéboolean reversible()
Maintenir un historique des commandes
Un Mémento peut conserver l’état d’une commande, nécessaire pour renverser ses effets
51
7. Vérification d’orthographe et césure de mots Analyse textuelle
– Vérifier les fautes d’orthographe– Introduire les tirets de césure si formatage fin
Supporter des algorithmes multiples
Faciliter l’ajout de nouveaux algorithmes
Faciliter l’ajout de nouvelles analyses textuelles– Recherche d’éléments– Comptage de mots– Vérification grammaticale
Découpler l’analyse textuelle des classes Glyph
52
Quel patron de conception ? Création Fabrique abstraite (Abstract
Factory) Monteur (Builder) Fabrique (Factory Method) Prototype (Prototype) Singleton (Singleton)
Structuraux Adaptateur (Adapter) Pont (Bridge) Objet composite (Composite) Décorateur (Decorator) Façade (Facade) Poids-mouche (Flyweight) Proxy (Proxy)
Comportementaux– Chaîne de responsabilité (Chain
of responsibility)– Commande (Command)– Interpréteur (Interpreter)– Itérateur (Iterator)– Médiateur (Mediator)– Mémento (Memento)– Observateur (Observer)– État (State)– Stratégie (Strategy)– Patron de méthode (Template
Method)– Visiteur (Visitor)
53
Accès à l’information éparse
Examiner le texte caractère par caractère
Le texte à analyser est réparti tout au long de la structure hiérarchique d’objets Glyph
Différentes structures de données au sein des glyphes pour stocker leurs enfants (listes chaînées, tableaux, arbres)
Accès à l’information de différentes manières– Vérification orthographe: avant– Recherche rétrograde : arrière– Évaluation d’expression algébrique : parcours infixe
54
Encapsulation d’accès et de parcours Avant : Un index entier pour identifier position dans tableau
Maintenant : Ne pas privilégier une structure de données particulière
Proposer des accesseurs plus généraux
Problèmes– Ne supporte pas de nouveaux modes traversée sans étendre enum– Si on introduit le mécanisme de traversée dans la hiérarchie Glyph
Solution : encapsuler le concept qui varie, i.e. les mécanismes d’accès et de traversée
Glyph g = ...
for(g.first(PREORDER); !g.done(); g.next()) {
Glyph current = g.getCurrent();
...
}
55
Quel patron de conception ? Création Fabrique abstraite (Abstract
Factory) Monteur (Builder) Fabrique (Factory Method) Prototype (Prototype) Singleton (Singleton)
Structuraux Adaptateur (Adapter) Pont (Bridge) Objet composite (Composite) Décorateur (Decorator) Façade (Facade) Poids-mouche (Flyweight) Proxy (Proxy)
Comportementaux– Chaîne de responsabilité (Chain
of responsibility)– Commande (Command)– Interpréteur (Interpreter)– Itérateur (Iterator)– Médiateur (Mediator)– Mémento (Memento)– Observateur (Observer)– État (State)– Stratégie (Strategy)– Patron de méthode (Template
Method)– Visiteur (Visitor)
56
Intention : Fournit un moyen d’accès séquentiel aux éléments d’un agrégat d’objets, sans mettre à découvert la représentation interne de celui-ci
Le patron Itérateur
57
Applicabilité– Accéder au contenu d’un objet d’un agrégat sans en révéler la
représentation interne– Gérer simultanément plusieurs parcours dans des agrégats d’objets– Offrir une interface uniforme pour les parcours au travers de
diverses structures agrégats
Conséquences+ Flexibilité: les agrégats et les parcours sont indépendants+ Multiples itérateurs et algorithmes de parcours- Charge de communication additionnelle entre l’itérateur et les
agrégats
Le patron Itérateur
58
Le patron Itérateur
59
Utiliser les itérateurs
Initialiser les itérateurs
Les itérateurs
Glyph g;
Iterator<Glyph> i = g.CreateIterator();
for (i.First(); !i.IsDone(); i.Next()) {
Glyph child = i.CurrentItem();
// do something with current child
}
public class Row extends Glyph {
Iterator<Glyph> CreateIterator () {
return new ListIterator<Glyph>(children);
}
60
Implémenter un itérateur complexe
Les itérateurs
void PreorderIterator::First () {
Iterator<Glyph*>* i = _root->CreateIterator();
if (i) {
i->First();
_iterators.RemoveAll();
_iterators.Push(i);
}
} Glyph* PreorderIterator::CurrentItem () const {
return _iterators.Size() > 0 ? _iterators.Top()->CurrentItem() : 0;
}void PreorderIterator::Next () {
Iterator<Glyph*>* i = _iterators.Top()->CurrentItem()->CreateIterator();
i->First();
_iterators.Push(i);
while ( _iterators.Size() > 0 && _iterators.Top()->IsDone() ) {
delete _iterators.Pop();
_iterators.Top()->Next();
}
}
61
Actions pendant la traversée
Maintenant qu’on peut parcourir la structure de glyphes, il faut ajouter les analyses pendant la traversée– Vérification orthographique, césure de mots, etc.
On peut augmenter les itérateurs avec des analyses– Mais ceci réduit leur réutilisation
On peut augmenter les classes Glyph– Mais nécessitera de changer toutes les classes Glyph pour chaque
nouvelle analyse
Solution: Encapsuler l’analyse dans un objet séparé
62
Actions dans les itérateurs
L’itérateur va transporter l’objet analyse pendant la traversé L’objet analyse va accumuler l’état, ex: caractères pour
vérification orthographique
63
Éviter les casts
Comment l’objet analyse peut distinguer différents types de Glyph sans switch statements et casts ?– Ex: éviter
public class SpellingChecker extends … {
public void check(Glyph g) {
if( g instanceof CharacterGlyph ) {
CharacterGlyph cg = (CharacterGlyph)g;
// analyze the character
} else if( g instanceof RowGlyph ) {
rowGlyph rg = (RowGlyph)g;
// prepare to analyze the child glyphs
} else …
}
}
64
Intention : “Représente une opération à effectuer sur les éléments d’une structure d’objet. Le visiteur permet de définir une nouvelle opération sans modifier les classes des éléments sur lesquels il opère.”
Le Patron Visiteur
65
Accepter les visiteurspublic abstract class Glyph {
public abstract void accept(Visitor v);
…
}
public class CharacterGlyph extends Glyph {
public void accept(Visitor v) {
v.visitCharacterGlyph(this);
}
…
}
66
Visiteurs et sous-classespublic abstract class Visitor {
public void visitCharacterGlyph(CharacterGlyph cg);
{ /* do nothing */ }
public abstract void visitRowGlyph(RowGlyph rg);
{ /* do nothing */ }
…
}
public class SpellingVisitor extends Visitor {
public void visitCharacterGlyph(CharacterGlyph cg) {
…
}
}
67
SpellingVisitorpublic class SpellingVisitor extends Visitor {
private Vector misspellings = new Vector();
private String currentWord = “”;
public void visitCharacterGlyph(CharacterGlyph cg) {
char c = cg.getChar();
if( isalpha(c) ) {
currentWord += c;
} else {
if( isMispelled(currentWord) ) {
// add misspelling to list
misspelling.addElement(currentWord);
}
currentWord = “”;
}
}
public Vector getMisspellings {
return misspellings;
}
…
}
68
Utiliser SpellingVisitorPreorderIterator i = new PreorderIterator();
i.setVisitor(new SpellingVisitor());
i.accept(rootGlyph);
Vector misspellings = ((SpellingVisitor)i.getVisistor()).getMisspellings();
public class Iterator {
private Visitor v;
public void accept(Glyph start) {
for(first(); !isDone(); next()) {
currentItem().accept(v);
}
}
…
}
69
aCharacterGlyph(‘a’) anotherCharacterGlyph(‘ _’) aSpellingChecker:SpellingVisitor
Diagramme de séquence
accept(aSpellingChecker)visitCharacterGlyph(this)
getChar()
visitCharacterGlyph(this)
getChar()
accept(aSpellingChecker)
getMisspellings()
isMispelled(currentWord)
70
HyphenationVisitor Visiter les mots, et ensuite insérer des
glyphes de ‘césure discrétionnaire’
71
En résumé Dans la conception de Lexi, nous avons utilisé les 8 patrons suivants:
– Composite• pour représenter la structure physique du document
– Stratégie• pour autoriser plusieurs algorithmes de formatage
– Commande• pour les opérations utilisateurs réversibles
– Itérateur• pour accéder aux structures d’objets et les traverser
– Visiteur• pour permettre un nombre illimité d’analyses possibles, sans compliquer
l’implémentation de la structure du document
72
Conception d'un éditeur WYSIWYG, appelé Lexi
Une représentation d’un document dans cetéditeur occupe une grande zone centralerectangulaire
Le document peut mélanger librement texte et graphiques dans une variété de formats (choix de polices pour le texte et format d’images pour le graphique)
Le document sera entouré des menus déroulants et des ascenseurs de défilements habituels
Étude de cas
73
Étude de cas
1. Structure du document2. Formatage3. Opérations utilisateur 4. Décoration de GUI5. Multiples look & feel6. Multiples systèmes de
fenêtrage7. Vérification d’orthographe
et césure de mots
7 problèmes de conception
74
Dans la conception de Lexi, nous avons vu les patrons de conception suivants:– Composite
• pour représenter la structure physique du document– Stratégie
• pour autoriser plusieurs algorithmes de formatage– Commande
• pour les opérations utilisateurs réversibles– Itérateur
• pour accéder aux structures d’objets et les traverser– Visiteur
• pour permettre un nombre illimité d’analyses possibles, sans compliquer l’implémentation de la structure du document
Résumé
75
4. Décoration de GUI
Ajout d’une bordure autour de la zone d’édition de texte et de barres de défilement
Héritage est une façon de le faire mais – Pas flexible à l’exécution– Mène à une prolifération des classes cf.
BorderedComposition, ScrollableComposition, BorderedScrollableComposition
Contraintes– Les décorations devraient être réutilisables sans ‘sous-
classage’, i.e., afin qu’elles puissent être ajoutéesdynamiquement à l’exécution
– Transparent aux clients
76
Quel patron de conception ? Création Fabrique abstraite (Abstract
Factory) Monteur (Builder) Fabrique (Factory Method) Prototype (Prototype) Singleton (Singleton)
Structuraux Adaptateur (Adapter) Pont (Bridge) Objet composite (Composite) Décorateur (Decorator) Façade (Facade) Poids-mouche (Flyweight) Proxy (Proxy)
Comportementaux– Chaîne de responsabilité (Chain
of responsibility)– Commande (Command)– Interpréteur (Interpreter)– Itérateur (Iterator)– Médiateur (Mediator)– Mémento (Memento)– Observateur (Observer)– État (State)– Stratégie (Strategy)– Patron de méthode (Template
Method)– Visiteur (Visitor)
77
Le Patron Decorator Intention : Ajoute de nouvelles responsabilités à un objet de
manière dynamique (i.e. à l’exécution)
Applicabilité– Pour ajouter et retirer dynamiquement des responsabilités à des objets
individuels sans affecter les autres objets
– Quand l’extension par dérivation est impraticable (Explosion de sous-classes)
78
Solution: Enveloppe transparente
MonoGlyph– Classe abstraite pour les glyphes d’ornementation – Notion de composition d’enfant unique (ou à simple
composant)
L’enveloppe va déléguer les requêtes au composant mais peut– Ajouter un état– Accomplir certaines tâches avant et/ou après délégation
79
Hiérarchie MonoGlyph
drawBorder(Window)
public abstract class MonoGlyph {
Glyph component;
public void draw(Window w) {
component.draw(w);
}
}
public class Frame extends MonoGlyph {
public void draw(Window w) {
// l’ordre peut être important
draw(w);
drawBorder(w);
}
public void drawBorder(Window w){...}
}
80
Nouvelle structure d’objet
81
5. Multiple standards Look-and-FeelBut– Application portable via diverses
librairies d’interface utilisateur (generic, Motif, Swing, PM, Macintosh, Windows, ...)
– Extensible pour des standards d’IHM futures
– Modifier l’IHM de Lexi à l’exécution
Contraintes– Ne pas recoder tous les widgets
existants ou les clients– Changer de look & feel sans
recompiler
82
Quel patron de conception ? Création Fabrique abstraite (Abstract
Factory) Monteur (Builder) Fabrique (Factory Method) Prototype (Prototype) Singleton (Singleton)
Structuraux Adaptateur (Adapter) Pont (Bridge) Objet composite (Composite) Décorateur (Decorator) Façade (Facade) Poids-mouche (Flyweight) Proxy (Proxy)
Comportementaux– Chaîne de responsabilité (Chain
of responsibility)– Commande (Command)– Interpréteur (Interpreter)– Itérateur (Iterator)– Médiateur (Mediator)– Mémento (Memento)– Observateur (Observer)– État (State)– Stratégie (Strategy)– Patron de méthode (Template
Method)– Visiteur (Visitor)
83
Intention : Fournit une interface pour créer des familles d’objets apparentés ou interdépendants sans qu’il soit nécessaire de spécifier leurs classes concrètes
Le Patron Fabrique abstraite
84
Singleton: une fabrique abstraite est souvent un singleton
Patrons reliés
85
Solution: Création abstraite d’objets
2 ensembles de classes glyphes widgets– Abstract
• ScrollBar, Button, …
– Concrete• MotifScrollBar, WinScrollBar, MacScrollBar, MotifButton, …
Au lieu deMotifScrollbar sb = new MotifScrollbar();
UtiliserScrollbar sb = guiFactory.createScrollbar();
où guiFactory est une instance de MotifFactory
86
Structure de la fabrique
public class MotifFactory extendsFactory{
public Scrollbar createScrollBar( ) {
return new MotifScrollbar();
}
}
public class PMFactory extends Factory{
public Scrollbar createScrollBar( ) {
return new PMScrollbar();
}
}
87
Interface Factory
88
Objets produits Une fabrique crée des objets produits
89
Si connu à la compilation (ex: Lexi v1.0 – seul Motif implémenté)GUIFactory guiFactory = new MotifFactory();
Au démarrage (Lexi v2.0)String LandF = appProps.getProperty("Look-and-Feel");GUIFactory guiFactory;if( LandF.equals("Motif") )
guiFactory = new MotifFactory();else if ( LandF.equals(“Presentation_Manager") ) ...
Modifiable par une commande menu (Lexi v3.0)– réinitialise ‘guiFactory’– reconstruit l’IU
Construire la fabrique
90
6. Multiples systèmes de fenêtrage
Nombreux systèmes de fenêtrage assez largement incompatibles : Mac, PM, Windows, X
Minimiser les dépendances entre les systèmes de fenêtrage en application et le code du framework
91
Quel patron de conception ? Création Fabrique abstraite (Abstract
Factory) Monteur (Builder) Fabrique (Factory Method) Prototype (Prototype) Singleton (Singleton)
Structuraux Adaptateur (Adapter) Pont (Bridge) Objet composite (Composite) Décorateur (Decorator) Façade (Facade) Poids-mouche (Flyweight) Proxy (Proxy)
Comportementaux– Chaîne de responsabilité (Chain
of responsibility)– Commande (Command)– Interpréteur (Interpreter)– Itérateur (Iterator)– Médiateur (Mediator)– Mémento (Memento)– Observateur (Observer)– État (State)– Stratégie (Strategy)– Patron de méthode (Template
Method)– Visiteur (Visitor)
92
6. Multiples systèmes de fenêtrage
Peut-on utiliser la fabrique abstraite ? – Chaque librairie GUI définit sa propre hiérarchie de
classes incompatibilité entre systèmes
– Pas possible d’avoir une classe produit abstraite commune ScrollBar, Button, Menu
– Mais, tous ont des principes communs
93
Solution
Comment faire pour que des classes de différentes hiérarchies soient conformes au même type abstrait ?
Utiliser le patron de conception Pont (Bridge)– Définit un ensemble uniforme d’abstraction de fenêtres
(interface commune)– Cache les implémentations individuelles
94
Intention : Découple une abstraction (logique) de son implémentation (physique) afin que les deux éléments puissent être modifiés indépendamment l’un de l’autre
Conséquences : – Découplage de l’interface et de l’implémentation– Les hiérarchies d’abstraction et d’implémentation peuvent être
étendues indépendamment l’une de l’autre– Dissimulation des détails d’implémentation aux clients
Le Patron Pont
95
Solution Commencer avec une hiérarchie de fenêtre
abstraite (ne dépend pas d’une librairie GUI)– Identifier les responsabilités communes d’une fenêtre
• Opérations pour dessiner des formes géométriques de base
• Maximiser/Minimiser• Redimensionner• (Re)dessiner les contenus sur demande (lorsque
restauré, recouvert, caché, etc.)– Deux philosophies possibles (extrêmes)
• Intersection de l’ensemble des fonctionnalités• Union de l’ensemble des fonctionnalités Trouver le juste milieu
96
Responsabilité Opérations
window management virtual void Redraw()virtual void Raise()virtual void Lower()virtual void Maximize()virtual void Minimize()
graphics virtual void DrawLine()virutal void DrawRect()virtual void DrawPolygon()Virtual void DrawText()
Hiérarchie de fenêtre Adopter une approche hybride
97
Hiérarchie de fenêtre
Commencer avec une hiérarchie de fenêtre abstraite (ne dépend pas d’une librairie GUI)
98
Implémentations de fenêtre
Qu’en est-il des implémentations de Window (i.e. des librairies de systèmes de fenêtrage) ?– Définir des classes et sous-classes alternatives de
Window• À la compilation, il faut substituer la classe appropriée
– Sous-classer la hiérarchie de Window
– Ou …
99
Implémentations de fenêtre
Qu’en est-il des implémentations de Window (i.e. des librairies de systèmes de fenêtrage) ?– Ou…
100
void Character::draw (Window &w) {w.drawText(...);
}void Window::drawText (...) {
rep->deviceText(...);}void XWindowRep::deviceText (...) {
XText(...); }
Structure
101
Découplage entre la structure logique du contenu d’une
fenêtre et le rendu physique du contenu dans la fenêtre
Structure objet
102
Glyph
Window WindowImp
XWindowImp
WindowSystemFactory
XWindowSystemFactory
uses
instantiates
uses
Rectangle
imp
uses
Exemple de code
103
Exemple de codepublic class Rectangle extends Glyph {
public void draw(Window w) {
w.drawRect(x0,y0,x1,y1);
}
}
public class Window {
public void drawRect(Coord x0,y0,x1,y1) {
imp.drawRect(x0,y0,x1,y1);
}
}
public class XWindowImp extends WindowImp {
public void drawRect(Coord x0,y0,x1,y1) {
...
XDrawRectangle(display, windowId, graphics, x,y,w,h);
}
}
104
Exemple de code : Abstract Factorypublic abstract class WindowSystemFactory {
public abstract WindowImp createWindowImp();
public abstract ColorImp createColorImp();
}
public class XWindowSystemFactory extends WindowSystemFactory {
public WindowImp createWindowImp() {
return new XWindowImp();
}
}
public class Window {
Window() {
imp = windowSystemFactory.createWindowImp();
}
}
105
Fabrique abstraite: peut créer et constituer un Pont particulier
Adaptateur: est équipé pour permettre à des classes sans lien de parenté de travailler ensemble. Il est généralement appliqué à des systèmes déjà conçus. Le Pont, en revanche, est utilisé lors des prémisses d’une conception pour permettre de modifier indépendamment abstraction et implémentation
Patrons reliés
106
En résumé Dans la conception de Lexi, nous avons utilisé les 8 patrons suivants:
– Composite• pour représenter la structure physique du document
– Stratégie• pour autoriser plusieurs algorithmes de formatage
– Décorateur• pour orner l’interface utilisateur
– Fabrique abstraite• pour offrir plusieurs standards de décor
– Pont• pour supporter plusieurs systèmes de fenêtrage
– Commande• pour les opérations utilisateurs réversibles
– Itérateur• pour accéder aux structures d’objets et les traverser
– Visiteur• pour permettre un nombre illimité d’analyses possibles, sans compliquer
l’implémentation de la structure du document
107
Conception détaillée
1. Introduction2. Patrons GRASP3. Patrons de conception4. Étude de cas5. Anti-patrons
108
Patrons de conception sont de “bonnes” solutions à des problèmes de conception récurrents
Défauts de conception sont de “mauvaises” solutions, mauvaises pratiques de
conception qui mènent à des conséquences négatives
2 catégories:
Défauts de haut niveau : anti-patrons
Défauts de bas niveau : mauvaises odeurs
Défauts de conception
109
Un anti-patron est un type spécial de patron de conception caractérisé par une solution refactorisée
Défauts de conception
110
2 exemples d’anti-patrons Blob (God Class)
“ Procedural-style design leads to one object with a lion’s share of the responsibilities while most otherobjects only hold data or execute simple processes ”
– Conception procédurale en programmationOO
– Large classe contrôleur
– Beaucoup d’attributs et méthodes avec unefaible cohésion*
– Dépend de classes de données* À quel point les méthodes sont étroitement liées aux attributs et aux méthodes de la classe.
Défauts de conception
111
Spaghetti Code“ Ad hoc software structure makes it difficult to extendand optimize code. ”
– Conception procédurale en programmation OO
– Manque de structure : pas d’héritage, pas de réutilisation, pas de polymorphisme
– Noms des classes suggèrent uneprogrammation procédurale
– Longues méthodes sans paramètres avec une faible cohésion
– Utilisation excessive de variables globales
2 exemples d’anti-patrons
Défauts de conception
112
Mauvaises odeurs Longue méthode Large classe Longue liste de paramètres Primitive obsession Groupe de données (Data
clumps) Instructions Switch Champ temporaire Héritage refusé Classes alternatives avec des
interfaces différentes Hiérarchies parallèles d’héritage
Classe paresseuse Classe de données Code dupliqué Généralité spéculative Chaine de messages Middle man Feature envy Intimité inappropriée Divergent change Shotgun surgery Classe de librairie
incomplète Commentaires
113
Code dupliqué– Structure de code dupliqué à différents endroits
Longue méthode– À décomposer pour viser la clarté et facilité de maintenance
Large classe– Classes qui essaient d’en faire trop. Présence de code dupliqué
Longue liste de paramètres– Passer à la méthode juste ce dont elle a besoin
Mauvaises odeurs
114
Divergent Change– Si une classe est modifiée de différentes manières pour différentes raisons,
ça vaut la peine de diviser la classe de sorte que chaque partie soit associée à un type de changement particulier
Shotgun Surgery– Si un type de changement nécessite plusieurs petits changement de code
dans différentes classes, tous ces bouts de code qui sont affectés devraientêtre mis ensemble dans une classe
Feature Envy– Une méthode d’une classe est plus intéressée par les attributs d’une autre
classe que celle de sa propre classe. Peut-être que placer la méthode danscette autre classe serait plus appropriée
Groupe de données– Le même groupe de données se retrouvent ensemble à plusieurs endroits:
champs dans plusieurs classes, paramètres de méthodes, données locales. Peut-être qu’ils devraient être groupés ensemble dans une petite classe
Mauvaises odeurs
115
Primitive Obsession– Parfois, plus intéressant de virer un type de données primitives vers une
classe légère pour le rendre explicite et identifier les opérations à réaliser(ex: créer une classe date plutôt qu’utiliser un couple d’entiers)
Instructions Switch– Tendent à créer de la duplication. Plusieurs instructions switch éparpillées à
différents endroits. Utiliser des classes et du polymorphisme
Hiérarchies parallèles d’héritage– Deux hiérarchies parallèles existent et un changement dans une classe de
la hiérarchie nécessite des changements dans l’autre hiérarchie également
Classe paresseuse– Les classes qui ne font pas assez de travail utile devrait être éliminé
Mauvaises odeurs
116
Généralité spéculative– Code pas nécessaire a été créé pour anticiper les futurs changements du
logiciel, rendant ainsi le logiciel plus complexe
Champ temporaire– Confusion lorsque certaines variables d’une classe sont utilisées seulement
occasionnellement
Chaîne de messages– Une méthode envoie un message à un objet, lequel envoie un message à
un autre objet, et ainsi de suite de sorte que la méthode originale devientcouplée à tous ces objets
Middle Man– La délégation est souvent utile, mais parfois ça peut aller loin. Si une classe
agit comme mandataire, mais ne réalise pas de travail supplémentaire utile, il peut être utile de la supprimer de la hiérarchie
Mauvaises odeurs
117
Intimité inappropriée– Classes qui dépensent trop de temps à fouiller dans les parties privées
d’autres classes.
Classes alternatives avec des interfaces différentes– Classes qui font des choses similaires, mais ont des noms différents,
devraient être modifiées pour partager un protocole commun
Classe de librairie incomplète– Le logiciel utilise une librairie qui n’est pas complète, forçant les
développeurs à étendre la fonctionnalité de la librairie
Classe de données– Classes qui ont juste des champs de données et des méthodes d’accès,
mais pas de réel comportement. Si les données sont publiques, rendez-les privées!
Mauvaises odeurs
118
Héritage refusé– Si une sous-classe ne veut pas ou n’a pas besoin de tout le comportement
de sa base classe, alors peut-être la hiérarchie de classe est fausse
Commentaires– Si les commentaires sont présents dans le code car le code est mauvais,
alors améliorer le code
Mauvaises odeurs