Vous êtes sur la page 1sur 20

08/11/2020

STUPID VS SOLID
Intro aux DP

Un code STUPID Vs SOLID


• deux grands principes de la programmation orientée objet :
STUPID et SOLID.
• Ces deux acronymes représentent respectivement une série
de mauvaises et de bonnes pratiques de développement
orientée objet.
• Savoir identifier rapidement et formellement les indices qui
montrent qu'un code est « STUPID », c'est aussi comprendre
les conséquences nuisibles à la qualité générale de ce
dernier. En revanche, savoir appliquer les principes de SOLID
à son code, c'est faire un premier pas vers un code robuste
et résistant aux changements.

1
08/11/2020

Le principe STUPID
• Acronyme pour :
– Singleton : instances uniques
– Tight Coupling: couplage fort
– Untestability: non testabilité
– Premature Optimizations : optimisations prématurées
– Indescriptive Naming : nommage indéchiffrable
– Duplication : duplications

Singleton
• les singletons sont comparables à des variables globales de
l'application (accessible depuis n'importe où et à n'importe quel
moment dans le code).
• Si l'état d'un singleton est modifiable à tout moment, par
l'intermédiaire de mutateurs (setters) par exemple, alors
n'importe quelle ligne de code de l'application pourrait modifier
cet objet.
• Une autre instruction de l'application exécutée plus tard
recevrait alors un singleton avec un état inattendu, ce qui
pourrait avoir des conséquences nuisibles.
• les singletons introduisent des couplages forts entre les objets

2
08/11/2020

Couplage fort
• Il se traduit par les dépendances qui existent entre
plusieurs modules.

Incapacité à tester le code


• Un code fortement couplé sera difficilement testable, voire intestable
• Il est important de tester unitairement le code afin :
• de garantir qu'il fonctionne
• De prévenir les bogues, cas limites et régressions.
• Un code bien testé est plus robuste aux changements pendant tout son cycle de
vie (développement, maintenance, évolution, déploiement...).
• Les tests unitaires facilitent la vie du développeur et permettent de détecter de
nombreux problèmes en amont, bien avant qu'ils se produisent.
• Pour être testé, le code doit bien sûr être testable. Par conséquent, cela implique
de suivre un certain nombre de bonnes pratiques pour y parvenir. Le principe
SOLID présenté dans la suite de cet article est un moyen efficace pour rendre son
code testable.

3
08/11/2020

Optimisations prématurées
• Optimiser le code trop tôt dans un but de le rendre plus performant ou
parfois plus concis est toujours un effort inutile car le code n’est pas
fini et sa performance peut être acceptable
• les optimisations prématurées du code rendent la lecture et la
compréhension de ce dernier plus difficiles.
• Il est plus sage de sacrifier ces optimisations au profit d'un code clair et
compréhensible.
• Il convient d'optimiser au moment opportun lorsque ce besoin se fait
réellement sentir.

Nommage indéchiffrable
• Un nommage simple et compréhensible du code
• Il fait gagner un temps précieux lorsqu'il s'agit de le relire, le maintenir ou le
faire évoluer.
• C'est l'une des tâches des plus compliquées pour un développeur.
• Savoir nommer correctement une variable, une fonction, une méthode, une
classe ou encore un espace de nommage n'est pas toujours facile.
• La faible maitrise du métier de l'application que l'on développe complique
cette tache.
• Un bon nommage apporte la sémantique au code
• Il fait éviter des commentaires inutiles.
• Eviter l’usage d'abréviations ou d'acronymes dans le code, car pas tout les
développeurs qui connaissent leurs sens.

4
08/11/2020

Duplications
Garder le code KISS (Keep It Simple Stupid) et DRY (Don't Repeat Yourself).
Les duplications de code augmentent le temps de maintenance et les
risques de bogues.
Une modification du code nécessite de répercuter le changement à
plusieurs endroits.
• Des méthodes simples existent pour réduire les duplications du code.
Dans un ensemble de classes, il s'agit par exemple de profiter de
l'héritage ou de la composition ou de Template en isolant les
redondances dans des classes, interfaces et méthodes.

Le principe SOLID
• SOLID est l'acronyme pour les cinq principes suivants :
– Responsabilité unique (Single Responsability Principle),
– Ouvert / fermé (Open Close Principle),
– Substitution de Liskov (Liskov Substitution Principle),
– Ségrégation d'interfaces (Interface Segregation Principle),
– Injection de dépendance (Dependency Injection Principle).

10

10

5
08/11/2020

Responsabilité unique (SRP)

A class should have one, and only one,


reason to change.
Robert C. Martin.
• une classe doit remplir un rôle précis.

11

11

Exemple
<?php
class CsvDataImporter {
public function import($file) { …. }
private function loadFile($file) { …}
private function importData(array $records) {
…}
}
la classe CsvDataImporter realise deux tâches de nature
complètement différente :
– Lire un fichier CSV et transformer les données en tableaux PHP,
– Importer ces enregistrements dans une base de données MySQL.

12

12

6
08/11/2020

• Solx: Décomposer la classe CsvDataImporter en deux classes


CsvFileLoader et DataGateway.
• La nouvelle classe DataImporter doit déléguer ces deux tâches
deux 2 nouvelles classes.

<?php
class DataImporter {
private $loader;
private $gateway;
public function __construct(FileLoader $loader, Gateway
$gateway) { ….}
public function import($file) { … }
}

Avantages : plus facile de :


– tester unitairement chaque objet,
– faire évoluer les implémentations existantes ou d'en ajouter de nouvelles.

13

13

• Pour revenir à notre Diag. de Classe on obtient:

14

14

7
08/11/2020

Ouvert / fermé (OCP)


You should be able to extend a classes behavior, without
modifying it. Robert C. Martin.
• Rendre les modules ouverts à l'extension et fermés aux
modifications.
• Pouvoir enrichir les fonctionnalités d'un module sans avoir à
modifier son comportement.
• Exemple :
– Supporter de nouveaux formats de sérialisation des données
– Supporter de nouveaux adapteurs pour des systèmes de stockage. ècréer de
nouvelles classes Implantant les interfaces sans changer la classe existante.

15

15

$importer = new DataImporter(new


CsvFileLoader(), new MySQLGateway());
$importer = new DataImporter(new
XmlFileLoader(), new MongoGateway());

• L'objet DataImporter n'a pas été modifié.


• On injecte de nouvelles implémentations des
interfaces FileLoader et Gateway
• On peut ainsi utiliser par exemple des données
sérialisées en JSON à insérer dans une base
MongoDB.
• l'implémentation interne de DataImporter est
Inchangé.
16

16

8
08/11/2020

Principe de substitution de Liskov (LSP)


Derived classes must be substitutable for their base classes.
Robert C. Martin.

• Il doit être possible pour un objet de type T acceptant une


dépendance de type S, de pouvoir remplacer cette dernière
par une dépendance d'un type dérivé de S sans impact sur
le fonctionnement du code.

• Il faut toujours conserver les signatures des méthodes


d'une classe parent dans les classes dérivées ainsi que la
nature des valeurs de retour.
17

17

Exemple
<?php
interface UrlGeneratorInterface {
public function generate($name, $parameters = array()); }
interface UrlMatcherInterface {
public function match($pathinfo); }
interface RouterInterface extends UrlMatcherInterface,
UrlGeneratorInterface {
public function getRouteCollection();
}

Avantages:
• Typer un argument uniquement avec l'interface
UrlGeneratorInterface quand une classe a besoin d'appeler
seulement la méthode generate(…) sur cet argument
• Un des avantages à fractionner des interfaces est la testabilité.

18

18

9
08/11/2020

Ségrégation d'interfaces (ISP)


Make fine grained interfaces that are client specific.
Robert C. Martin.

• Identique au principe de responsabilité unique des classes


(SRP),
• une interface doit d'être la plus petite possible et
représenter l'implémentation d'une seule tâche.
• Plus les interfaces sont petites, plus il est facile de tester
leurs implémentations

19

19

20

20

10
08/11/2020

21

21

22

22

11
08/11/2020

23

23

Exemple en php
<?php
interface UrlGeneratorInterface {
public function generate($name, $parameters = array());
}
interface UrlMatcherInterface {
public function match($pathinfo);
}
interface RouterInterface {
public function getRouteCollection();
}

24

24

12
08/11/2020

Injection de dépendance (DIP)

Depend on abstractions, not on concretions.


Robert C. Martin.
« High-level modules should not depend on
low-level modules. Both should depend on
abstractions. Abstractions should not depend
on details. Details should depend on
abstractions ».
• Il faut programmer par rapport à des
abstractions plutôt que des
implémentations. 25

25

26

26

13
08/11/2020

• Exemple de dépendance
<?php
class DataImporter {
private $loader;
private $gateway;
public function __construct() {
$this->loader = new CsvFileLoader();
$this->gateway = new DataGateway();
}
}
Inconvénients:
• la classe DataImporter devient fortement couplée à sa dépendance
CsvFileLoader.
è Impossibilité de remplacer cette dépendance par une autre pour un
besoin ultérieur.
• Empêche de tester unitairement la classe DataImporter puisque les
dépendances ne peuvent être remplacées par des doublures (« mocks
»).

27

27

• Inversion de dependance:
<?php
class DataImporter {
private $loader;
private $gateway;
public function __construct(FileLoader $loader, Gateway $gateway) {
$this->loader = $loader;
$this->gateway = $gateway; }
}

28

28

14
08/11/2020

Les Design Patterns

29

29

Introduction au DP
• L'utilisation actuelle vient des travaux de l'architecte
Christopher Alexander
• Il a étudié les manières d'améliorer le processus de
conception de bâtiments et des zones urbaines
“Chaque patron est une règle en 3 parties, qui exprime une relation entre un certain
contexte, un problème et une solution.”
• La définition habituelle d'un patron est :
“Une solution à un problème dans un contexte.”
• Les patrons peuvent être utilisés dans de nombreux
domaines différents, y compris le développement logiciel.

30

30

15
08/11/2020

Pourquoi le DP?
"Concevoir un logiciel orienté-objet est difficile, et concevoir
un logiciel orienté-objet réutilisable est encore plus difficile. »
Erich Gamma
• Les concepteurs expérimentés réutilise des solutions qui ont
fonctionné dans le passé
• Les systèmes orientés-objet bien structurés suivent des
patrons récurrents pour les classes et objets
• Les patrons qui ont fonctionné dans le passé permettent
d'être plus productif.
• Les conceptions qui en résultent sont plus flexibles et
réutilisables.
31

31

Etre Expert en Dev Logiciel


1- Apprendre les règles : les algorithmes, les structures de
données, UML, les langages de programmation, ...

2- Apprendre les principes : la programmation structurée, la


conception UML, la POO, les P. géneriques, ….

3- Etudier la conception d'autres Expert approuvés : Ces


conceptions contiennent des patrons qui doivent être compris,
mémorisés, et appliqués de manière répétée.

NB. Il y a des centaines de patrons

32

32

16
08/11/2020

Historique des DP
• Cunningham et Beck utilisent les idées d'Alexander pour
développer un petit langage de patrons pour Smalltalk 1990 –
• Le Gang des 4 (« Gang of Four » : Gamma, Helm, Johnson and
Vlissides) commence à travailler à la compilation d'un catalogue
de patrons de conceptions
• Bruce Anderson donne le premier workshop de Patrons au
OOPSLA
• Kent Beck et Grady Booch sponsorisent la première réunion de
ce qui est maintenant connu comme le groupe Hillside
• Le Gang des 4 (GoF) publie le livre des Patrons de conception

33

33

DP GoF
• Le premier livre sur les patrons de conceptions était :
‘Design Patterns Elements of Reuse’
par Erich Gamma, Richard Helm, Ralph Johnson, et John Vlissides’
Les patrons de conception sont :
« Descriptions d'objets et de classes communicantes qui sont
adaptées à la résolution d'un problème général de conception
dans un contexte particulier » Chaque patron de conception
décrit un ensemble d'objets et de classes communicants.

34

34

17
08/11/2020

• Ils ont défini 23 patrons de conception fondamentaux


• Les patrons sont regroupés en 3 catégories :
– Patrons de création : liés au processus de la création d'objets. Ils
aident à créer des objets, au lieu d’avoir à instancier les objets
directement.
– Patrons de structure : Concernent la composition de classes et
d'objets. Ils aident à composer des groupes d’objets en des structures
plus larges,
• Exemple: interfaces utilisateur complexes.
– Patrons de comportement : Concernent l'interaction des classes et
des objets. Ils aident à définir la communication entre les objets du
système et à définir comment le flux est contrôlé.
35

35

Portée d’un DP

• Portée de Classe
– Focalisation sur les relations entre classes et
leurs sous-classes
– Réutilisation par héritage

• Portée d’Instance
– Focalisation sur les relations entre les objets
– Réutilisation par composition
36

36

18
08/11/2020

37

37

Description des Patterns


Chaque Pattern est décrit par:
• Nom du pattern : utilisé pour décrire le pattern, ses solutions et les
conséquences en un mot ou deux
• Problème : description des conditions d ’applications. Explication du
problème et de son contexte
• Solution : description des éléments (objets, relations, responsabilités,
collaboration) Permettant de concevoir la solution au problème ;
utilisation de diagrammes de classes, de séquences, ... vision statique
ET dynamique de la solution
• Conséquences: description des résultats (effets induits) de l’application
du pattern sur le système (effets positifs ET négatifs)

38

38

19
08/11/2020

Caractéristiques d’un Pattern


• Simple mais difficile à imaginer
• Indépendant des langages: Solution abstraite, et de haut
niveau
• Souvent orienté vers le bon découpage en packages
(modularité, flexibilité, réutilisabilité) Exprimé sous forme
d’architecture reliant quelques classes très abstraites
• Repose beaucoup sur des interfaces
• Basé plus sur la composition que sur l’héritage
• Repose souvent sur l’encapsulation de ce qui vari

39

39

Comment devenir un Pattern ?


– Être présent dans au moins 3 très gros projets très largement utilisés
– Se retrouver dans des programmes écrits dans des langages objets différents
(c++, Eiffel, Smalltalk, Java, c#, O’CAML...)
– Ne pas être décomposable en patterns plus simples
– Être documenté complètement

• Seuls les 23 patterns initiaux ont franchi ce seuil, en 10


ans..

40

40

20

Vous aimerez peut-être aussi