Principes SOLID en Go : guide avancé avec exemples

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 : niveau avancé

\n\n

SOLID est un ensemble de cinq principes fondamentaux de conception orientée objet qui aident à créer un code flexible, maintenable et évolutif. Dans le contexte de Go, un langage avec une philosophie unique de composition plutôt que d'héritage, l'application de SOLID nécessite une approche particulière. Dans cet article, nous analyserons chaque principe à un niveau avancé, avec des exemples concrets et des anti-patrons caractéristiques de la communauté Go.

\n\n

1. Single Responsibility Principle (SRP) en Go

\n\n

Le principe de responsabilité unique stipule : une classe (structure) ne doit avoir qu'une seule raison de changer. En Go, cela est souvent violé dans les packages utilitaires et les "objets divins".

\n\n

Anti-patron : structure avec de multiples responsabilités

\n\n
type UserService struct {\n    db *sql.DB\n    cache *redis.Client\n    logger *log.Logger\n}\n\nfunc (s *UserService) CreateUser(ctx context.Context, u User) error {\n    // 1. Validation\n    // 2. Hachage du mot de passe\n    // 3. Sauvegarde en base de données\n    // 4. Envoi d'email\n    // 5. Journalisation\n    return nil\n}
\n\n

Solution : divisez les responsabilités en services séparés et utilisez la composition.

\n\n
type UserValidator interface {\n    Validate(u User) error\n}\n\ntype PasswordHasher interface {\n    Hash(password string) (string, error)\n}\n\ntype UserRepository interface {\n    Save(ctx context.Context, u User) error\n}\n\ntype EmailSender interface {\n    SendWelcomeEmail(ctx context.Context, email string) error\n}\n\ntype UserService struct {\n    validator   UserValidator\n    hasher      PasswordHasher\n    repo        UserRepository\n    emailSender EmailSender\n    logger      Logger\n}
\n\n

Chaque composant a désormais une seule raison de changer, ce qui simplifie les tests et la maintenance.

\n\n

2. Open-Closed Principle (OCP) via les interfaces

\n\n

Le principe d'ouverture/fermeture : les entités doivent être ouvertes à l'extension, mais fermées à la modification. En Go, cela est réalisé via les interfaces et l'injection de dépendances.

\n\n

Mauvais exemple : couplage fort

\n\n
type PaymentProcessor struct {\n    paypalAPI *PayPalAPI\n}\n\nfunc (p *PaymentProcessor) Process(amount float64) error {\n    return p.paypalAPI.Charge(amount)\n}
\n\n

Si vous devez ajouter Stripe, vous devrez modifier le code.

\n\n

Approche correcte : interface + stratégie

\n\n
type PaymentGateway interface {\n    Charge(amount float64) error\n    Refund(transactionID string) error\n}\n\ntype PayPalGateway struct{ /* ... */ }\ntype StripeGateway struct{ /* ... */ }\n\nfunc (p *PayPalGateway) Charge(amount float64) error { /* ... */ }\nfunc (s *StripeGateway) Charge(amount float64) error { /* ... */ }\n\ntype PaymentService struct {\n    gateway PaymentGateway\n}\n\nfunc NewPaymentService(gw PaymentGateway) *PaymentService {\n    return &PaymentService{gateway: gw}\n}
\n\n

Vous pouvez désormais ajouter de nouvelles passerelles de paiement sans modifier PaymentService.

\n\n

3. Liskov Substitution Principle (LSP) dans le contexte de Go

\n\n

Le principe de substitution de Barbara Liskov : 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, où il n'y a pas d'héritage classique, le LSP se manifeste à travers les contrats d'interface.

\n\n

Violation typique : interface avec des méthodes redondantes

\n\n
type Bird interface {\n    Fly() error\n    Swim() error\n}\n\ntype Penguin struct{}\n\nfunc (p *Penguin) Fly() error {\n    return errors.New("penguins can't fly")\n}\n\nfunc (p *Penguin) Swim() error {\n    return nil\n}
\n\n

Ici, Penguin ne peut pas implémenter correctement Fly(), ce qui viole le LSP.

\n\n

Solution : séparation des interfaces

\n\n
type Flyer interface {\n    Fly() error\n}\n\ntype Swimmer interface {\n    S                

Blogs

Book Recommendations