Rinfrescare i principi della programmazione (2)
15-10-2022
I principi SOLID
DEV
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
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
Vantaggi
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
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
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