🚀 Les principes SOLID (Flutter)
Les principes SOLID sont cinq règles incontournables en programmation orientée objet. Créés par Robert C. Martin (Uncle Bob), ils t'aident à écrire du code Flutter :
- ✅ Plus facile à maintenir
- ✅ Plus simple à tester
- ✅ Plus évolutif
- ✅ Plus robuste
📌 1. Single Responsibility Principle (SRP)
Une classe = Une seule responsabilité.
✅ Pourquoi c'est important ?
- Ton code devient plus clair, lisible et simple à modifier.
🔴 Mauvais exemple :
class UserService {
void login(String email, String password) {}
void logout() {}
void saveUser(User user) {}
}
⚠️ Problème : mélange authentification et sauvegarde des données.
🟢 Bon exemple :
class AuthService {
void login(String email, String password) {}
void logout() {}
}
class UserRepository {
void saveUser(User user) {}
}
👍 Avantage : Chaque classe gère une responsabilité précise :AuthService
: authentification uniquement.UserRepository
: gestion des données utilisateur.
📌 2. Open-Closed Principle (OCP)
Ouvert aux extensions, mais fermé aux modifications.
✅ Pourquoi c'est important ?
- Tu peux améliorer ton app sans risquer d'introduire de nouveaux bugs.
🔴 Mauvais exemple :
double calculateArea(Shape shape) {
if (shape is Square) return shape.side * shape.side;
if (shape is Circle) return pi * shape.radius * shape.radius;
throw UnsupportedError('Forme inconnue');
}
⚠️ Problème : ajouter une nouvelle forme oblige à modifier ce code.
🟢 Bon exemple :
abstract class Shape {
double area();
}
class Square implements Shape {
final double side;
Square(this.side);
@override
double area() => side * side;
}
class Circle implements Shape {
final double radius;
Circle(this.radius);
@override
double area() => pi * radius * radius;
}
👍 Avantage : Ajouter une nouvelle forme n’impliquera plus de modifier le code existant.
📌 3. Liskov Substitution Principle (LSP)
Les classes dérivées doivent pouvoir remplacer leurs classes parentes sans altérer leur comportement.
✅ Pourquoi c'est important ?
- Cela garantit la cohérence et évite les bugs subtils.
🔴 Mauvais exemple :
class Bird {
void fly() {}
}
class Penguin extends Bird {
@override
void fly() => throw Exception('Pingouin ne vole pas !');
}
⚠️ Problème : Un pingouin ne peut pas remplacer correctement un oiseau volant.
🟢 Bon exemple :
abstract class Bird {}
abstract class FlyingBird extends Bird {
void fly();
}
class Sparrow extends FlyingBird {
@override
void fly() => print('vole');
}
class Penguin extends Bird {
void swim() => print('nage');
}
👍 Avantage : Plus de clarté et pas de comportements inattendus.
📌 4. Interface Segregation Principle (ISP)
Préférer plusieurs petites interfaces spécialisées plutôt qu'une grosse interface unique.
✅ Pourquoi c'est important ?
- Les classes implémentent uniquement les méthodes dont elles ont vraiment besoin.
🔴 Mauvais exemple :
abstract class UserActions {
void login();
void logout();
void deleteUser();
}
class SimpleUser implements UserActions {
void login() {}
void logout() {}
void deleteUser() => throw UnimplementedError();
}
⚠️ Problème : SimpleUser
implémente inutilement une méthode qu’il n’utilise jamais.
🟢 Bon exemple :
abstract interface class AuthActions {
void login();
void logout();
}
abstract interface class AdminActions {
void deleteUser();
}
class SimpleUser implements AuthActions {
void login() {}
void logout() {}
}
👍 Avantage : Chaque classe est spécialisée et claire.
📌 5. Dependency Inversion Principle (DIP)
Dépendre des abstractions plutôt que des implémentations concrètes.
✅ Pourquoi c'est important ?
- Ton code devient découplé, flexible et facile à tester.
🔴 Mauvais exemple :
class UserService {
final FirebaseAuth auth;
UserService(this.auth);
}
⚠️ Problème : Le module métier dépend directement d’une implémentation concrète (Firebase).
🟢 Bon exemple :
abstract interface class AuthRepository {
Future<void> login();
}
class FirebaseAuthRepository implements AuthRepository {
Future<void> login() {}
}
class UserService {
final AuthRepository authRepository;
UserService(this.authRepository);
}
👍 Avantage : Si demain Firebase est remplacé par Supabase, aucune modification du service métier ne sera nécessaire.
🎯 Résumé rapide :
Lettre | Principe | Résumé simple |
---|---|---|
S | Single Responsibility | Une classe doit avoir une seule responsabilité |
O | Open-Closed | Ouvert aux ajouts, fermé aux modifications |
L | Liskov Substitution | Remplaçable sans changer de comportement |
I | Interface Segregation | Petites interfaces spécialisées |
D | Dependency Inversion | Dépendre des abstractions, pas des implémentations |