SOLID Principle : Le guide du super-héros pour écrire du code propre !
Si vous êtes un développeur de logiciels, vous avez peut-être entendu parler de SOLID. C'est un acronyme qui signifie :
- Principe de responsabilité unique (SRP)
- Principe ouvert/fermé (OCP)
- Principe de substitution de Liskov (LSP)
- Principe de ségrégation d'interface (ISP)
- Principe d'inversion de dépendance (DIP)
Plongeons-nous dans chaque principe plus en détail, avec quelques exemples de code Java pour aider à illustrer les concepts.
1. Principe de responsabilité unique (SRP)
Le SRP stipule qu'une classe ne doit avoir qu'un seul objectif. En d'autres termes, une classe ne devrait avoir qu'une seule responsabilité. Ce principe permet de garantir que votre code est ciblé, lisible et facile à entretenir. Nous ne devrions pas surcharger une classe avec des fonctionnalités excessives.
Supposons que vous ayez une Userclasse qui gère l'authentification des utilisateurs et les notifications par e-mail. Voici un exemple de la façon dont vous pouvez refactoriser cette classe pour suivre le SRP :
// Before refactoring
public class User {
public void login(String username, String password) {
// Authenticate user
}
public void sendEmail(String to, String subject, String body) {
// Send email
}
}
// After refactoring
public class User {
public void login(String username, String password) {
// Authenticate user
}
}
public class EmailService {
public void sendEmail(String to, String subject, String body) {
// Send email
}
}
L'OCP stipule que les entités logicielles (classes, modules, fonctions, etc.) doivent être ouvertes pour extension mais fermées pour modification. En d'autres termes, vous devriez pouvoir ajouter de nouvelles fonctionnalités à votre code sans modifier le code existant.
Supposons que vous ayez une PaymentProcessorclasse qui gère le traitement des paiements pour différents modes de paiement. Voici un exemple de la façon dont vous pouvez refactoriser cette classe pour suivre l'OCP :
// Before refactoring
public class PaymentProcessor {
public void processPayment(Payment payment) {
if (payment.getMethod() == PaymentMethod.CREDIT_CARD) {
// Process credit card payment
} else if (payment.getMethod() == PaymentMethod.PAYPAL) {
// Process PayPal payment
} else if (payment.getMethod() == PaymentMethod.BITCOIN) {
// Process Bitcoin payment
}
}
}
// After refactoring
public interface PaymentMethodProcessor {
void processPayment(Payment payment);
}
public class CreditCardProcessor implements PaymentMethodProcessor {
public void processPayment(Payment payment) {
// Process credit card payment
}
}
public class PayPalProcessor implements PaymentMethodProcessor {
public void processPayment(Payment payment) {
// Process PayPal payment
}
}
public class BitcoinProcessor implements PaymentMethodProcessor {
public void processPayment(Payment payment) {
// Process Bitcoin payment
}
}
public class PaymentProcessor {
private Map<PaymentMethod, PaymentMethodProcessor> processors = new HashMap<>();
public PaymentProcessor() {
processors.put(PaymentMethod.CREDIT_CARD, new CreditCardProcessor());
processors.put(PaymentMethod.PAYPAL, new PayPalProcessor());
processors.put(PaymentMethod.BITCOIN, new BitcoinProcessor());
}
public void processPayment(Payment payment) {
PaymentMethodProcessor processor = processors.get(payment.getMethod());
if (processor != null) {
processor.processPayment(payment);
}
}
}
3. Principe de substitution de Liskov (LSP)
Le principe de substitution de Liskov (LSP) stipule que les objets d'une superclasse doivent être remplaçables par des objets d'une sous-classe sans casser l'application. En d'autres termes, une sous-classe doit pouvoir être utilisée à la place de sa super-classe sans provoquer de comportement inattendu ou d'erreurs.
Disons que vous avez une Rectangleclasse qui calcule l'aire d'un rectangle. Voici un exemple de la façon dont vous pouvez refactoriser cette classe pour suivre le LSP :
// Before refactoring
public class Rectangle {
private int width;
private int height;
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getArea() {
return width * height;
}
}
public class Square extends Rectangle {
public void setWidth(int width) {
super.setWidth(width);
super.setHeight(width);
}
public void setHeight(int height) {
super.setWidth(height);
super.setHeight(height);
}
}
// Test code
Rectangle rect = new Square();
rect.setWidth(5);
rect.setHeight(10);
System.out.println(rect.getArea()); // Expected output: 50
// After refactoring
public class Rectangle {
protected int width;
protected int height;
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getArea() {
return width * height;
}
}
public class Square extends Rectangle {
public Square(int size) {
super(size, size);
}
}
// Test code
Rectangle rect = new Rectangle(5, 10);
System.out.println(rect.getArea()); // Expected output: 50
Square square = new Square(5);
System.out.println(square.getArea()); // Expected output: 25
Le principe de ségrégation des interfaces (ISP) stipule qu'un client ne doit pas être contraint d'implémenter des interfaces qu'il n'utilise pas. En d'autres termes, vous devez séparer les interfaces en plus petites, plus ciblées, plus faciles à mettre en œuvre et à modifier.
Disons que vous avez une Printerinterface qui a deux méthodes : print()et scan(). Voici un exemple de la façon dont vous pouvez refactoriser cette interface pour suivre le FAI :
// Before refactoring
public interface Printer {
void print();
void scan();
}
public class LaserPrinter implements Printer {
public void print() {
// Print document
}
public void scan() {
// Scan document
}
}
public class InkjetPrinter implements Printer {
public void print() {
// Print document
}
public void scan() {
// Do nothing
}
}
// After refactoring
public interface Printable {
void print();
}
public interface Scanable {
void scan();
}
public class LaserPrinter implements Printable, Scanable {
public void print() {
// Print document
}
public void scan() {
// Scan document
}
}
public class InkjetPrinter implements Printable {
public void print() {
// Print document
}
}
// Test code
Printable laserPrinter = new LaserPrinter();
laserPrinter.print();
((Scanable)laserPrinter).scan();
Printable inkjetPrinter = new InkjetPrinter();
inkjetPrinter.print();
5. Principe d'inversion de dépendance (DIP)
Le principe d'inversion de dépendance (DIP) stipule que les modules de haut niveau ne doivent pas dépendre des modules de bas niveau. Au lieu de cela, les deux devraient dépendre d'abstractions. Les abstractions ne doivent pas dépendre des détails. Les détails doivent dépendre des abstractions. En d'autres termes, votre code doit dépendre d'interfaces ou de classes abstraites, plutôt que d'implémentations concrètes.
Disons que vous avez une Bookclasse qui a besoin de récupérer des données d'une Databaseclasse. Voici un exemple de la façon dont vous pouvez refactoriser ce code pour suivre le DIP :
// Before refactoring
public class Book {
private Database database;
public Book() {
this.database = new Database();
}
public String getTitle(int id) {
return database.getTitle(id);
}
}
public class Database {
public String getTitle(int id) {
// Retrieve title from database
return "Title";
}
}
// After refactoring
public interface Database {
String getTitle(int id);
}
public class Book {
private Database database;
public Book(Database database) {
this.database = database;
}
public String getTitle(int id) {
return database.getTitle(id);
}
}
public class DatabaseImpl implements Database {
public String getTitle(int id) {
// Retrieve title from database
return "Title";
}
}
// Test code
Database database = new DatabaseImpl();
Book book = new Book(database);
System.out.println(book.getTitle(123)); // Expected output: "Title"
Conclusion
Les principes SOLID sont un ensemble de lignes directrices qui peuvent vous aider à écrire un code meilleur et plus maintenable. En suivant ces principes, vous pouvez rendre votre code plus modulaire, flexible et réutilisable.
N'oubliez pas que ces principes ne sont pas des règles absolues, mais plutôt des lignes directrices pour vous aider à concevoir de meilleurs logiciels. Comme pour toute directive, il peut y avoir des cas où il est logique de s'écarter des principes afin d'atteindre un objectif spécifique. Cependant, en général, suivre les principes SOLID vous aidera à écrire un code plus propre, plus maintenable et plus extensible.
Pour résumer, les principes SOLID peuvent se résumer ainsi :
- SRP : Une classe ne doit avoir qu'un seul but.
- OCP : Les entités logicielles doivent être ouvertes pour extension mais fermées pour modification.
- LSP : les sous-types doivent être substituables à leurs types de base.
- FAI : Les clients ne doivent pas être obligés de dépendre d'interfaces qu'ils n'utilisent pas.
- DIP : les modules de haut niveau ne doivent pas dépendre des modules de bas niveau. Les deux devraient dépendre d'abstractions.
Enfin, il convient de mentionner que les principes SOLID ne sont qu'un aspect d'une bonne conception de logiciels. Il existe de nombreux autres principes de conception et meilleures pratiques que vous pouvez appliquer à votre code pour le rendre plus efficace et maintenable. Cependant, en suivant les principes SOLID, vous pouvez établir une base solide pour votre logiciel et vous préparer au succès à long terme.
Si vous souhaitez en savoir plus sur les principes SOLID, de nombreuses ressources intéressantes sont disponibles en ligne, notamment des livres, des articles et des vidéos. Vous pouvez également explorer d'autres modèles de conception et meilleures pratiques qui peuvent vous aider à écrire un meilleur code.
Je vous encourage à continuer à apprendre et à explorer de nouvelles idées et techniques pour améliorer la conception de votre logiciel. En investissant dans vos compétences et vos connaissances, vous pouvez devenir un développeur de logiciels meilleur et plus efficace et contribuer au succès de votre équipe et de votre organisation.
Merci d'avoir lu et bon codage !
Want to Connect? If you have any feedback,
please ping me on my LinkedIn: https://linkedin.com/in/shuhanmirza/
Source
![Qu'est-ce qu'une liste liée, de toute façon? [Partie 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































