Quali sono i principi e le tecniche usati
per la creazione dei programmi?
In un ambiente object-oriented quali soluzioni adottare?
Ecco alcune risposte e la soluzione completa di un caso reale.
In tutte
le attività industriali di creazione e realizzazione di un nuovo prodotto
si seguono una serie di passi che conducono, partendo dalle specifiche
dell'oggetto da creare, al prodotto finito. Queste tecniche di progettazione
sono state introdotte da tempo anche in campo software con notevoli risultati.
Una tecnica che tende a standardizzare, attraverso precisi passi elementari,
la modalità di costruzione di un programma, prende il nome di
metodologia.
E' universalmente riconosciuto che nella realizzazione di un sistema software,
soprattutto se complesso, la mancanza di una metodologia, porta inevitabilmente
alla realizzazione di software scadente, ovvero di software difficile da
modificare e da riusare.
La maggior parte delle metodologie usate nella realizzazione di un
programma, semplice o complesso che sia, prevede in generale i seguenti passi
da compiere:
1) Analisi e specifica
dei requisiti.
Si esamina il problema nel dettaglio, i suoi vincoli e i suoi requisiti,
ovvero si analizza ogni informazione che sarà necessaria durante la
progettazione per realizzare un prodotto che dovrà essere esattemente
corrispondente a ciò che si desidera.
"Un requisito è una proprietà che il software dovrà possedere o un comportamento che dovrà avere durante la sua esecuzione, in corrispondenza di un determinato evento."
Innanzitutto in questa fase si analizza se vi è
una soluzione fattibile al problema (analisi dei requisiti),
successivamente, se esso è ritenuto risolvibile, si passa alla
specifica dei requisiti attraverso la quale si stila un documento
che deve essere approvato dal gruppo di lavoro e che deve specificare
dettagliatamente il comportamento del programma durante tutte le fasi dell'
esecuzione, nonchè i vincoli e le caratteristiche di funzionamento
(anche la sua interfaccia).
Questo documento deve specificare, in modo preciso e non ambiguo il comportamento
del software visto dall'utente, ovvero cosa il software dovrà
fare durante la sua esecuzione e non tanto come ciò sarà
fatto.
2) Disegno del
progetto software.
Come l'ingegnere edile, ricevute le indicazioni sulla casa che deve progettare,
inizia il disegno dell'abitazione, manualmente o al computer, così
il disegnatore software inizia a definire e progettare i moduli del programma
e le loro interazioni, senza entrare, in questa fase, nei dettagli della
realizzazione. Il disegno del software dovrà ovviamente partire dalla
specifica dei requisiti (output della fase precedente).
Un modulo è un componente software indipendente che realizza un servizio, ovvero una serie di funzionalità correlate.
Ogni modulo realizza una precisa funzione o un servizio
(gruppo di funzioni correlate) e, insieme agli altri moduli del programma,
concorre alla risoluzione del problema iniziale.
I vantaggi della modularità in ambito software sono sostanzialmente
due:
1) Un progetto modulare riduce la complessità di progettazione;
2) Un progetto modulare favorisce la manutenzione, poichè ogni modulo
racchiude al suo interno determinate funzionalità realizzate in modo
indipendente da quelle degli altri moduli.
Così un televisore è più facile da progettare se si
adopera la modularità (suddivisione in schede elettroniche), ma anche
da riparare, poichè ogni scheda è indipendente dalle altre
e realizza una serie di funzioni, così che la ricerca di un guasto
di una funzione è limitata all'interno della scheda che realizza quella
funzionalità.
Un altro obiettivo più ambizioso della modularità è
la riusabilità dei componenti software. Se progettati bene e soprattutto
se documentati, alcuni moduli possono essere riutilizzati in altre applicazioni,
così come una stessa scheda elettronica potrebbe essere montata in
modelli diversi di televisore, con evidenti vantaggi derivanti dalla riduzione
dei costi.
Un ambiente Object-Oriented favorisce la modularità poichè
ogni classe è essa stessa un componente software indipendente. Esempi
di moduli in ambiente Object-Oriented possono essere considerati sia
le librerie DLL (a collegamento dinamico) e i componenti ActiveX in Visual
Basic che i Package in Java e, in generale, le librerie software.
La progettazione consisterà sia nel racchiudere gli oggetti individuati
per la risoluzione del problema, che sono tra loro correlati o meglio che
realizzano funzionalità correlate, nello stesso modulo (Progettazione
architetturale) e sia nel definire e progettare le classi di ogni modulo
(Progettazione dettagliata).
3) Codifica attraverso il linguaggio
di programmazione o l'uso di un ambiente di sviluppo.
Obiettivo di questa fase è scrivere il programma partendo dal risultato
della fase precedente, ovvero dal disegno software dei vari moduli e di tutte
le classi di ogni modulo. La codifica sarà realizzata usando uno specifico
linguaggio o ambiente di sviluppo. Mentre nella fase precedente si lavora
ad un livello di astrazione maggiore, non preoccupandosi tanto della
realizzazione di ciò che si sta definendo, in questa fase si usano
gli strumenti software a disposizione per implementare il disegno, ovvero
per trasformarlo in un software funzionante, facilmente modificabile e
possibilmente riusabile. Si avrà dunque a che fare , per esempio,
con procedure o function, con matrici, stringhe, con classi e oggetti. Come
già accennato i disegnatori software, che operano nella fase precedente,
non si preoccupano tanto degli aspetti relativi all'implementazione, tuttavia
risulta evidente che essi devono essere pienamente consapevoli degli strumenti
di realizzazione da utilizzare nella fase 3) per non progettare dei "castelli
fantastici che non si potranno mai costruire".
4) Testing.
Al termine della realizzazione dell'edificio progettato dall'ingegnere e
realizzato dall'impresa edile, il responsabile dei lavori, prima di consegnare
le chiavi in mano al cliente, esegue una verifica complessiva, controllando
tutto, anche se, per esempio, dai rubinetti dell'acqua del giardino fuoriesca
effettivamente acqua !!
In ambito software, in questa fase, il risultato dell'implementazione, cioè
il programma, viene provato per constatare, innanzitutto se vi sono errori
e poi se risponde alle attese del committente, ovvero se è conforme
alle specifiche iniziali.
Conclusioni
E' quasi superfluo notare come le fasi più delicate siano quelle iniziali. Infatti poichè l'output di una fase è l'input per la fase successiva, un errore commesso all'inizio del progetto si propagherà in modo disastroso nelle fasi successive.
L'adozione di una metodologia è garanzia
per un software di qualità e un software di qualità è
un programma realizzato senza troppi sforzi, facilmente modificabile e
potenzialmente riusabile.
Disegno del progetto software di tipo
Object-Oriented
Un'astrazione è una generalizzazione che consente di separare alcuni aspetti della realtà da altri irrilevanti per la nostra analisi.
Una cartina stradale della Puglia è un buon
esempio di astrazione del territorio Puglia, poichè mette in
luce solo alcuni aspetti, cioè la viabilità, trascurando
volutamente altri, quali per esempio le risorse del sottosuolo o le
strutture alberghiere. Così l'autista che deve viaggiare in Puglia,
guardando la cartina, potrà meglio concentrarsi su ciò
che realmente gli interessa.
Nella fase di progettazione software, il progettista ha necessità
di astrarre dai dettagli relativi all'implementazione e deve poter disegnare
il software da un punto di vista concettuale. Ecco che l'oggetto, incapsulando
sia dati che codice, è uno strumento validissimo per questo scopo.
La programmazione orientata agli oggetti è nata proprio per produrre
modelli della realtà.
Il vantaggio dello sviluppo object-oriented nella soluzione dei problemi
è che dalle specifiche è agevole ricavare gli oggetti della
soluzione software (un semplice modo è quello di individuare i sostantivi
più significativi) e, una volta definiti e progettati gli oggetti,
la codifica object-oriented è altrettanto facile.
Se per esempio si deve risolvere il problema della realizzazione di un
elaboratore di testi, sicuramente nelle specifiche si farà riferimento
a termini quali documento, riga di testo, parola, carattere,
margini, immagine ecc. Ecco i potenziali oggetti di una soluzione
object-oriented, ognuno dei quali avrà determinati attributi e
comportamenti in corrispondenza di determinati eventi.
Il processo di individuazione degli oggetti di una soluzione software non
è univoco ed è un'attività abbastanza creativa che dipende
molto dalle capacità e dall'esperienza del progettista. In generale
in un progetto object-oriented occorrerà
- individuare gli oggetti della soluzione;
- definire i relativi attributi e metodi;
- definire le relazioni tra gli oggetti.
Ecco ora un esempio di disegno
software object-oriented:(2)
1) Identificazione degli oggetti
principali.
Nella prima fase del disegno si devono individuare i principali oggetti correlati
con il problema e con la sua soluzione. Prendendo in esame l' analisi dei
requisiti, generalmente gli oggetti principali si identificano con i principali
sostantivi.
2) Individuazione degli attributi
degli oggetti principali
Gli attributi rappresentano caratteristiche che descrivono l'oggetto, quali
forma, colore, dimensione etc. Essi possono essere a loro volta istanze di
classi, ovvero oggetti.
Per esempio nel disegno di un gioco "Battaglia navale", la Mappa dove
avverrà la battaglia può essere sicuramente considerato un
oggetto principale, ed essa può avere come attributi le celle in cui
saranno collocate le navi. Ogni cella può essere considerata, a sua
volta, istanza di una classe generica Cella, quindi oggetto, con attributi
quali: forma, dimensione e colore della cella, il tipo di nave che contiene
etc.
In tale fase il progettista fa uso del processo logico dell'astrazione, ovvero
egli deve individuare e selezionare per ogni oggetto principale gli attributi
essenziali per la risoluzione del problema, trascurando volutamente gli attributi
non necessari per la realizzazione del programma.
3) Individuazione degli oggetti
secondari e dei relativi attributi.
Un oggetto secondario può essere definito come un attributo di un
oggetto principale che è, a sua volta, un oggetto. In questa fase,
dunque devono essere definiti tutti gli attributi di tutti gli oggetti
individuati in modo iterativo, dall'alto verso il basso, ovvero dagli oggetti
principali fino agli ultimi oggetti della gerarchia che via via si sta
delineando.
4) Disegno di una gerarchia
delle classi.
L'obiettivo di questo passo è quello di disegnare in qualche forma
una rappresentazione della gerarchia delle classi che finora si sono definite.
Nella rappresentazione si dovrebbero mettere in evidenza le classi, con le
loro sottoclassi e le dipendenze evidenziando sinteticamente anche gli attributi
di ogni classe.
5) Identificazione e definizione
dei principali metodi per gli oggetti principali e
secondari.
Partendo dagli oggetti principali, in questa fase, si definiscono i metodi
con i relativi parametri e i risultati prodotti da ogni metodo. In questa
fase si procede in modo top-down, ovvero partendo dalla definizione dei metodi
delle classi in alto nella gerarchia si procede verso il basso utilizzando
la rappresentazione di gerarchia delle classi creata nella fase precedente.
6) Sviluppo di un prototipo
di soluzione utilizzando i metodi degli oggetti.
Questo passo dovrebbe essere fatto contestualmente con lo svolgimento
del precedente. Si individua una bozza di soluzione del problema utilizzando
i metodi degli oggetti definiti, senza però entrare nei
dettagli ed in forma molto generica.
7) Rielaborazione delle classi
per renderle più generiche, possibilmente riusabili e per raggrupparle
in moduli.
Si dovrebbe ridefinire la struttura delle classi per renderle
maggiormente generiche e quindi riusabili, introducendo, ove è possibile
delle classi astratte. Una classe astratta è una classe che
non ha istanze, ma viene definita per essere usata come classe antenata
di nuove classi che erediteranno da essa.
Inoltre le classi che realizzano uno stesso servizio, ovvero funzionalità
correlate, verranno inglobate nello stesso modulo.
Questo è tutto per ora. Nella seconda parte ci sarà meno teoria e inizieremo a discutere le specifiche di un gioco, con la relativa progettazione object-oriented applicando la metodologia precedentemente presentata. Infine nell'ultimo articolo sarà presentata la codifica in Java del progetto.
Bibliografia:
(1) "Principi e Tecniche di Progettazione Software"
di Barbuti, Bella, Degano, Levi - Ed. Franco Angeli
(2)
"Objective-C
Object-Oriented Programming Techniques"
di Pinson, Wiener - Ed. Addison-Wesley