Informatique

SOLID & Clean Code

Les principes pour ecrire du code propre et maintenable

Le S de SOLID, en mouvement

Clique sur le bouton : la classe User qui fait tout se scinde en trois classes à responsabilité unique.

class User 3 responsabilités = God Class class User name, email (juste les données) UserRepository EmailService PDFGenerator 1 responsabilité 1 responsabilité 1 responsabilité saveToDatabase() sendEmail() generatePDF() Violation : class User a 3 raisons de changer (BDD, email, PDF). Modifier l'une risque de casser les autres.

Les 5 Principes SOLID

🎯 S — Single Responsibility

Une classe = une seule responsabilité. Elle ne doit avoir qu'une seule raison de changer.

❌ Mauvais

class User {
  saveToDatabase() { }
  sendEmail() { }
  generatePDF() { }
}

✅ Bon

class User { }
class UserRepository { save() }
class EmailService { send() }
class PDFGenerator { generate() }

🔓 O — Open/Closed

Ouvert à l'extension, fermé à la modification. On ajoute du comportement sans toucher au code existant.

❌ Modifier le code

function getArea(shape) {
  if (shape.type === 'circle')
    return PI * r * r;
  if (shape.type === 'square')
    return side * side;
  // Ajouter ici à chaque fois...
}

✅ Étendre

interface Shape { getArea(): number }

class Circle implements Shape {
  getArea() { return PI * r * r }
}
class Square implements Shape {
  getArea() { return side * side }
}

🔄 L — Liskov Substitution

Une classe fille doit pouvoir remplacer sa classe mère sans casser le comportement.

❌ Viole LSP

class Bird { fly() { } }
class Penguin extends Bird {
  fly() { throw Error("Can't fly!") }
}
// Penguin casse le contrat de Bird

✅ Respecte LSP

class Bird { }
class FlyingBird extends Bird {
  fly() { }
}
class Penguin extends Bird {
  swim() { }
}

✂️ I — Interface Segregation

Plusieurs petites interfaces > une grosse interface. Ne pas forcer l'implémentation de méthodes inutiles.

❌ Interface géante

interface Worker {
  work()
  eat()
  sleep()
}
// Robot doit implémenter eat() ?!

✅ Interfaces séparées

interface Workable { work() }
interface Eatable { eat() }
interface Sleepable { sleep() }

class Robot implements Workable

🔌 D — Dependency Inversion

Dépendre des abstractions, pas des implémentations. Injection de dépendances.

❌ Couplage fort

class OrderService {
  private db = new MySQLDatabase();
  save(order) {
    this.db.insert(order);
  }
}

✅ Injection

class OrderService {
  constructor(private db: Database) {}
  save(order) {
    this.db.insert(order);
  }
}
// Injecter MySQL, Postgres, Mock...

Visualise le D : inverser la dépendance

Change de base de données dans chaque mode : en couplage fort, OrderService doit être modifié ; avec l'injection, il ne bouge plus.

OrderService db = new MySQLDatabase() module haut niveau « Database » interface (abstraction) MySQL PostgreSQL MockDB dépend directement de… Couplage fort : OrderService crée lui-même sa base concrète. Tout changement de BDD le force à être réécrit.

🎁 Bonus : DRY, KISS, YAGNI

🔁

DRY

Don't Repeat Yourself

Éviter la duplication de code

💋

KISS

Keep It Simple, Stupid

Préférer la simplicité

🚫

YAGNI

You Aren't Gonna Need It

Ne pas coder "au cas où"

🦨 Code Smells à éviter

  • ⚠️God Class — Classe qui fait tout
  • ⚠️Long Method — +30 lignes
  • ⚠️Magic Numbers — if (x > 42)
  • ⚠️Duplicate Code — Copier-coller
  • ⚠️Too Many Params — +3 paramètres
  • ⚠️Dead Code — Code jamais exécuté

🎮 Quiz SOLID & Clean Code

Testez vos connaissances sur SOLID et Clean Code !

Glisser pour continuer vers TDD & CI/CD
⬇️
Bachelor Informatique