SUPERCAT.DEV

Benvenut* sul mio blog

DEV

Rinfrescare i principi della programmazione (2)

15-10-2022

I principi SOLID

In programmazione orientata agli oggetti, SOLID è un acronimo mnemonico che raggruppa i cinque principi destinati a produrre architetture più comprensibili, flessibili e mantenibili. I principi sono un sotto-insieme di una serie molto più numerosa promossa dall'istruttore americano Robert C. Martin (coautore del metodo Agile). L'acronimo è stato introdotto da Micheal Feathers. Sono tutti principi di buon senso e nessuno necessita di una conoscenza approfondita del linguaggio.

Principi

  • Single responsibility principle
  • Open/closed principle
  • Liskov substitution principle
  • Interface segregation principle
  • Dependency inversion principle

Piccolo "dizionario"
Coesione
A che punto i pezzi di un componente sono in relazione gli uni con gli altri Accoppiamento
Metrica che misura l'interconnessione tra i moduli. Due moduli si dicono accoppiati se una modifica di un solo modulo richiede la modifica anche dell'altro. Incapsulazione
L'idea dietro l'incapsulazione è di integrare all'interno dell'oggetto tutti gli elementi necessari al suo funzionamento (sia metodi che dati). Un oggetto dovrebbe nascondere il suo funzionamento interno ed esporre esternamente solo la propria interfaccia con cui i clienti possono manipolarlo.

S (Single responsibility principle - SRP)
È il principio più vecchio e si basa sugli studi di Tom DeMarco del 1979 che lo qualifica come principio di coesione. Una classe, una funzione, o un metodo deve avere una e una sola responsabilità. Per cui deve avere solo una sola ragione per essere modificata.

Come applicare il principio

  • In una grande classe si potrebbero raggruppare i metodi con i nomi/azioni che sembrano essere della stessa famiglia. Se vengono fuori più gruppi allora è un indizio che la classe andrebbe riprogettata.
  • Un altro metodo è guardare le dipendenze esterne (tipo uso diretto della base dati). Se ci sono responsabilità annesse allora merita una riprogettazione.

Vantaggi

  • diminuzione della complessità del codice
  • aumento della leggibilità della classe
  • possibilità di migliore incapsulazione e migliore coesione

O (Open/closed principle - OCP)
Un'entità deve essere chiusa alla modifica ma aperta all'estensione. (Bertrand Meyer) Come il principio di Liskov è estratto da un articolo del 1988. La classe non deve essere modificata che per correggere un errore. Qualunque nuova funzionalità dovrebbe essere aggiunta con una nuova classe che potrebbe eventualmente ereditare la classe iniziale.

Come applicare il principio
Usare design patterns come il Decorator o il Visitor possono estendere le capacità di nuove funzionalità senza modificare il codice esistente. L'esempio classico è quello in cui ho un TypeEnum nel costruttore e un po' di if (tipo == Tipo::Primo) ... (tipo == Tipo::Secondo) ... ma se devo aggiungerne uno nuovo sorge un problema. Una soluzione sarebbe aggiungere un'interfaccia con una funzione Manage. Poi usare l'interfaccia su ogni classe così da slegarsi dalle classi.

Vantaggi

  • Migliore flessibilità successive all'aggiunta di nuove funzionalità
  • Diminuzione dell'accoppiamento

L (Liskov substitution principle - LSP)
I sotto-tipi devono essere sostituibili al tipo di base. Lo scopo di questo principio è che si possa usare un metodo senza bisogno di conoscere la gerarchia delle classi usate nell'applicazione.

Come applicare il principio
Per vedere se lo rispetti fatti la domanda: posso rimpiazzare senza che si blocchi tutto la classe in uso con un'interfaccia di livello superiore?

Vantaggi

  • Incremento dell'incapsulazione
  • Diminuzione dell'accoppiamento

I (Interface segregation principle - ISP)
Preferire più interfacce specifiche che una sola interfaccia generale. Gli utilizzatori di un'entità non devono dipendere da un'interfaccia che non usano.

Come applicare il principio
Come per SRP riunisci sotto gruppi funzionali. Non usare interfacce tipo IMyClass. Non spingere il principio all'eccesso avendo un'interfaccia per metodo.

D (Dependency inversion principle - DIP)
Bisogna dipendere dalle astrazioni e non dalle implementazioni. È da molti considerato un principio secondario in quanto è un'applicazione dei principi LSP e OCP. Ad esempio se si cambia l'accesso alla base dati la classe non deve esserne impattata. E viceversa.

Come applicare il principio
Ogni contatto tra le classi deve essere fatto attraverso un'astrazione (generalmente un'interfaccia ma anche una classe, una factory ad esempio) Creare a ogni strato un provider intermedio. Bisogna tendere verso questo principio senza per forza arrivare a soluzioni integraliste.

Vantaggi

  • Una diminuzione consistente dell'accoppiamento