[Parte 2Parte 3]

La programmazione
orientata agli oggetti:
tecniche per lo sviluppo dei programmi.
Francesco Colucci     I° parte
 fcoluc@tin.it

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


In un disegno software di tipo object-oriented l'elemento cardine attorno al quale si basa il progetto è l'oggetto. Poichè un oggetto è un'astrazione, un progetto object-oriented è sicuramente più semplice da realizzare rispetto ad uno che non preveda l'uso degli oggetti. Il progettista, pensando ad un oggetto, astrae dai dettagli della rappresentazione in memoria dei dati dell'oggetto e dalla realizzazione dei suoi metodi, poichè lo considera solo come un'entità con precisi attributi e caratteristiche e un determinato comportamento. L'oggetto è il componente ideale per rappresentare oggetti del mondo reale.

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