3.2. Voyage au pays des Patterns
Pour bien appr hender l'int r t des Patterns, le mieux est de r fl chir
la conception d'une application et de voir petit petit quels besoins ou
probl mes apparaissent. Pour
r pondre chaque besoin, nous
essaierons de piocher un Pattern standard de notre biblioth que: celle
constitu e des 23 Patterns du GOF (GOF signifie Gang Of Four, soit la
bande des quatre auteurs qui ont crit
le livre phare mentionn
pr c demment).
L'application "cas d' cole" que nous avons choisie est un syst me de
gestion d'articles et de news. Nous nous proposons d'en concevoir
la fois le processus de publication et celui de lecture et de navigation
travers les articles. L'objectif n'est absolument pas d' tre exhaustif ou
tr s pr cis concernant les aspects fonctionnels de ce syst me, mais bel
et bien d'introduire progressivement les Design Patterns.
3.2.1. Cahier des charges
Les besoins fonctionnels de notre application sont extr mement
simples: il s'agit pour les auteurs d'articles ou de news d' tre capables
de r diger leurs crits (cette partie n'est pas int grer dans le syst me),
puis de les publier. Si d'aventure plusieurs auteurs tentaient de publier le
m me jour, un m canisme de gestion des priorit s devrait choisir
l' l ment publier et mettre les autres en attente d'une date de
publication ult rieure.
D'autre part, tant pour les auteurs que pour leurs lecteurs, il doit tre
possible de faire des recherches simples parmi tous ces articles et de lire
ceux qui les int ressent.
Afin d' viter les mauvaises surprises, un m canisme de tol rance aux
pannes devra tre mis en Suvre. Il peut s'agir d'une sauvegarde
p riodique, condition que la d perdition de performances ne se fasse
pas sentir lorsque cette sauvegarde s'ex cute.
Enfin, au cas o d'autres outils seraient utilis s l'avenir pour g rer les
articles et news, le syst me doit disposer d'un m canisme d'export dans
Design Patterns
32 / 257
un format neutre (un document XML semble tout indiqu ).
3.2.2. Conception initiale
Afin d' tre brefs sur cette partie, nous allons faire une grosse entorse
au processus habituel de recueil des besoins, d'identification des cas
d'utilisation, de d couverte des objets m tier, d'analyse statique et
dynamique... en esp rant que les experts de ces tapes (tels que Pascal
Roques, cf Bibliographie) ne nous en voudront pas trop.
Supposons donc que nous ayons mod lis les objets m tier la va-vite
et que nous soyons arriv s au r sultat suivant.
Livrable
-date:DateTime
-titre:string
-auteur:string
-sujet:string
-etat:int
+Publier(datePublication:DateTime):void
+Afficher():void
+Imprimer():void
+SoumettreAPublication():void
+ExporterEnXML():void
+Sauvegarder():void
Catalogue
*
+Rechercher(titre:string):Livrable
+Ajouter(nouveau:Livrable):void
+ExporterEnXML():void
+Sauvegarder():void
+Rechercher(auteur:string):Livrable[]
Article
-urlContenu:string
+SoumettreARelecture():void
+ExporterEnXML():void
+Sauvegarder():void
News
+ExporterEnXML():void
+Sauvegarder():void
Figure 6. Conception initiale
Il est certain que ces quatre classes vont r pondre aux besoins
Design Patterns
33 / 257
exprim s dans le cahier des charges. Mais cette conception est-elle
satisfaisante pour autant? Si l'on adopte le point de vue du concepteur
Objet, la r ponse est n gative, et ce pour de nombreuses raisons.
Prenons tout d'abord nos sacro-saints principes de conception:
"
"
"
"
"
Les objets m tier portent des responsabilit s techniques. Par
exemple, le Livrable impl mente les services Afficher(), Imprimer(),
Sauvegarder(), ExporterEnXML(), ce qui ne r pond pas au crit re de
l'Inversion des D pendances.
Un corollaire du point pr c dent est que toutes les m thodes de la
classe Livrable (il en va de m me pour les autres classes, en r alit )
ne visent pas le m me objectif. Certaines sont l pour r pondre des
besoins de sauvegarde, d'autres aux besoins fonctionnels de
l'application... On sent entre elles une faible coh sion.
Ces m mes services techniques peuvent tre amen s voluer. Le
format d'export XML en particulier est susceptible de changer avec le
temps et avec les besoins d'int gration aux applications connexes. Or
si l'impl mentation de ce service est du ressort du Livrable, nous ne
pourrons pas faire voluer le format XML sans toucher au code de
cette classe. En cons quence, le crit re de l'Ouvert-Ferm n'est pas
respect non plus.
Pour reformuler le point pr c dent, il existe un couplage fort entre
le format d'export XML et les classes Livrable, Article et News.
En fait, le seul principe qui soit satisfait dans notre conception est
celui de la substitution de Liskov, car les Articles et les News sont
bien des livrables dans le domaine mod lis , et chaque cas
d'utilisation d'un Livrable garde tout son sens si on l'applique un
Article ou une News.
Ce n'est pas tout. D'autres critiques de conception peuvent tre
formul es du point de vue de la maintenabilit ou de l' volutivit :
"
"
La gestion de l' tat du Livrable n'est pas claire; elle sera certes
explicit e dans le code mais elle restera compl tement opaque du
point de vue de la conception.
Il n'y a aucun d couplage entre les processus m tier,
les
l'affichage ou l'impression des
interactions avec l'utilisateur et
Design Patterns
34 / 257
Livrables. Le cycle de vie de ces diff rentes parties du logiciel est
donc vou tre le m me, alors que ce n'est pas forc ment le cas
dans le domaine m tier mod lis ; il est m me probable que la charte
graphique volue, ou que le processus de s lection de la date de
publication d'un article change, alors que les objets m tier Livrables,
Article et News, ont peu de chances de changer aussi vite.
"
Il semble difficile de garder la trace de l'historique du d roulement
des publications, et donc de faire des statistiques qui permettraient
ventuellement d'am liorer leur processus.
Forts de toutes ces critiques, nous allons essayer d'am liorer la
conception de ce petit syst me en appliquant progressivement les Design
Patterns.
3.2.3. Diff rencier le contexte
Attardons-nous sur la publication d'un nouveau Livrable. Si aucune
publication n'est planifi e, le processus est tr s simple: il suffit de rendre
ce nouveau Livrable disponible dans la liste des publications, tous les
lecteurs pourront en prendre connaissance imm diatement. Si par contre
au moins une publication est d j planifi e, il faut mettre le nouveau
livrable en attente de la disponibilit d'une date.
serions
tent s de g rer
Intuitivement, nous
le contexte dans
l'impl mentation de la m thode Ajouter(nouveau:Livrable) de la
classe Catalogue. Mais tout changement fonctionnel aurait un impact
sur
la
responsabilit d'ajouter un livrable un autre objet que le Catalogue, un
objet qui pourrait tre diff rent selon qu'une publication est ou non en
attente.
Il vaudrait donc mieux d l guer
cette impl mentation.
Advertisement
Design Patterns
35 / 257
Catalogue
+Ajouter(nouveau:Livrable):void
+
etat
EtatCatalogue
+Ajouter(nouveau:Livrable):void
RienAPublier
PublicationPlanifiee
+Ajouter(nouveau:Livrable):void
+Ajouter(nouveau:Livrable):void
Figure 7. tat
On appelle ce Pattern tat car on d l gue la nouvelle classe
EtatCatalogue la responsabilit de g rer le comportement du Catalogue
dans un tat donn . Chaque tat sp cifique est en r alit g r par une
classe fille d'EtatCatalogue (nous n'avons ici que deux tats diff rents:
RienAPublier et PublicationPlanifieee), ce qui fait que chaque classe
n'a qu'un objectif, et qu'un changement fonctionnel tel que l'ajout de
nouveaux cas particuliers pourra se faire en ajoutant de nouvelles
classes filles d'EtatCatalogue.
La m thode Ajouter(nouveau:Livrable) du Catalogue ne fait plus que
d l guer la m thode Ajouter(nouveau:Livrable) de l' tat courant. Et
c'est bien l que tout se joue: selon le type r el de l' tat courant, le
comportement sera diff rent gr ce au polymorphisme.
il
Bien s r, le diagramme de classes ne repr sente que la partie statique
du Pattern;
transitions, qui
correspondent simplement au "changement d' tat", c'est- -dire
l'affectation au Catalogue d'une r f rence vers le nouvel tat. Cette
affectation est souvent effectu e l'initiative des tats eux-m mes, qui
faut galement
impl menter
les
Design Patterns
36 / 257
l'on fait porter la responsabilit de conna tre (ou de choisir) l' tat
suivant.
Outre l' volutivit , ce Pattern permet d'impl menter la perfection les
diagrammes d' tats-transition UML et d'avoir une bijection, donc une
tra abilit parfaite, entre le nombre d' tats dans les diagrammes et le
nombre de classes de conception.
3.2.4. Comment choisir la prochaine
publication?
Finissons-en avec le processus de publication: vous vous tes
certainement dit que le choix de la prochaine publication pouvait se faire
de diverses mani res (la premi re soumise est la premi re publi e, ou
les Articles avant les News, ou une alternance savante entre Articles et
News...). Or celle pour laquelle nous allons opter aujourd'hui pourrait
bien ne pas convenir, auquel cas il faudrait en changer demain.
Il
faut donc trouver une technique l gante pour fixer un choix
aujourd'hui et tre capable d'en changer demain sans qu'il n'y ait
d'impact sur le reste de l'application. La solution ressemble au Pattern
pr c dent et tire elle-aussi profit de la d l gation:
Design Patterns
37 / 257
PublicationPlanifiee
StrategiePlanification
+
strategie
+Ajouter(nouveau:Livrable):void
+Ajouter(nouveau:Livrable):void
FIFO
Pondere
+Ajouter(nouveau:Livrable):void
+Ajouter(nouveau:Livrable):void
ArticlesPrioritaires
+Ajouter(nouveau:Livrable):void
Figure 8. Strat gie
Strat gie et tat
se ressemblent donc norm ment dans
leur
conception. La s mantique, elle, est bien diff rente car si la strat gie est
choisie par param trage de l'application ou par le biais d'une interface
utilisateur, les tats quant eux voluent en autonomie au cours du
fonctionnement de l'application.
3.2.5. Comment exporter les Livrables dans un
format neutre?
Dans notre conception initiale, nous avons choisi d'ajouter la m thode
ExporterEnXML() chaque objet m tier,
leur faisant ainsi porter la
responsabilit de "s'exporter eux-m mes" dans ce format. En effet, qui
mieux que l'objet Article pourrait savoir qu'il faut exporter l'attribut
urlContenu sous forme d'une balise <UrlContenu> par exemple?
Mais critiquons ce choix. D'une part, il donne aux objets m tier une
responsabilit technique et l'inversion des d pendances nous rappelle
recommandable. D'autre part,
qu'une telle conception n'est pas
imaginons que le format du document XML d'export change (son sch ma
Design Patterns
38 / 257
volue): nous risquons alors d'avoir apporter des modifications dans le
code de plusieurs objets m tier, au pire dans tous! C'est inacceptable.
De plus, cette approche ne permet d'avoir qu'un seul format d'export. En
supporter plusieurs requerrait d'ajouter autant de m thodes techniques,
sur tous les objets m tier, que de formats diff rents (binaire, CSV, un
autre sch ma XML...).
Pour toutes ces raisons, nous ne pouvons pas nous contenter de cette
conception "brouillon". Pour rationaliser, il faudrait rassembler dans une
nouvelle classe les sp cificit s du format d'export, tout en conservant la
possibilit de choisir dynamiquement parmi plusieurs formats en fonction
des besoins. Cerise sur le g teau, il faudrait que les objets m tier soient
le moins coupl possible ce m canisme d'exportation, de m me
l'algorithme d'exportation la structure des objets en m moire, en
particulier leur organisation (en liste, en arborescence...). Que
pensez-vous de cette nouvelle conception:
Catalogue
Livrable
+Accueillir(v:IVisiteur):void
*
+Accueillir(v:IVisiteur):void
Article
News
+Accueillir(v:IVisiteur):void
+Accueillir(v:IVisiteur):void
<< interface >>
IVisiteur
+Visiter(a:Article):void
+Visiter(n:News):void
+Visiter(c:Catalogue):void
ExportXMLVisiteur
+Visiter(a:Article):void
+Visiter(n:News):void
+Visiter(c:Catalogue):void
Figure 9. Visiteur
Vous l'aurez compris, la seule chose que l'on demande aux objets
Design Patterns
39 / 257
m tier est "d'accueillir" un Visiteur et de le faire progresser sur
l'ensemble des objets d pendants: par exemple, le Catalogue invoquera
la m thode Visiter(this) sur le Visiteur, puis bouclera sur les livrables
dont il a la charge pour que le Visiteur ait l'occasion de tous les
parcourir.
Nous avons ainsi d coupl les objets m tier de la technique d'export,
ce qui nous permet d'imaginer autant de formats diff rents que cela est
n cessaire. Chaque format donnera lieu une nouvelle impl mentation
du IVisiteur.
3.2.6. Parcourir les livrables soi-m me
Le Visiteur que nous avons mis en Suvre pr c demment n'est pas le
seul devoir parcourir le graphe des objets m tier. Certains algorithmes
auront eux aussi ce besoin, mais tous ne pourront pas devenir des
visiteurs, soit parce qu'ils voudront parcourir le graphe de diverses
mani res (parcourir les news d'abord, les articles ensuite, ou encore un
parcours de livrables tri s ou filtr s selon certains crit res), soit parce
qu'ils souhaiteront piloter le parcours au lieu de se laisser guider par le
graphe d'objet lui-m me.
Dans ce cas, il faudrait que les classes clientes des objets m tier (les
algorithmes qui utilisent ces objets) aient un acc s en lecture toutes
les propri t s mono- ou multi-valu es. Or prenons l'exemple du
Catalogue: s'il donnait ses client la visibilit directe de sa collection de
Livrables, rien n'emp cherait ceux-ci d'ajouter ou de supprimer des
Advertisement
Livrables sans que le Catalogue ne puisse exercer de contr le! Nous
venons de briser l'encapsulation.
l'It rateur.
Pour contourner ce probl me tout en permettant aux clients d'arpenter
librement le mod le objet, il existe deux Design Patterns: le D corateur
et
le
comportement nominal d'un objet, mais nous allons l'utiliser ici dans un
mode d grad : lorsqu'un client souhaitera parcourir la collection des
Livrables,
fournira bel et bien un objet de type
Collection, mais dont seules les op rations de lecture seront autoris es.
le Catalogue lui
normalement
d'enrichir
premier
permet
Le
Design Patterns
40 / 257
Catalogue
+
Livrables
<< interface >>
Collection
contient
Livrable
*
+Ajouter(obj:object):void
+Supprimer(obj:object):void
+Lire(indice:int):object
Delegue
CollectionLectureSeule
+Ajouter(obj:object):void
+Supprimer(obj:object):void
+Lire(indice:int):object
Ajouter et Supprimer
lancent une exception
l'ex cution
Figure 10. D corateur
Cela peut para tre satisfaisant, mais en r alit , nos principes de
conception ne sont pas tous satisfaits. En particulier, notre d corateur
ne r pond pas au principe de substitution de Liskov puisque
l'utilisation d'une CollectionLectureSeule en lieu et place d'une Collection
n'est pas neutre et ne peut pas tre trait e sans pr caution
suppl mentaire: l'utilisateur typique d'une Collection ne sera pas pr t
rattraper les exceptions que l verait une CollectionLectureSeule! En
d corant ainsi la Collection, nous avons donc rompu le contrat qui la
lie ses utilisateurs (celui de r pondre aux services Ajouter() et
Supprimer() sans lever d'exception). D'un autre cot , cette solution est
tr s simple mettre en Suvre et sa consommation en ressources
suppl mentaires est n gligeable; elle ne requiert pas, par exemple, de
dupliquer la Collection que les clients souhaitent parcourir.
Dans le cas o l'on souhaite maximiser la robustesse ou faire varier le
mode de parcours d'un client travers le graphe d'objets m tier, notre
second Pattern est plus adapt : l'It rateur. A l'image de ce que
proposent la plupart des biblioth ques d'acc s aux donn es avec la
notion de Curseur, l'It rateur est un objet d di un seul client la fois
et qui permet de parcourir en lecture seule une collection d'objets. Outre
le fait qu'il simplifie le parcours travers une structure de donn es,
Design Patterns
41 / 257
l'It rateur est galement un excellent outil de d couplage entre la
l'arpente. En effet, quelle que
collection d'objet parcourus et celui qui
soit l'organisation interne des objets, on utilise un It rateur toujours de
la m me mani re.
L'It rateur, quant lui, doit avoir une relation privil gi e avec la
collection dont il facilite la travers e. Or l'organisation des objets peut
varier en fonction des types de collections (listes cha n es, listes bas es
sur des tableaux, arborescences tri es...), donc il est n cessaire de
disposer d'un type d'it rateur par type de collection parcourue.
Enfin, toujours pour masquer l'impl mentation l'utilisateur, il faut faire
porter la Collection d'objets elle-m me la responsabilit de cr er le bon
type d'It rateur (en fonction de sa structure de donn es interne). On dit
que la Collection se comporte comme une Fabrique (ou qu'elle porte
une m thode de fabrication).
Collection
+CreerIterateur():Iterateur
<< interface >>
Iterateur
+Avancer():void
+GetElementCourant():Livrable
+GetParcoursTermine():boolean
CollectionIterateur
+CollectionIterateur(aParcourir:Collection):
+Avancer():void
+GetElementCourant():Livrable
+IsParcoursTermine():boolean
Figure 11. It rateur
A noter que l'It rateur que nous avons mod lis est tr s ancr dans le
mod le des objets m tier et qu'il ne pourrait pas tre r utilis dans
d'autres situations. Cette contrainte a amen les concepteurs des
.NET, par exemple, proposer des It rateurs
frameworks Java et
g n riques qui parcourent et
"Object".
renvoient n'importe quel
L'avantage induit est bien videmment la souplesse, qui se paie par une
Design Patterns
42 / 257
diminution de la robustesse de l'application car on peut se tromper lors
du transtypage des objets parcourus et le compilateur n'est d'aucune
aide puisque pour lui, l'It rateur peut se promener sur n'importe quel
Object. Cette g ne n'existe pas en C++ o les Templates permettent
d'impl menter des It rateurs param tr s par le type d'objets qu'ils
parcourent; et fort heureusement, les langages Java 1.5 et C# 2.0 nous
proposent un quivalent aux Templates, les Generics.
"It rateurs modifiables". Ceux-ci
D'autre part, on trouve galement dans certains frameworks des
It rateurs "am lior s" qui permettent de supprimer l'objet courant lors
d'une travers e de structure de donn es. Appelons ce type d'It rateurs
des
tr s pratiques
compar s aux autres techniques de modification des Collections au gr
d'un parcours. Mais mieux y r fl chir, si nous renvoyons un It rateur
modifiable un utilisateur de nos classes, par exemple un utilisateur
du Catalogue, rien ne l'emp cherait de parcourir les Livrables et d'en
supprimer certains sans que le Catalogue ne puisse effectuer le moindre
contr le. Ce qui revient nouveau briser l'encapsulation: il est
quasiment aussi grave de renvoyer un It rateur modifiable qu'une
r f rence sur la Collection d'objets elle-m me.
s'av rent
3.2.7. Interactions avec le syst me
Avoir mod lis et con u les objets m tier d'un syst me est satisfaisant
car on peut d s lors crire du code qui se lit comme de la bonne prose;
du moins, il parle une personne du domaine que la syntaxe d'un
langage de programmation ne fait pas fuir... Mais si l'on n'y prend garde,
solliciter un mod le objet directement am ne souvent un probl me de
tra abilit . En effet,
(d'une couche de
pr sentation par exemple) pouvait invoquer les m thodes des objets
m tier, non seulement nous aurions de nombreuses d pendances mais il
deviendrait surtout tr s difficile de dire quel besoin m tier correspond
chaque invocation ou quelle motivation de l'utilisateur final cette
invocation se rattache.
si n'importe quel objet
Afin de rationaliser l'interaction entre la couche de pr sentation et la
les architectures "multi-couches" nous
couche d'objets m tier ,
recommandent d'ins rer un interm diaire, souvent appel couche de
Design Patterns
43 / 257
services, qui expose un ensemble de Fa ades fonctionnelles. Comme
dans la vie courante, une Fa ade offre un point d'acc s simplifi un
ensemble de services et permet par l -m me de limiter le couplage entre
deux couches logiques successives. Une autre mani re de le dire: la
fa ade masque les d tails dont les utilisateurs ne doivent pas tre
d pendants.
Dans notre exemple,
les utilisateurs finaux souhaitent g rer
les
publications ainsi que les th mes qui les regroupent. Une seule Fa ade
Advertisement
de GestionDesPublications devrait suffire rassembler les principaux
services du syst me; elle devient d s lors un point d'entr e obligatoire
pour les utilisateurs (un contr leur, souvent proche des cas d'utilisation
d termin s en analyse).
GestionDesPublications
+AjouterTheme(theme:string):void
+PublierArticle(theme:string,titre:string,auteur:string,text:string,urlContenu:string):void
+PublierNews(theme:string,titre:string,auteur:string,text:string):void
Figure 12. Fa ade
Comme nous pouvons le constater, la Fa ade est tr s simple utiliser
puisqu'elle se charge de tout:
"
"
La cr ation des objets n cessaires. La Fa ade peut s'appuyer sur
la
une
abstraite)
responsabilit d'instancier les objets concrets.
( ventuellement
d l guer
Fabrique
pour
L'initialisation compl mentaire de ces objets. Certains objets
n'offrent qu'un constructeur sommaire (ou leur fabrique n'offre
qu'une m thode acceptant peu de param tres); il s'agit donc
d'affecter les propri t s qui n'ont pas pu l' tre par le biais de ce
constructeur.
"
L'invocation de m thodes, dans un ordre compatible avec les
workflows applicatifs et m tier.
La Fa ade GestionDesPublications est une classe sans attribut. Ses
il serait
instances sont donc sans tat,
indistincts. Dans ce cas,
Design Patterns
44 / 257
dommage d'en cr er plusieurs puisque chacune de ces instances est
parfaitement identique sa petite sSur.
Pour viter ce g chis, il convient d'interdire la cr ation tout va
d'instances de GestionDesPublications. Comment? En rendant son
constructeur inaccessible aux clients ext rieurs (rendons-le priv par
exemple). Mais de ce fait, il devient n cessaire d'offrir un autre point
d'entr e la GestionDesPublications, qui ne n cessite pas de l'instancier
au pr alable: seule une m thode statique peut faire l'affaire. Et donc
la
sans
GestionDesPublications (la premi re fois qu'on l'invoque), soit de
r cup rer une r f rence cette instance devenue unique (les fois
suivantes).
cette m thode va permettre soit d'instancier
surprise,
Cette gymnastique de l'esprit, qui part du besoin de partager des
informations ou d'optimiser l'occupation m moire par l'interdiction de
cr er plusieurs instances, et qui aboutit une classe l'instance unique
accessible par le biais d'une m thode statique porte un nom: le Design
Pattern Singleton. Dans la phrase pr c dente, on comprend comment
les Patterns permettent d' lever le niveau du langage et de limiter les
ambigu t s entre interlocuteurs avertis.
-instance:GestionDesPublications
GestionDesPublications
<< create >>-GestionDesPublications():
+GetInstance():GestionDesPublications
+AjouterTheme(theme:string):void
+PublierArticle(theme:string,titre:string,auteur:string,text:string,urlContenu:string):void
+PublierNews(theme:string,titre:string,auteur:string,text:string):void
Figure 13. Singleton
3.2.8. Am lioration de la tra abilit
Introduire une Fa ade a certes simplifi l'acc s aux fonctionnalit s
essentielles de notre syst me, mais cela n'a pas am lior la tra abilit ni
la gestion de l'historique des interactions entre l'utilisateur final et le
Design Patterns
45 / 257
syst me. Mais nous sommes pr s du but: puisque nous ne pouvons
il
cataloguer que des objets, et non des invocations de m thodes,
faudrait
classe
chaque
GestionDesPublications soit r ifi e en objet, c'est- -dire qu'il nous
faudrait instancier un objet pour rendre compte de chaque invocation
des m thodes AjouterTh me(), PublierArticle() et PublierNews().
simplement
sollicitation
que
de
la
Afin de banaliser la gestion de toutes ces interactions, nous allons nous
efforcer de respecter le m me contrat dans chacune de ces nouvelles
classes de conception. Typiquement, elles offriront toutes une m thode
Execute() qui permettra de d clencher l'invocation du service associ .
Seules varieront
les
informations sp cifiques n cessaires l'ex cution de chaque commande
(les "Setters"), ainsi que les m thodes de r cup ration des r sultats
ventuels (les "Getters"). Cette mani re de faire s'appelle le Pattern
Commande:
les m thodes qui permettront de fournir
<< interface >>
Commande
+Execute():void
PublierArticleCmd
PublierNewsCmd
AjouterThemeCmd
-auteur:string
-sujet:string
-titre:string
-urlContenu:string
+Execute():void
-sujet:string
-auteur:string
-titre:string
+Execute():void
-sujet:string
+Execute():void
Figure 14. Commande
La Commande pr sente l'avantage de simplifier la tra abilit entre les
besoins des utilisateurs finaux et leur impl mentation dans le syst me.
Mais tout de m me, quelle lourdeur pour arriver quelque chose qui ne
semble pas tr s loign de la simple Fa ade pr c dente!
Design Patterns
46 / 257
Non, en r alit , la valeur ajout e de la Commande sur la Fa ade est
ailleurs. Chaque invocation de service est maintenant un objet en
m moire, et il en d coule de nombreuses (bonnes) propri t s:
"
"
"
"
"
Il est maintenant possible de cr er un historique de tous les
services sollicit s par les utilisateurs finaux.
En cas de probl me majeur, il sera donc toujours possible de
rejouer les derni res commandes d'un utilisateur pour remettre
le syst me dans un tat coh rent.
Certains domaines peuvent
tirer parti de la connaissance des
op rations d clench es par un client. La gestion de la relation client
en particulier est friande de ce type de renseignement. De m me
pour la gestion de la navigation des utilisateurs travers un site
Web.
nous
Comme
disposons
de
commandes, il devient possible de d faire ce que les commandes
ont fait, dans le sens inverse, puis ventuellement de rejouer les
commandes annul es.
chronologique
historique
d'un
soit
par un interm diaire
Les commandes seront ex cut es soit par celui qui en fait la
Advertisement
demande,
appellerons
l'ordonnanceur de commandes. Ce dernier peut tout fait g rer
une notion de priorit entre commandes, traiter certaines de mani re
asynchrone ou m me d l guer l'ex cution de certaines commandes
d'autres nSuds de traitement du syst me (d'autres serveurs, dans le
cas d'un cluster par exemple).
que nous
Remarque: ce Pattern a t pouss l'extr me dans l'approche par
Pr valence. Suivant les pr ceptes de Bertrand Meyer, les outils comme
Prevayler et Bamboo.NET vont jusqu' distinguer les commandes qui ont
un effet sur l' tat du syst me et celles qui ne font que le consulter.
Seules les premi res sont enregistr es dans un journal de commandes
(typiquement sur disque dur, par s rialisation), ce qui permet, associ
un m canisme de persistance p riodique des objets m tier, d'obtenir un
syst me compl tement fiable, persistant, orient objet... sans utiliser la
moindre base de donn es. Une initiative tr s
int ressante et
prometteuse...
Design Patterns
47 / 257
3.2.9. G rer les v nements applicatifs
Imaginons que les administrateurs du syst me de publication
leur
souhaitent avoir sous les yeux un tableau de bord graphique qui
permette de prendre connaissance en temps r el de l' tat des demandes
de publications de nouveaux Articles.
La premi re technique que l'on peut mettre en Suvre est simple: il
suffit de scruter le Catalogue de Livrables et de r agir en d clenchant
une alarme d s que l' tat d'un Livrable change. Mais pour cela, il faudrait
avoir fait une copie de l' tat de chaque objet et comparer cet tat
"pr c dent" avec l' tat "courant" de chaque objet lors de la scrutation
p riodique. C'est envisageable si le nombre d'objets scruter n'est pas
tr s important ou si la fr quence de scrutation est faible.
Dans le cas contraire, il serait plus judicieux d'inverser la d pendance.
Apr s tout, celui qui para t le plus m me de savoir quand change l' tat
d'un Livrable, c'est bien le Livrable lui-m me. Il suffit donc de faire en
sorte que ce dernier puisse informer, notifier les objets int ress s qu'il
est en train de changer d' tat. Pour cela, le Livrable doit offrir aux objets
ext rieurs un moyen de s'abonner aupr s de lui et de se d sabonner
ult rieurement. Inversement, chaque objet ext rieur doit convenir avec
le Livrable de la m thode d clencher pour notifier son changement
d' tat. Ce m canisme d'Abonnement-Publication, que l'on aper oit
galement dans les Middleware Orient s Message, porte le nom de
"Pattern Observateur-Observable".
<< interface >>
ObservateurDeLivrable
*
+Notification(l:Livrable):void
Livrable
+Abonnement(obs:ObservateurDeLivrable):void
+Desabonnement(obs:ObservateurDeLivrable):void
InterfaceGraphiqueAdministrateur
+Notification(l:Livrable):void
Figure 15. Observateur - Observable
Design Patterns
48 / 257
La m me remarque d j formul e au sujet de l'It rateur s'applique
nouveau ici: notre Observateur est ancr dans le mod le m tier du
syst me de publication puisqu'il ne peut tre notifi que des
modifications de l' tat d'un Livrable. La g n ricit permet de g n raliser
ce Pattern tout en conservant un typage fort.
D'autre part, en particulier si l'on transpose l'Observateur-Observable
dans une architecture distribu e, une question revient souvent: vaut-il
mieux passer syst matiquement l'objet dont l' tat change en param tre
ou se limiter sa r f rence, son identifiant? M me s'il est difficile de
trancher dans le cas g n ral, la premi re solution est souvent choisie:
"
"
Elle n'implique que n invocations de m thodes distance (autant
que d'observateurs), alors que la seconde technique en implique
jusqu' 2*n voire m me davantage (tous les Observateurs risquent
d'invoquer une m thode sur l'Observable pour prendre connaissance
de la modification qui a eu lieu, et ventuellement pour r cup rer le
nouvel tat de l'objet).
Elle garantit
la coh rence des notifications. Dans la seconde
approche,
les Observateurs reviennent vers l'Observable pour
r cup rer les informations compl mentaires; or ce dernier risque
d'avoir encore chang d' tat entre temps! Un tat interm diaire peut
ainsi ne jamais tre port la connaissance de certains
Observateurs.
3.2.10.Am liorer les performances du syst me
syst me
La plupart des Design Patterns que nous avons abord s apportent
notre
de
maintenabilit . Mais rares sont ceux qui visent une am lioration des
performances. Terminons notre voyage dans le monde des Patterns avec
quelques consid rations sur ce th me.
d' volutivit
souplesse,
parfois
plus
de
et
Dans un langage Objets, deux l ments techniques sont
tr s
consommateurs de temps: il s'agit de la construction et de la destruction
des objets. Si nous pouvions trouver une technique pour les limiter au
strict minimum, nous gagnerions certainement un temps consid rable.
Remarque: le Singleton allait d j dans ce sens, mais il ne s'applique
Design Patterns
49 / 257
pas au cas g n ral des classes instanci es de nombreuses fois.
Prenons l'exemple des Articles et des News dans notre application. De
nombreuses instances de chacune de ces deux classes seront cr es au
cours de l'ex cution de l'application, mais si nous utilisons un m canisme
de sauvegarde, il ne sera pas n cessaire de conserver constamment tous
ces objets en m moire. Donc certains objets, une fois sauvegard s, ne
nous seront plus utiles et nous pourrons ainsi les lib rer.
Au lieu de cr er et de "jeter" nos objets apr s usage, ce qui donnera en
Java et en .NET un gros travail au Ramasse-Miettes, nous ferions mieux
de les recycler. Cette solution, plus cologique, est galement plus
efficace puisqu'il ne sera plus n cessaire d'allouer et de d sallouer autant
d'espaces m moire qu'auparavant, ni de d fragmenter la m moire aussi
souvent. Mais qui doit d cider de cr er, recycler ou d truire les objets?
Sur quels crit res?
Pour tre certain de g rer ce probl me de mani re coh rente, il faut
affecter la responsabilit de g rer tout le cycle de vie des Articles
la m me classe, que nous appellerons FabriqueArticles. A travers notre
application, d s que l'on aura besoin de cr er un nouvel Article, il faudra
s'adresser elle. De m me, apr s en avoir termin avec un Article, il
faudra veiller "le lui rendre", de telle sorte que le recyclage puisse avoir
lieu.
FabriqueArticles
+creerArticle():void
+detruireArticle(a:Article):void
*
+
articlesDisponibles
Article
+Recycler():void
Figure 16. Fabrique et Pool d'objets
Design Patterns
50 / 257
De son c t ,
la fabrique g re une collection d'Articles disponibles
(c'est- -dire existant en m moire mais qui ne sont plus utilis s par
personne). Lorsqu'une classe cliente lui demande de cr er un nouvel
Article:
"
"
Si elle dispose d'Articles disponibles, elle en prend un, le recycle et
le renvoie l'appelant.
Dans le cas contraire, elle peut prendre la d cision d'instancier un
nouvel Article, mais comme il est probable qu'on lui demande d'en
cr er encore un nouveau tr s peu de temps apr s, elle peut tr s bien
prendre l'initiative d'instancier plusieurs Articles d'u...