Principes SOLID en Go : théorie et pratique sur Golang

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Principes SOLID en Go : théorie et pratique



SOLID est un acronyme de cinq principes fondamentaux de conception orientée objet qui aident à créer un code flexible, maintenable et évolutif. Bien que Go ne soit pas un langage OOP classique (il n'a pas d'héritage de classes), ses interfaces, sa composition et son typage strict permettent d'appliquer SOLID avec succès. Dans cet article, nous allons analyser chaque principe avec des exemples concrets en langage Go.



1. Principe de responsabilité unique (SRP — Single Responsibility Principle)



Théorie : Chaque type (structure, fonction, interface) ne doit avoir qu'une seule raison de changer. En d'autres termes, il est responsable d'une seule partie de la fonctionnalité du programme.



Pratique en Go : Une erreur fréquente est la création de structures « divines » qui gèrent à la fois la logique métier, la journalisation et l'envoi de notifications.



Mauvais exemple (violation du SRP) :



type OrderService struct{}

func (s *OrderService) Create(order Order) error { // 1. Sauvegarde en BDD // 2. Envoi d'email // 3. Journalisation return nil}


Bon exemple (respect du SRP) :



type OrderRepository interface {    Save(order Order) error}

type EmailService interface { Send(to string, subject string, body string) error}

type Logger interface { Info(msg string)}

type OrderService struct { repo OrderRepository email EmailService log Logger}

func (s *OrderService) Create(order Order) error { if err := s.repo.Save(order); err != nil { s.log.Info("Failed to save order") return err } if err := s.email.Send(order.Email, "Order Confirmed", "Your order is placed"); err != nil { s.log.Info("Failed to send email") } s.log.Info("Order created successfully") return nil}


Maintenant, chaque structure est responsable de sa propre tâche, et un changement dans la logique d'email n'affectera pas la sauvegarde des commandes.



2. Principe d'ouverture/fermeture (OCP — Open/Closed Principle)



Théorie : Les classes (types) doivent être ouvertes à l'extension, mais fermées à la modification. Cela signifie que vous devez pouvoir ajouter de nouvelles fonctionnalités sans modifier le code existant.



Pratique en Go : Utilisez les interfaces et la composition pour ajouter de nouvelles implémentations sans modifier la logique principale.



Exemple : Supposons que nous ayons un système de calcul des frais de livraison. Initialement, il n'y a qu'une « livraison standard », mais nous devons ajouter une « livraison express ».



// Définition de l'interfacetype ShippingCostCalculator interface {    Calculate(order Order) float64}

// Implémentation standardtype StandardShipping struct{}

func (s StandardShipping) Calculate(order Order) float64 { return 5.99}

// Nouvelle implémentation sans modifier le code ci-dessustype ExpressShipping struct{}

func (e ExpressShipping) Calculate(order Order) float64 { return 15.99}

// Utilisationfunc ProcessOrder(order Order, calculator ShippingCostCalculator) { cost := calculator.Calculate(order) fmt.Printf("Shipping cost: %.2f", cost)}


Nous ne modifions pas ProcessOrder — nous passons simplement une nouvelle instance de ExpressShipping. C'est cela, l'OCP.



3. Principe de substitution de Liskov (LSP — Liskov Substitution Principle)



Théorie : Les objets d'un programme doivent être remplaçables par des instances de leurs sous-types sans altérer la correction du programme. En Go, cela signifie que si une fonction attend une interface, toute implémentation de cette interface doit fonctionner correctement.



Pratique en Go : Assurez-vous que vos implémentations d'interfaces ne violent pas les attentes du code appelant. Par exemple, si l'interface suppose que la méthode GetName() retourne toujou

Blogs

Book Recommendations