SOLID sono cinque principi di progettazione per costruire sistemi OOP mantenibili e flessibili. Ciascuno affronta una causa comune di codice rigido e fragile.
| Lettera | Principio | Significato in una riga |
|---|
| S | Single Responsibility | Una classe dovrebbe avere una sola ragione per cambiare |
| O | Open/Closed | Aperto per l'estensione, chiuso per la modifica |
| L | Liskov Substitution | I sottotipi devono essere utilizzabili dovunque lo sia il tipo base |
| I | Interface Segregation | Molte piccole interfacce superano una grande |
| D | Dependency Inversion | Dipendere da astrazioni, non da classi concrete |
# Dependency Inversion: high-level code depends on an abstraction
class Notifier: # abstraction
def send(self, msg): ...
class EmailNotifier(Notifier):
def send(self, msg): print("email:", msg)
class OrderService:
def __init__(self, notifier: Notifier): # injected abstraction
self.notifier = notifier # not "new EmailNotifier()"
def place(self):
self.notifier.send("order placed") # works with ANY Notifier
OrderService non dipende specificamente dalla email — sostituisci con SMS o un test double senza toccarlo (D). Aggiungere un nuovo tipo di notificatore non richiede alcun cambio a OrderService (O).
SOLID è una guida, non una legge. Over-applicarla — un'interfaccia per classe, indirezione ovunque — produce "zuppa di astrazione" più difficile da seguire del problema che risolveva.
SOLID fornisce un linguaggio diagnostico condiviso: i revisori possono nominare perché una classe è difficile da cambiare ("questo viola SRP") invece di discutere per gusto personale.
Applicati con giudizio, i principi riducono gli effetti a cascata — i cambiamenti rimangono locali, le nuove funzionalità estendono piuttosto che riscrivono, e i test possono sostituire fake alle dipendenze reali.