5 principes de POO
Un module doit avoir une seule responsabilité. Une seule raison de changer.
class User {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
getFullName() {
return `<h1>Fullname: ${this.firstName} ${this.lastName}</h1>`;
}
}
Un module doit avoir une seule responsabilité. Une seule raison de changer.
class User {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
getFullName() {
return this.firstName + " " + this.lastName;
}
}
function displayFullName(fullName) {
return `<h1>Fullname: ${fullName}</h1>`;
}
const user = new User("Toby", "Fox");
displayFullName(user.fullName());
Un module doit être ouvert aux extensions,
mais fermé aux modifications.
Possibilité d'étendre sans devoir modifier
class Square {
constructor(size) {
this.type = "square";
this.size = size;
}
}
class Circle {
constructor(radius) {
this.type = "circle";
this.radius;
}
}
function sumAreas(shapes) {
const areas = shapes.map(shape => {
switch (shape.type) {
case "circle":
return shape.radius * shape.radius * Math.PI;
case "square":
return shape.size * shape.size;
default:
throw new Error("Unknown shape");
}
});
return areas.reduce((sum, area) => sum + area, 0);
}
class Square {
constructor(size) {
this.type = "square";
this.size = size;
}
area() {
return this.size * this.size;
}
}
class Circle {
constructor(radius) {
this.type = "circle";
this.radius;
}
area() {
return this.radius * this.radius * Math.PI;
}
}
function sumAreas(shapes) {
const areas = shapes.map(shape => shape.area());
return areas.reduce((sum, area) => sum + area, 0);
}
(sympa le nom...)
Si deux classes réalise la même interface, on peut utiliser l'une ou l'autre sans casser le programme.
Si ça casse, alors elles ne devraient pas partager la même interface.
L'abstraction est incorrecte
class Rectangle {
setHeight(height) {
this.height = height;
}
setWidth(width) {
this.width = width;
}
}
class Square extends Rectangle {
setHeight(height) {
// Uh oh... :S
// Que faire ?
}
}
// Interface pour des formes géométrique,
// imposée par une librairie
interface Shape {
area()
volume()
}
class Square {
area() {
this.size * this.size;
}
// En trop généralisant, on force le client
// à faire des choses incorrectes
volume() {
// ? throw error ?
}
}
Ne pas forcer le code client à implémenter une interface dont il n'a pas usage.
Les modules de haut niveau ne doivent pas dépendre des détails des modules de bas niveau.
Ils doivent dépendre d'abstractions que les modules de bas-niveau doivent satisfaire
// Déplace la voiture un peu en avant
function avancerUnPeu(voiture) {
voiture.tourneClef();
voiture.enleveFreinAMain();
voiture.appuieAccelerateur();
voiture.freine();
voiture.metFreinAMain();
voiture.tourneClef();
}
class VehiculeVoiture {
constructor(voiture) {
this.voiture = voiture;
}
allumer() {
this.voiture.tourneClef();
this.voiture.enleveFreinAMain();
}
avancer() {
this.voiture.appuieAccelerateur();
}
arreter() {
this.voiture.freine();
}
eteindre() {
this.voiture.metFreinAMain();
this.voiture.tourneClef();
}
}
// Déplace un véhicule un peu en avant
function avancerUnPeu(vehicule) {
vehicule.allumer();
vehicule.avancer();
vehicule.arreter();
vehicule.eteindre();
}
const vehicule = new VehiculeVoiture(voiture);
avancerUnPeu(vehicule);