SlideShare a Scribd company logo
1 of 12
Download to read offline
Come costruire software SOLID(O)
Alex Pagnoni
www.innoteam.it
Una delle sfide più importanti nello sviluppo di applicazioni
software critiche per le aziende è la progettazione di valide
architetture che siano in grado di assicurare requisiti non
funzionali quali l’estensibilità, la manutenibilità, la
testabilità e la leggibilità del codice nel tempo.
2Innoteam
Quando i clienti ci chiedono infatti di modificare o riscrivere le
loro applicazioni, ciò avviene spesso perchè si ritrovano
con una base di codice sviluppata male che ha costi e
tempi di manutenzione troppo elevati per via delle
(mancate) scelte progettuali; in questi casi riscrivere o
effettuare il refactoring dell’applicazione con adeguati principi
architetturali diventa una scelta da valutare molto seriamente
dopo un accurato audit.
3Innoteam
Alcuni di questi principii che seguiamo quando lavoriamo
sulle applicazioni legacy dei clienti, e non solo, sono
sintetizzati nell’acronimo SOLID (Single responsibility, Open-
closed, Liskov substitution, Interface segregation,
Dependency inversion), un insieme di importanti concetti
della programmazione ad oggetti che assieme alle suite di
test aiutano a mantenere un’elevata qualità del software.
4Innoteam
Applichiamo questi concetti sia quando riscriviamo ex novo
l’applicazione che quando procediamo al refactoring. Infatti,
sebbene si sia spesso tentati di cestinare la vecchia base di
codice per ripartire da una nuova, non sempre questa è la
soluzione più economica; in molti casi è infatti sufficiente
riutilizzare il codice sufficientemente buono e applicare
l’approccio SOLID riscrivendo le parti attorno e quando
possibile dentro a quelle porzioni di codice.
5Innoteam
Questi sono i principi SOLID:
•  Single Responsibility Principle (SRP): una classe deve farsi carico di una sola
responsabilità;
•  Open Closed Principle (OCP): l’estensione dovrebbe essere preferita rispetto
alla modifica;
•  Liskov Substitution Principle (LSP): un oggetto di una classe parente dovrebbe
essere in grado di fare riferimento a oggetti figli tramite polimorfismo;
•  Interface Segregation Principle (ISP): un client non dovrebbe essere obbligato a
utilizzare un’interfaccia se non ne ha bisogno, è meglio avere tante interfacce
specifiche piuttosto che una generica per tutti gli scopi;
•  Dependency Inversion Principle (DIP): il codice di più alto livello non deve
dipendere dall’implementazione di codice di più basso livello ma dovrebbe
dipendere dalle astrazioni (es. tramite iniezione delle dipendenze).
6Innoteam
Il principio della “Single Responsibility” stabilisce che ogni classe deve
avere una sola responsabilità e che questa deve essere gestita
internamente.
Ad esempio, una classe Prodotto che salva i suoi attributi sul database
non dovrebbe definire il proprio codice per aprire la connessione al
database ed effettuare il logging di eventuali errori, ma dovrebbe
affidarsi ad apposite classi dedicate rispettivamente al database e al
logging.
Le classi che violano il principio della singola responsabilità tendono ad
essere difficili da sottoporre a unit testing.
Single Responsibility Principle
7Innoteam
Questo principio stabilisce che le classi dovrebbero essere aperte per
l’estensione ma chiuse per la modifica.
“Aperte per l’estensione” significa che le classi andrebbero progettate in modo che
nuove funzionalità possano essere aggiunte tramite ereditarietà man mano che
arrivano nuovi requisiti.
“Chiuse per la modifica” significa che una volta che la classe è stata implementata
non dovrebbe essere più modificata, se non per correggere i bug.
Utilizzando interfacce e classi astratte, e strutturando correttamente le dipendenze,
nuove funzionalità possono essere aggiunte creando nuove classi che implementano
tali interfacce. Un beneficio collaterale di questo principio è che usare le interfacce
per definire le dipendenze comporta la riduzione di accoppiamento e l’ottenimento di
codice orientato ai componenti.
Open Closed Principle
8Innoteam
Il principio di sostituzione di Liskov si applica all’ereditarietà, specificando che le
classi devono essere progettate in modo tale che le dipendenze del client
possano essere sostituite con altre sottoclassi senza che il client si accorga
della variazione.
In sostanza, quindi, tutte le sottoclassi devono operare nello stesso modo della
superclasse. Le funzionalità di una sottoclasse possono essere ovviamente differenti
ma devono essere conformi al comportamento che ci si aspetta dalla superclasse.
Liskov Substitution Principle
9Innoteam
Questo principio stabilisce che le interfacce che sono diventate molto grandi (in modo
simile alle “God class”) devono essere suddivise in interfacce più piccole, in modo che
il codice client non debba essere forzato a dipendere da metodi dell’interfaccia che non
usa e favorendo la composizione rispetto all’ereditarietà.
In questo modo, quando è necessario modificare alcune di queste interfacce non è necessario
aggiornare larghe porzioni di codice che in realtà non dovrebbero dipendere da tali modifiche.
Inoltre si ottiene un maggiore disaccoppiamento e il refactoring, il redeploy e la modifica di
codice diventano più facili.
Questo principio nasce in Xerox, dove un nuovo sistema di gestione di stampanti con
funzionalità aggiuntive come il fax era costruito attorno ad un’unica classe centralizzata
invocata per ogni attività.
Questa classe conteneva quindi il codice per inviare un fax anche quando veniva istanziata per
effettuare una stampa, rendendo arduo aggiungere e correggere funzionalità, oltre che ad
applicare aggiornamenti. La soluzione applicata prevedeva la suddivisione del codice in più
classi specializzate.
Interface Segregation Principle
10Innoteam
Il principio di inversione delle dipendenze stabilisce infine che moduli di alto livello
non devono dipendere da moduli di basso livello, devono invece dipendere da
astrazioni. Inoltre, le astrazioni non devono dipendere dai dettagli, mentre i
dettagli devono dipendere dalle astrazioni.
Questo principio è molto importante per ottenere un forte disaccoppiamento del
codice e per renderlo facile da testare in modo isolato, poiché dettagli come il tipo di
database non sono “hard coded” ma passati come “plugin”.
Dependency Inversion Principle
11Innoteam
I principi SOLID sono strumenti preziosi che dovrebbero essere presi in
considerazione sia quando si scrive nuovo codice che quando si
effettua il refactoring di sistemi legacy. In particolare dimostrano la loro
potenza quando sono usati in combinazione.
Sebbene la sensazione dei programmatori meno esperti che si
imbattono in codice e framework progettati con questi principi sia quello
di avere a che fare con sistemi “over-engineered”, la realtà è che non
usare pienamente questi principi porta a pentirsi di non averlo fatto
quando si realizza che il debito tecnico accumulato rende il codice non
più mantenibile in modo efficace.
Conclusione
12Innoteam

More Related Content

Similar to Come scrivere software SOLID(O)

e-SUAP - General software architecture (Italiano)
e-SUAP - General software architecture (Italiano)e-SUAP - General software architecture (Italiano)
e-SUAP - General software architecture (Italiano)Sabino Labarile
 
Slide evento Code Refactoring JavaScript
Slide evento Code Refactoring JavaScriptSlide evento Code Refactoring JavaScript
Slide evento Code Refactoring JavaScriptLuca Pagliaro
 
MySQL Day Milano 2018 - Le architetture a microservizi
MySQL Day Milano 2018 - Le architetture a microserviziMySQL Day Milano 2018 - Le architetture a microservizi
MySQL Day Milano 2018 - Le architetture a microserviziPar-Tec S.p.A.
 
Dependency injection questa sconosciuta
Dependency injection questa sconosciutaDependency injection questa sconosciuta
Dependency injection questa sconosciutaAndrea Dottor
 
Progetto SOD Davide Sito
Progetto SOD Davide SitoProgetto SOD Davide Sito
Progetto SOD Davide SitoDavide Sito
 
Delphi & Dintorni Webinar - Padroneggiare i principi SOLID con Delphi
Delphi & Dintorni Webinar - Padroneggiare i principi SOLID con DelphiDelphi & Dintorni Webinar - Padroneggiare i principi SOLID con Delphi
Delphi & Dintorni Webinar - Padroneggiare i principi SOLID con DelphiMarco Breveglieri
 
Domain Driven Design e CQRS
Domain Driven Design e CQRSDomain Driven Design e CQRS
Domain Driven Design e CQRSManuel Scapolan
 
PowerMock TDD User Group Milano
PowerMock TDD User Group MilanoPowerMock TDD User Group Milano
PowerMock TDD User Group MilanoMassimo Groppelli
 
Le 7 sfide da affrontare nella migrazione da monolite a miniservizi
Le 7 sfide da affrontare nella migrazione da monolite a miniserviziLe 7 sfide da affrontare nella migrazione da monolite a miniservizi
Le 7 sfide da affrontare nella migrazione da monolite a miniserviziLuca Acquaviva
 
[AxonIQ Italia Community] Architetture distribuite a eventi: sono adatte al m...
[AxonIQ Italia Community] Architetture distribuite a eventi: sono adatte al m...[AxonIQ Italia Community] Architetture distribuite a eventi: sono adatte al m...
[AxonIQ Italia Community] Architetture distribuite a eventi: sono adatte al m...Corrado Musumeci
 
Modelli per l'integrazione aziendale
Modelli per l'integrazione aziendaleModelli per l'integrazione aziendale
Modelli per l'integrazione aziendaleCarlo Zamagni
 
MySQL Day Roma 2019 - Le architetture a microservizi e MySQL
MySQL Day Roma 2019 - Le architetture a microservizi e MySQLMySQL Day Roma 2019 - Le architetture a microservizi e MySQL
MySQL Day Roma 2019 - Le architetture a microservizi e MySQLPar-Tec S.p.A.
 
Cloud Hosting Vs Cluster
Cloud Hosting Vs ClusterCloud Hosting Vs Cluster
Cloud Hosting Vs ClusterStefano Sordi
 
Cloud Hosting Vs Cluster di Tobia Caneschi (Register.it)
Cloud Hosting Vs Cluster di Tobia Caneschi (Register.it)Cloud Hosting Vs Cluster di Tobia Caneschi (Register.it)
Cloud Hosting Vs Cluster di Tobia Caneschi (Register.it)Register.it
 
Microservices architecture & Service Fabric
Microservices architecture & Service FabricMicroservices architecture & Service Fabric
Microservices architecture & Service FabricMassimo Bonanni
 
Web Api – The HTTP Way
Web Api – The HTTP WayWeb Api – The HTTP Way
Web Api – The HTTP WayLuca Milan
 

Similar to Come scrivere software SOLID(O) (20)

Microservices
MicroservicesMicroservices
Microservices
 
Che cosa sono i microservizi?
Che cosa sono i microservizi?Che cosa sono i microservizi?
Che cosa sono i microservizi?
 
e-SUAP - General software architecture (Italiano)
e-SUAP - General software architecture (Italiano)e-SUAP - General software architecture (Italiano)
e-SUAP - General software architecture (Italiano)
 
Slide evento Code Refactoring JavaScript
Slide evento Code Refactoring JavaScriptSlide evento Code Refactoring JavaScript
Slide evento Code Refactoring JavaScript
 
Kotlin hexagonal-architecture
Kotlin hexagonal-architectureKotlin hexagonal-architecture
Kotlin hexagonal-architecture
 
MySQL Day Milano 2018 - Le architetture a microservizi
MySQL Day Milano 2018 - Le architetture a microserviziMySQL Day Milano 2018 - Le architetture a microservizi
MySQL Day Milano 2018 - Le architetture a microservizi
 
Dependency injection questa sconosciuta
Dependency injection questa sconosciutaDependency injection questa sconosciuta
Dependency injection questa sconosciuta
 
Progetto SOD Davide Sito
Progetto SOD Davide SitoProgetto SOD Davide Sito
Progetto SOD Davide Sito
 
Delphi & Dintorni Webinar - Padroneggiare i principi SOLID con Delphi
Delphi & Dintorni Webinar - Padroneggiare i principi SOLID con DelphiDelphi & Dintorni Webinar - Padroneggiare i principi SOLID con Delphi
Delphi & Dintorni Webinar - Padroneggiare i principi SOLID con Delphi
 
Domain Driven Design e CQRS
Domain Driven Design e CQRSDomain Driven Design e CQRS
Domain Driven Design e CQRS
 
PowerMock TDD User Group Milano
PowerMock TDD User Group MilanoPowerMock TDD User Group Milano
PowerMock TDD User Group Milano
 
Database Data Aggregator
Database Data AggregatorDatabase Data Aggregator
Database Data Aggregator
 
Le 7 sfide da affrontare nella migrazione da monolite a miniservizi
Le 7 sfide da affrontare nella migrazione da monolite a miniserviziLe 7 sfide da affrontare nella migrazione da monolite a miniservizi
Le 7 sfide da affrontare nella migrazione da monolite a miniservizi
 
[AxonIQ Italia Community] Architetture distribuite a eventi: sono adatte al m...
[AxonIQ Italia Community] Architetture distribuite a eventi: sono adatte al m...[AxonIQ Italia Community] Architetture distribuite a eventi: sono adatte al m...
[AxonIQ Italia Community] Architetture distribuite a eventi: sono adatte al m...
 
Modelli per l'integrazione aziendale
Modelli per l'integrazione aziendaleModelli per l'integrazione aziendale
Modelli per l'integrazione aziendale
 
MySQL Day Roma 2019 - Le architetture a microservizi e MySQL
MySQL Day Roma 2019 - Le architetture a microservizi e MySQLMySQL Day Roma 2019 - Le architetture a microservizi e MySQL
MySQL Day Roma 2019 - Le architetture a microservizi e MySQL
 
Cloud Hosting Vs Cluster
Cloud Hosting Vs ClusterCloud Hosting Vs Cluster
Cloud Hosting Vs Cluster
 
Cloud Hosting Vs Cluster di Tobia Caneschi (Register.it)
Cloud Hosting Vs Cluster di Tobia Caneschi (Register.it)Cloud Hosting Vs Cluster di Tobia Caneschi (Register.it)
Cloud Hosting Vs Cluster di Tobia Caneschi (Register.it)
 
Microservices architecture & Service Fabric
Microservices architecture & Service FabricMicroservices architecture & Service Fabric
Microservices architecture & Service Fabric
 
Web Api – The HTTP Way
Web Api – The HTTP WayWeb Api – The HTTP Way
Web Api – The HTTP Way
 

Come scrivere software SOLID(O)

  • 1. Come costruire software SOLID(O) Alex Pagnoni www.innoteam.it
  • 2. Una delle sfide più importanti nello sviluppo di applicazioni software critiche per le aziende è la progettazione di valide architetture che siano in grado di assicurare requisiti non funzionali quali l’estensibilità, la manutenibilità, la testabilità e la leggibilità del codice nel tempo. 2Innoteam
  • 3. Quando i clienti ci chiedono infatti di modificare o riscrivere le loro applicazioni, ciò avviene spesso perchè si ritrovano con una base di codice sviluppata male che ha costi e tempi di manutenzione troppo elevati per via delle (mancate) scelte progettuali; in questi casi riscrivere o effettuare il refactoring dell’applicazione con adeguati principi architetturali diventa una scelta da valutare molto seriamente dopo un accurato audit. 3Innoteam
  • 4. Alcuni di questi principii che seguiamo quando lavoriamo sulle applicazioni legacy dei clienti, e non solo, sono sintetizzati nell’acronimo SOLID (Single responsibility, Open- closed, Liskov substitution, Interface segregation, Dependency inversion), un insieme di importanti concetti della programmazione ad oggetti che assieme alle suite di test aiutano a mantenere un’elevata qualità del software. 4Innoteam
  • 5. Applichiamo questi concetti sia quando riscriviamo ex novo l’applicazione che quando procediamo al refactoring. Infatti, sebbene si sia spesso tentati di cestinare la vecchia base di codice per ripartire da una nuova, non sempre questa è la soluzione più economica; in molti casi è infatti sufficiente riutilizzare il codice sufficientemente buono e applicare l’approccio SOLID riscrivendo le parti attorno e quando possibile dentro a quelle porzioni di codice. 5Innoteam
  • 6. Questi sono i principi SOLID: •  Single Responsibility Principle (SRP): una classe deve farsi carico di una sola responsabilità; •  Open Closed Principle (OCP): l’estensione dovrebbe essere preferita rispetto alla modifica; •  Liskov Substitution Principle (LSP): un oggetto di una classe parente dovrebbe essere in grado di fare riferimento a oggetti figli tramite polimorfismo; •  Interface Segregation Principle (ISP): un client non dovrebbe essere obbligato a utilizzare un’interfaccia se non ne ha bisogno, è meglio avere tante interfacce specifiche piuttosto che una generica per tutti gli scopi; •  Dependency Inversion Principle (DIP): il codice di più alto livello non deve dipendere dall’implementazione di codice di più basso livello ma dovrebbe dipendere dalle astrazioni (es. tramite iniezione delle dipendenze). 6Innoteam
  • 7. Il principio della “Single Responsibility” stabilisce che ogni classe deve avere una sola responsabilità e che questa deve essere gestita internamente. Ad esempio, una classe Prodotto che salva i suoi attributi sul database non dovrebbe definire il proprio codice per aprire la connessione al database ed effettuare il logging di eventuali errori, ma dovrebbe affidarsi ad apposite classi dedicate rispettivamente al database e al logging. Le classi che violano il principio della singola responsabilità tendono ad essere difficili da sottoporre a unit testing. Single Responsibility Principle 7Innoteam
  • 8. Questo principio stabilisce che le classi dovrebbero essere aperte per l’estensione ma chiuse per la modifica. “Aperte per l’estensione” significa che le classi andrebbero progettate in modo che nuove funzionalità possano essere aggiunte tramite ereditarietà man mano che arrivano nuovi requisiti. “Chiuse per la modifica” significa che una volta che la classe è stata implementata non dovrebbe essere più modificata, se non per correggere i bug. Utilizzando interfacce e classi astratte, e strutturando correttamente le dipendenze, nuove funzionalità possono essere aggiunte creando nuove classi che implementano tali interfacce. Un beneficio collaterale di questo principio è che usare le interfacce per definire le dipendenze comporta la riduzione di accoppiamento e l’ottenimento di codice orientato ai componenti. Open Closed Principle 8Innoteam
  • 9. Il principio di sostituzione di Liskov si applica all’ereditarietà, specificando che le classi devono essere progettate in modo tale che le dipendenze del client possano essere sostituite con altre sottoclassi senza che il client si accorga della variazione. In sostanza, quindi, tutte le sottoclassi devono operare nello stesso modo della superclasse. Le funzionalità di una sottoclasse possono essere ovviamente differenti ma devono essere conformi al comportamento che ci si aspetta dalla superclasse. Liskov Substitution Principle 9Innoteam
  • 10. Questo principio stabilisce che le interfacce che sono diventate molto grandi (in modo simile alle “God class”) devono essere suddivise in interfacce più piccole, in modo che il codice client non debba essere forzato a dipendere da metodi dell’interfaccia che non usa e favorendo la composizione rispetto all’ereditarietà. In questo modo, quando è necessario modificare alcune di queste interfacce non è necessario aggiornare larghe porzioni di codice che in realtà non dovrebbero dipendere da tali modifiche. Inoltre si ottiene un maggiore disaccoppiamento e il refactoring, il redeploy e la modifica di codice diventano più facili. Questo principio nasce in Xerox, dove un nuovo sistema di gestione di stampanti con funzionalità aggiuntive come il fax era costruito attorno ad un’unica classe centralizzata invocata per ogni attività. Questa classe conteneva quindi il codice per inviare un fax anche quando veniva istanziata per effettuare una stampa, rendendo arduo aggiungere e correggere funzionalità, oltre che ad applicare aggiornamenti. La soluzione applicata prevedeva la suddivisione del codice in più classi specializzate. Interface Segregation Principle 10Innoteam
  • 11. Il principio di inversione delle dipendenze stabilisce infine che moduli di alto livello non devono dipendere da moduli di basso livello, devono invece dipendere da astrazioni. Inoltre, le astrazioni non devono dipendere dai dettagli, mentre i dettagli devono dipendere dalle astrazioni. Questo principio è molto importante per ottenere un forte disaccoppiamento del codice e per renderlo facile da testare in modo isolato, poiché dettagli come il tipo di database non sono “hard coded” ma passati come “plugin”. Dependency Inversion Principle 11Innoteam
  • 12. I principi SOLID sono strumenti preziosi che dovrebbero essere presi in considerazione sia quando si scrive nuovo codice che quando si effettua il refactoring di sistemi legacy. In particolare dimostrano la loro potenza quando sono usati in combinazione. Sebbene la sensazione dei programmatori meno esperti che si imbattono in codice e framework progettati con questi principi sia quello di avere a che fare con sistemi “over-engineered”, la realtà è che non usare pienamente questi principi porta a pentirsi di non averlo fatto quando si realizza che il debito tecnico accumulato rende il codice non più mantenibile in modo efficace. Conclusione 12Innoteam