Designs Patternscomment rendre son code faiblement couplé,
et maintenable...
Pourquoi réinventer la roue, alors que nos douleurs quotidiennes ont été étudiées par d’autres avant nous ?
Par masochisme ? Par sadisme ?
Constat :
Hormis les algorithmes métier,les difficultés de l’ingénierie de code sont souvent identiques !
Les solutions mises en œuvres sont (trop) souvent dépendante de l’imagination du développeur…
Une solution : Les Designs Patterns !
Ce sont un ensemble de recettes permettant de résoudre les principaux problèmes liés à l’ingénierie de code,
Objectif :Garder un code ouvert au changement, mais fermé aux
modifications,
Fondements des DP
GOF (Gang of four)N’est pas le groupe de musique post-punk des années 70…Mais plutôt les 4 créateurs à l’origine des DP !
« Chaque patron décrit un problème qui se manifeste constamment dans notre environnement, et donc décrit le cœur de la solution à ce problème, d’une façon telle que l’on puisse réutiliser cette solution des millions de fois, sans jamais le faire deux fois de la même manière »
23 patterns de « base »
Quel que soit le langage, ou la technologie objet !
Tous les autres sont des dérivés... (MVVM, ...)
3 Types
Création (Creational Patterns)Singleton, Factory, Abstract Factory, Prototype
Structural (Structural Patterns)Adapter, Facade, Proxy,...
Comportements (Behavioral Patterns)Strategy, Chain of responsability, Iterator, Observer, ...
Formalisme
Entrons dans le vif du sujet
Le pattern Sssssssss
Etape 3L’année suivante, le client désire ajouter une évolution : les canards savent voler...
Nom : Sssssssss
Type : Comportement
But : Encapsuler les comportements susceptible de changer, afin de les rendre interchangeables. Exercice :
Etape 1Un client désire une FPS de canards...Un canard a un nom, peut nager, cancaner et doit être affiché.Etape 2Lors de la release de la version, le client note que tout les canards nagent et cancanent de la même manière... c’est MAL !.
Bug ! les canards en plastique qui étaient dans l’application (des leurres en quelque sorte) se mettent à voler...
Nous avons donc un problème de conception !
Quelles solutions d’après vous pourraient apporter implémentation pérenne, en d’autres termes :
Disposer d’une application fermée aux modifications mais ouverte aux changements ?
Héritage ?Interfaces ?
Reprenons de la hauteur !Quel est le réel problème ?
Que proposez vous comme solutions ?
LE CHANGEMENT !
Nom : Sssssssss
Type : Comportement
But : Encapsuler les comportements susceptible de changer, afin de les rendre interchangeables.
LA VRAIE question porte donc sur ce qui change :Quels sont les différences entre les différents canards ?
réponse : leur comportement... (vol, cancan, affichage)
Nom : Sssssssss
Type : Comportement
But : Encapsuler les comportements susceptible de changer, afin de les rendre interchangeables.
Nom : Stratégie (Strategy)Type : Comportement
But : Encapsuler les comportements susceptible de changer, afin de les rendre interchangeables.
Cancan
etc.
Nom : Stratégie (Strategy)Type : Comportement
But : Encapsuler les comportements susceptible de changer, afin de les rendre interchangeables.
Exemple de stratégie
Nom : Stratégie (Strategy)Type : Comportement
But : Encapsuler les comportements susceptible de changer, afin de les rendre interchangeables.
Exemple de Contexte
Nom : Stratégie (Strategy)Type : Comportement
But : Encapsuler les comportements susceptible de changer, afin de les rendre interchangeables.
Exemples réels :Une application de paiement en ligne peut offrir différents moyens de paiements, il suffit de choisit la bonne stratégie en fonction du choix du client. Car hormis le mode de paiement, la suite du flux de commande demeure identique...
En .net, la classe ArrayList (contexte) est une bon exemple. La méthode sort par défaut offre une implémentation (stratégie concrète) par défaut. Cette méthode peut être substituée par l’implémentation fournie à l’exécution (implémentation de l’interface IComparer - stratégie)...
Privilégier le couplage faible favorise l’évolution...
Il est préférable
d’implémenter des
interfaces !
Retour sur les brèves de comptoir ...
L’héritage est un concept
qui s’applique au modèle
métier (le plus souvent).
Encapsuler ce qui change est un gage d’évolution !
Un code doit être ouvert au changement, mais
fermé aux modifications...
La composition est
préférable à l’héritage !
Nom : Stratégie (Strategy)Type : Comportement
But : Encapsuler les comportements susceptible de changer, afin de les rendre interchangeables.
Le pattern Aaaaaaa
Nom : Aaaaaaa
Type : Structural
But : Permettre à deux instances de classes d'interagir entre elles, sans modification de structure.
Reprenons notre SuperCanard...
Un jour, notre client favoris rachète un produit concurrent : Super Dindes.
Il vient nous voir, car il désire créer une édition spéciale :
Dindes VS Canards
Nom : Aaaaaaa
Type : Structural
But : Permettre à deux instances de classes d'interagir entre elles, sans modification de structure.
Reprenons notre précédent projet...
Quelle était le sujet de Super Canards ?
Quelles étaient les contraintes ?
Quelle solution(s) avons nous apporté ?
?
Nom : Aaaaaaa
Type : Structural
But : Permettre à deux instances de classes d'interagir entre elles, sans modification de structure. Petit rappel...
La classe Duck, et les strategies de comportement...
Nom : Aaaaaaa
Type : Structural
But : Permettre à deux instances de classes d'interagir entre elles, sans modification de structure. Petit rappel...
La classe Duck, et les strategies de comportement...
Privilégier le couplage faible favorise l’évolution...
Nom : Aaaaaaa
Type : Structural
But : Permettre à deux instances de classes d'interagir entre elles, sans modification de structure.
Il est préférable
d’implémenter des
interfaces !
Retour sur les brèves de comptoir ...
L’héritage est un concept
qui s’applique au modèle
métier (le plus souvent).
Encapsuler ce qui change est un gage d’évolution !
Un code doit être ouvert au changement, mais
fermé aux modifications...
La composition est
préférable à l’héritage !
Nom : Aaaaaaa
Type : Structural
But : Permettre à deux instances de classes d'interagir entre elles, sans modification de structure.
Quelles solutions pourraient apporter une solution simple, rapide... et
maintenable ?
VS
Nom : Aaaaaaa
Type : Structural
But : Permettre à deux instances de classes d'interagir entre elles, sans modification de structure.
Cela jacasse dur autour de ce concept !
Mais en termes d’implémentation cela donne quoi ?
Nom : Adaptateur (Adapter)Type : Structural
But : Permettre à deux instances de classes d'interagir entre elles, sans modification de structure.
IHM gérant exclusivement des
canards...
Interface de canards...
Adaptateur canards-dinde Dinde
Nom : Aaaaaaa
Type : Structural
But : Permettre à deux instances de classes d'interagir entre elles, sans modification de structure.
Revenons à nos mouton...ou plutot à nos canards, et dindes...
En sachant ce que vous savez, quelle serait l’application du pattern Adapter ?
Nom : Adaptateur (Adapter)Type : Structural
But : Permettre à deux instances de classes d'interagir entre elles, sans modification de structure.
Solution = 3 adaptateurs :
- Adaptateur de comportement de nage,- Adaptateur de comportement Quack,- Adaptateur permettant de transformer une dinde en canard
Nom : Adaptateur (Adapter)Type : Structural
But : Permettre à deux instances de classes d'interagir entre elles, sans modification de structure.
Il est donc nécessaire d’adapter notre dinde aux concepts manipulés...
(comportements)(ceci est nécessaire pour adapter la dinde à l’implémentation
existante)Adaptateur pour passer d’un comportement lié à la classe au pattern stratégie
Interface Dinde - Duck différente... A l’initialisation,
fournir à l’adaptateur l’objet adapté !
Nom : Adaptateur (Adapter)Type : Structural
But : Permettre à deux instances de classes d'interagir entre elles, sans modification de structure.
Il est donc nécessaire d’adapter notre dinde aux concepts manipulés... (duck)
(ceci est nécessaire pour adapter la dinde à l’implémentation existante)
Nom : Adaptateur (Adapter)Type : Structural
But : Permettre à deux instances de classes d'interagir entre elles, sans modification de structure.
Utilisation...
12 3
Attention : un canard
peut masquer une dinde...
Nom : Adaptateur (Adapter)Type : Structural
But : Permettre à deux instances de classes d'interagir entre elles, sans modification de structure.
Un oeil dans le code ? une démo ?
Nom : Adaptateur (Adapter)Type : Structural
But : Permettre à deux instances de classes d'interagir entre elles, sans modification de structure.... et dans la vraie vie... le concret du
réel... pouvez vous me donner des exemples
decette implémentation ...?Adaptateur .net - COM,
Adaptateur entre dll third party et main app,Fonctionnement des add ons,
Hors informatique ? des adaptateurs de prise UK - FR, les réducteurs de wc pour enfants, les réducteur pour dock d’ipod etc.
Privilégier le couplage faible favorise l’évolution...
Nom : Adaptateur (Adapter)Type : Structural
But : Permettre à deux instances de classes d'interagir entre elles, sans modification de structure.
Il est préférable
d’implémenter des
interfaces !
Retour sur les brèves de comptoir ...
L’héritage est un concept
qui s’applique au modèle
métier (le plus souvent).
Encapsuler ce qui change est un gage d’évolution !
Un code doit être ouvert au changement, mais
fermé aux modifications...La composition est
préférable à l’héritage !
Ce n’est ni à la classe métier, ni au contexte à
devoir s’adapter...
Le pattern eeeeeeee
Nom : EeeeeeeeType : Creational
But : Centraliser l’instanciation d’objets.
Et où est le problème ?
Techniquement, nulle part... mais en ce qui concerne la gestion du
changementil s’agit d’une autre affaire !
Jusque là, pour instancier des objets nous placions des new là où nous en avions besoin...
Nom : EeeeeeeeType : Creational
But : Centraliser l’instanciation d’objets.En implémentant des interfaces, nous isolons le code des changements qui peuvent se
produire en aval.
En s’appuyant sur une interface, le code client continuera de fonctionner lors du
remplacement d’une classe, et ce par polymorphisme.
Le couplage est donc faible.
Nom : EeeeeeeeType : Creational
But : Centraliser l’instanciation d’objets.
En codant nos classes sans interface, il est nécessaire de « réouvrir » le code aux
modifications pour prendre en compte à chaque changement de classe.
Nom : EeeeeeeeType : Creational
But : Centraliser l’instanciation d’objets.
Comment éviter le coté obscure ?
Identifier ce qui changeet
L’externaliser !
souvenez vous des patterns stratégie et adapteur...
PS : Cette règle vaut pour tous les patterns...
Nom : EeeeeeeeType : Creational
But : Centraliser l’instanciation d’objets.
Bonjour Messieurs,J’ai l’honneur de vous annoncer que vous avez été sélectionnés pour la réalisation de notre application de gestion de pizzérias.Félicitations !Luigi Del Gusto
Nom : EeeeeeeeType : Creational
But : Centraliser l’instanciation d’objets.
En tant pour bon concepteur, comment aller vous mettre en
oeuvre cette application de pizza ?
Nom : EeeeeeeeType : Creational
But : Centraliser l’instanciation d’objets.
Pour fêter les transhumances, Luigi désire ajouter à la carte des spécialités régionnales : - pizza raclette, - pizza reblochonne, - pizza au gorgonzola
J’en ai l’eau à la bouche !
Evolution :
Nom : EeeeeeeeType : Creational
But : Centraliser l’instanciation d’objets.
Luigi revient nous voir, il a monté des pizzerias dans les quatre coin de France et Navarre.
Il désire maintenant s’exporter...
Or les pizza allemande portent le même nom que les françaises, seul la composition peut varier...Le processus de fonctionnement des pizzerias demeure le même...
Scoop : Une nouvelle évolution pointe le bout de son nez :
Nom : EeeeeeeeType : Creational
But : Centraliser l’instanciation d’objets.
Qu’allez vous mettre en place pour permettre d’étendre l’application, tout en gardant le code fermé au maximum ?
Nom : Fabrique (Factory)Type : Creational
But : Centraliser l’instanciation d’objets.
La solution : La notion de fabrique et le pattern « fabrique abstraite »
Nom : Fabrique simple (Factory)Type : Creational
App pizzeria
Pizza napolitaine
Pizza 4 froms
4 fromsFR
4 fromsDE
Fabrique pizza
fabrique Fr fabrique DE
NapoFR
NapoDE
Contrat : Interface ou classe abstraite (italique)
Contrat : Interface ou classe abstraite (italique)
Implémentation
de la fabrique
Implémentationdes pizzas sur base des contrats
Nom : Fabrique (Factory)Type : Creational
Une dernière notion : le client consomme la «bonne fabrique abstraite» via une méthode «
fabrique »
consomme
Un oeil dans le code ? une démo ?
Nom : Fabrique (Factory)Type : Creational
Pourquoi favoriser l’utilisation des principes de fabrique et fabrique abstraite ?
Nom : Fabrique (Factory)Type : Creational
Les constructeurs sont assez limités dans leur processus de création : ils retourne une instance de xxx.
Pour permettre une plus grande évolutivité, les fabriques permettent de découpler les logiques d'interactions, de l’implémentation...
Ce qui permet de masquer l’implémentation au consommateur de classes...
Pourquoi favoriser l’utilisation des principes de fabrique et fabrique abstraite ?
Nom : Fabrique (Factory)Type : Creational
Régulièrement, nous sommes confrontés à des incertitudes du client. Les choix permettant de levés ces incertitudes peuvent être repoussés à plus loin, sans pour autant bloquer le développement des applications.
Exemple : Ado.net permet de masquer, et de paramétrer l’implémentation utilisée via les chaines de connexions.Pour ce faire, nous pouvons utiliser l’espace de nom Db : DbConnection, DbCommand, DbDataAdapter
Pourquoi favoriser l’utilisation des principes de fabrique et fabrique abstraite ?
Nom : Fabrique (Factory)Type : Creational
Les constructeurs ne laissent pas toujours deviner de leurs intentions réelles. Imaginons une classe, avec de multiples constructeurs :
public Vehicle (int passengers)public Vehicle (int passengers, int horsePower)public Vehicle (int wheels, bool trailer)public Vehicle (string type)
Pourquoi favoriser l’utilisation des principes de fabrique et fabrique abstraite ?
Nom : Fabrique (Factory)Type : Creational
La factory clarifie rapidement l’intention du développeur
public Vehicle CreateCar (int passengers)public Vehicle CreateSuv (int passengers, int horsePower)public Vehicle CreateTruck (int wheels, bool trailer)public Vehicle CreateBoat ()public Vehicle CreateBike ()
Pourquoi favoriser l’utilisation des principes de fabrique et fabrique abstraite ?
Nom : Fabrique (Factory)Type : Creational
Vous verrez que derrière le terme de fabrique, nous retrouvons souvent à la fois des fabriques abstraites et des méthodes de fabriques.En .net, les méthodes fabriques sont surtypées par Factory.
Privilégier le couplage faible favorise l’évolution...
Il est préférable
d’implémenter des
interfaces !
Retour sur les brèves de comptoir ...
Les interfaces sont des
contrats remplis par
certaines instances, et
consommés par d’autres
Encapsuler ce qui change est un gage d’évolution !
Un code doit être ouvert au changement, mais
fermé aux modifications...
Les composants applicatifs consomment les instances, mais ne sont pas responsables de leur instanciation
Nom : Fabrique (Factory)Type : Creational
Centraliser les créations d’instances favorise la
dissociation entre modèle et comportement.
Le « new » n’est pas si anodin que cela !
Top Related