Présentations
Équipe pédagogique
- Adrien Krähenbühl
- CMx + Groupe 34 de TDs + Groupe 3 de TPs
- Ludovic Christmann
- Groupe TDs/TPs 12
- Romain Orhand
- Groupe TP 4
- Romain Perrin
- Groupe TDs/TPs 56
Séances
- 3 CMx \(\rightarrow\) 1 \(\times\) 2h + (2 ou 3) \(\times\) 1h
- 6 TDs
- 7 TPs classiques jusqu’octobre
- 7 TPs pour réaliser un projet sur novembre/décembre
Détail des séances
Contenu
- Principes de conception
- Patrons du “Gang of Four”
- GRASP et SOLID
- Swing
![]()
Note : Le contenu est construit sur la base du PPN 2013 (page 46).
Répartition
1\(^{ère}\) séquence : CM 2h + 2 TDs + 3 TPs
2\(^{ème}\) séquence : CM 1h + 2 TDs + 2 TPs
3\(^{ème}\) séquence : CM 1h + 2 TDs + 2 TPs
4\(^{ème}\) séquence : TP x 7
Évaluation du module
Trois notes
- 1 QCM
- Avant les vacances de la Toussaint.
- 1 TP noté
- 1\(^{ère}\) semaine de novembre.
- 1 projet en binôme
- 7 séances de TP dédiées après les vacances de la Toussaint.
Calcul de votre moyenne
Note finale = (0.25 \(\times\) QCM) + (0.35 \(\times\) TP noté) + (0.4 \(\times\) projet)
Qu’est-ce qu’un patron de conception ?
Un patron de conception (design pattern) est une solution éprouvée à un problème concret et récurrent de programmation.
Les patrons :
- sont représentés par des diagrammes de classes
- évitent de ré-inventer le roue
… mais :
- doivent être utilisés dans des cas bien identifiés
- ne sont pas la solution à tous les problèmes
Qu’est-ce qu’un principe de conception ?
Un principe de conception est un principe général permettant de prendre de bonnes décisions, qui n’est pas spécifique à un problème.
« Le meilleur outil de conception pour le développement de logiciels est un esprit bien éduqué sur les principes de conception. Ce n’est pas UML ou toute autre technologie. » Craig Larman, 2005.
Il en existe beaucoup :
GRASP - SOLID - KISS - DRY - YAGNI - La loi de Demeter - …
Attention, un principe N’EST PAS un patron.
Historique
- Origine en architecture en 1977
- “A pattern language: Towns, Buildings, Construction”
C. Alexander et al.
- Récupération en IHM (Interaction design) en 1986…
- “User Centered System Design”, D. Norman & S. Draper
- … puis en informatique
- 1987 : 1er projet de conception mettant en oeuvre des patrons de conception par K. Beck & W. Cunningham chez Tektronix
- 1991 : “Design Patterns: Elements of Reusable Object-Oriented Software” par le Gang Of Four : E. Gamma, R. Helm, R. Johnson & J. Vlissides
\(\rightarrow\) Référence de la COO
Les principes de conception
Le principe KISS
KISS (Keep It Simple, Stupid) signifie “Restez simple, stupide”.
Principe :
- Toujours choisir la simplicité
- Éviter autant que possible la complexité
En POO, cela consiste notamment à privilégier plusieurs classes ou fonctions simples à une classe ou fonction complexe.
Le principe DRY
DRY (Don’t Repeat Yourself) signifie “Ne vous répétez pas”.
Principe :
- La duplication c’est le mal
- Mutualisez ce qui est mutualisable
public int somme( int a, int b ) {
return a+b;
}
public double somme( double a, double b ) {
return a+b;
}
\(\rightarrow\)
public <T> T somme( T a, T b ) {
return a+b;
}
La généricité est un exemple d’application du principe DRY.
Le principe YAGNI
YAGNI (You ain’t gonna need it) signifie
“Vous n’en aurez pas besoin”.
Ne codez que des choses utiles maintenant, le reste est une perte de temps qui peut être source de bugs.
public class MaClasse {
private Integer _value;
// Constructeur inutile
public MaClasse() {
_value = 3;
}
public MaClasse( Integer value ) {
_value = value;
}
}
\(\rightarrow\)
public class MonAppli {
public static void main( String args ) {
MaClasse obj = new MaClasse(5);
}
}
La “Loi de Demeter”
La loi de Demeter peut se résumer par
“Ne communiquez qu’avec vos voisins immédiats”.
public class Belote {
private List<Player> _players;
public void nextRound() {
for ( Player player : players ) {
Integer randomIndex = ...
Card cardToPlay =
player.getCards().remove(randomIndex);
...
}
}
}
public class Player {
private List<Card> cards;
public List<Card> getCards() { return cards; }
}
public class Card { ... }
\(\rightarrow\)
public class Belote {
private List<Player> players;
public void nextRound() {
for ( Player player : players ) {
Card cardToPlay = player.takeNextCard();
...
}
}
}
public class Player {
private List<Card> cards;
public Card takeNextCard() {
Integer randomIndex = ...
Card cardToPlay = cards.remove(randomIndex);
}
}
public class Card { ... }
… et les “groupes” de principes
Ils ont été présentés en A22, il s’agit de :
- GRASP
- proposés par Craig Larman
- gestion de l’assignation des responsabilités
et :
- SOLID
- proposés par Robert C. Martin
- couvrent l’assignation des responsabilités et l’héritage
Nous y reviendrons plus tard.
Objectifs et description
Rappel : Un patron de conception est une solution éprouvée à un problème concret et récurrent de programmation.
- Objectifs
- L’objectif est d’obtenir un code MAINTENABLE et RÉUTILISABLE
- Les design pattern résultent de l’expérience de nombreux développeurs
- Fiche de description
- un nom
- une description du problème à résoudre
- une description de la solution \(\rightarrow\) le DP
- les conséquences et/ou implications issus de la solution
Trois types de patrons
- Les patrons de création
- décrivent comment instancier les classes, c’est-à-dire comment créer et configurer des objets.
- Les patrons de structure
- décrivent comment structurer les classes afin d’avoir un minimum de dépendances entre l’implémentation et l’utilisation.
- Les patrons de comportement
- décrivent une structure de classes permettant de faire collaborer des objets efficacement.
Quelques
patrons de création
1. Singleton
- Problème
- Comment permettre à une classe de n’avoir qu’une et une seule instance quelle que soit son utilisation ?
Solution
La classe interdit aux autres classes de la construire et gère elle-même son unique instance.
Utilisation (java)
Singleton instance = new Singleton(); // ERREUR DE COMPILATION
Singleton uniqueInstance = Singleton.getInstance(); // OK
2. Factory method - le problème
- Problème
- Plusieurs classes concrètes héritent de la même classe abstraite. Comment faire pour qu’une classe externe puisse instancier des objets de chacune des classes concrètes sans dépendance ?
2. Factory method - la solution
- Solution
- Créer une classe dédiée à la fabrication des classes concrètes.
- Conséquences
- Une classe externe ne dépendra que de la classe abstraite et de la fabrique quel que soit le nombre de classes concrètes.
- Ajouter une nouvelle classe concrète implique de créer une nouvelle fonction dans la fabrique.
Quelques
patrons de comportement
1. Template method - le problème
- Problème
- Comment mutualiser du code partiellement redondant lorsqu’une structure algorithmique similaire se dégage ?
1. Template method - La solution
AlgoTemplate basic = new BasicAlgo();
basic.execute(); // convertFromArray + exchangeSort
AlgoTemplate funny = new FunyAlgo();
funny.execute(); // convertFromGraph + bubbleSort
- Solution
- Créer une classe avec une méthode qui réalise l’algorithme commun en appellant des méthodes abstraites redéfinies dans ses sous-classes.
1. Template method - Les conséquences
- Modifier l’algorithme commun ne nécessite que de modifier la classe
Template
.
- Ajouter une nouvelle variante ne nécessite que de coder les méthodes abstraites de la classe
Template
.
- Une méthode identiques à plusieurs variantes peut devenir une méthode concrète de la classe
Template
, redéfinie dans les variantes où elle diffère (loadElements
dans l’exemple).
2. Strategy - le problème
- Problème
- Comment permettre à un client de choisir dynamiquement le comportement d’une méthode selon un contexte donné ?
2. Strategy - la solution
- Solution
Définir un contexte :
- qui possède une stratégie modifiable,
- qui utilise la dernière stratégie sélectionnée lorsqu’on l’utilise.
2. Strategy - les conséquences
- Conséquences
- Le choix de la stratégie et son exécution son découplées
- Pas besoin de modifier le contexte lorsqu’on ajoute une nouvelle stratégie
- L’ajout d’une nouvelle stratégie n’implique aucune modification de son exécution
Exemple avec les stratégies de tri
3. Observer - le problème
- Problème
- Comment permettre à des objets de réagir au comportement d’autres objets tout en limitant les dépendances et la redondance du code ?
3. Observer - la solution
AnObjectObserver observerOne = new ReactiveObject();
AnObjectObserver observerTwo = new AnotherReactiveObject();
AnObject anObject = new AnObject();
anObject.addObserver(observerOne);
anObject.addObserver(observerTwo);
anObject.doSomething();
- Solution
- Créer une interface pour les observateurs
- Faire gérer une liste d’observateurs par la classe observable
- Notifier tous les observateurs lorsque nécessaire
3. Observer - les conséquences
- Il est possible d’ajouter (ou supprimer) dynamiquement des observateur à l’objet observable
- La méthode
notifyObservers()
peut être appelée à n’importe quel moment de n’importe quelle méthode de la classe observable.
- Une classe qui souhaite observer les objets observables doit simplement implémenter l’interface
Observer
. Le code de l’objet observable ne sera pas modifié.