designs patterns comment rendre son code faiblement couplé, et maintenable

Post on 03-Apr-2015

108 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

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