Progettare applicazioni basate sul paradigma object-oriented non è affatto banale, riuscire a renderle anche riusabili ed estendibili a piacimento è ancora più arduo.
Ciò che occorre di volta in volta è saper individuare gli oggetti giusti, con un livello di dettaglio e granularità adeguato, ed essere in grado di definire una struttura gerarchica consistente, basata su un insieme di relazioni e collaborazioni coerente ed efficace.
Riuscire
nell’intento di definire una struttura ad oggetti che sia corretta
e al tempo stesso riusabile e flessibile è un’impresa ardua,
soprattutto nel caso di applicazioni particolarmente complesse. In genere, durante la sua realizzazione,
un’applicazione subisce innumerevoli modifiche dettate dalla
variabilità delle specifiche progettuali, dalla scarsa conoscenza
del dominio applicativo e dall’inesperienza. In più la mancanza di
tempo, che nei progetti di sviluppo è un aspetto quasi congenito,
porta sovente a scegliere soluzioni molto focalizzate sul modello
reale attuale e poco orientate ad adattarsi ai cambiamenti futuri.
In
uno scenario come quello descritto, diventa importante sia per chi
progetta, sia per chi scrive il codice saper individuare delle
soluzioni che siano riutilizzabili più volte nell’ambito di uno
stesso progetto, piuttosto che in progetti diversi, senza ogni volta
dover partire da zero per risolvere uno specifico problema.
Per
minimizzare il lavoro da svolgere, gli sviluppatori meno esperti
solitamente tendono a ricorrere a tecniche non object-oriented (non
ultimo, il famigerato copia-e-incolla),
con il risultato di duplicare parti di codice e di introdurre in modo
più o meno voluto accoppiamento e dipendenze tra gli oggetti. E’
sicuramente preferibile ricercare soluzioni object-oriented che in
passato si sono rivelate vincenti ed efficaci.
Queste
soluzioni, che in prima analisi possiamo definire pattern,
sono orientate a risolvere particolari problematiche di progettazione
e tendono ad introdurre nell’ambito di una struttura ad oggetti
quella flessibilità che è necessaria per rendere il codice
riutilizzabile ed estendibile.
esistono
diverse tipologie di pattern in funzione della loro area di
applicazione, in generale essi possono essere raggruppati in
macrocategorie specifiche (dette anche cluster),
ciascuna delle quali contenente pattern orientati a risolvere
problematiche similari. I cluster possono a loro volta essere
suddivisi in sottocategorie a granularità più bassa.
Oltre
che l’appartenenza ad un determinato cluster, per un pattern è
possibile considerare come fattore distintivo anche il livello di
astrazione che lo contraddistingue. Nell’ambito del cluster dei
pattern relativi allo sviluppo di applicazioni software possiamo
individuare tre categorie di pattern caratterizzate da un diverso
livello di astrazione.
1. Pattern
architetturali: descrivono lo
schema organizzativo della struttura che caratterizza un sistema
software. In genere questi pattern individuano le parti del sistema a
cui sono associate responsabilità omogenee e le relazioni che
esistono tra i diversi sottosistemi.
2. Pattern
di disegno (design
pattern): sono i pattern che si
riferiscono alle problematiche legate al disegno object-oriented.
3. Pattern
di implementazione (idiomi):
sono pattern di basso livello specifici per una particolare
tecnologia (per esempio, il .NET Framework). Essi descrivono le
modalità implementative da utilizzare per risolvere problematiche di
sviluppo sfruttando in modo mirato le caratteristiche peculiari di
una particolare piattaforma.
Come
detto, ciascuno di questi gruppi è caratterizzato da un grado di
astrazione differente. I design pattern si collocano tra i pattern
architetturali, troppo generici per essere orientati a risolvere
problematiche di disegno, e i pattern idiomatici, molto legati alla
tecnologia a cui si riferiscono e all’implementazione vera e
propria. I design pattern descrivono soluzioni che lasciano sempre e
comunque un certo grado di libertà nella loro adozione e
implementazione, dal momento che non descrivono mai soluzioni che
sono valide per una piattaforma specifica, ma al contrario hanno una
validità più generale e trasversale rispetto alla tecnologia.
Uno
degli aspetti più delicati nel disegno object-oriented (OOD)
consiste nella scomposizione del sistema in oggetti. Si tratta di una
attività complessa dal momento che entrano in gioco fattori non
direttamente collegati alle specifiche funzionali quali
l’accoppiamento tra oggetti, la loro dipendenza, la coesione
funzionale, la granularità, la flessibilità, l’estendibilità e
la riusabilità. Questi aspetti devono necessariamente influenzare il
processo di scomposizione, talvolta anche in modi tra loro
discordanti.
Esistono
diversi approcci che permettono di scomporre in oggetti un sistema. È
possibile partire dai casi d’uso, individuare in essi i sostantivi
e i verbi e da questi ricavare le classi e i metodi corrispondenti al
fine di ottenere la struttura ad oggetti desiderata. In alternativa,
è possibile porre l’attenzione principalmente sulle responsabilità
e sulle collaborazioni nell’ambito del sistema in fase di studio e,
in funzione di esse, individuare gli oggetti necessari per gestirle
opportunamente. O ancora, è possibile partire da un modello del
mondo reale e tradurre gli elementi individuati in altrettanti
oggetti.
Ognuno
di questi approcci concorre a definire la struttura statica del
sistema che, se da un lato rispecchia la realtà di oggi, dall’altro
in genere non si presta direttamente ad evolvere nel tempo e ad
adattarsi alla realtà di domani. L’esigenza di individuare una
struttura flessibile ed estendibile, in grado di rispondere al meglio
ai cambiamenti nel tempo, porta inevitabilmente a cercare soluzioni
di disegno che facciano largo uso di astrazioni e oggetti non
necessariamente collegati alla realtà in esame per non limitare in
modo importante l’evoluzione del sistema.
I
design pattern aiutano ad individuare queste astrazioni e gli oggetti
in grado di rappresentarle. Essi concorrono a limitare le dipendenze,
incrementando l’estendibilità e la riusabilità, e rendono di
conseguenza il sistema più manutenibile nel tempo, in grado di
rispondere ai cambiamenti in modo efficiente ed elegante.
I
design pattern agevolano il riuso di soluzioni architetturali note,
rendendo accessibili agli architetti e agli sviluppatori tecniche di
disegno universalmente riconosciute come valide ed efficaci. In
questo senso i design pattern aiutano i progettisti a operare scelte
consapevoli tra le varie alternative possibili allo scopo di favorire
la riusabilità.
Nessun commento:
Posta un commento