Nella scorsa puntata è stato introdotto l’uso di un comodo strumento open-source per la realizzazione di diagrammi UML, è stato mostrato come creare gli elementi base e come interconnetterli tra loro. Continuiamo in questa analisi per mostrare come creare rappresentazioni UML più complesse e come generare codice dal relativo diagramma. Si analizzerà inoltre come utilizzare nella pratica gli strumenti finora forniti.
Nella precedente puntata è stato proposto come esempio pratico da realizzare il cosiddetto “programma Pizza”, il quale ha lo scopo di descrivere le caratteristiche (prezzo, forma, etc.) di una pizza appunto; si tratta di un esempio semplice che consente di apprezzare le funzionalità del software StartUML. La figura 1 riporta la parte di diagramma che era stato realizzato nella scorsa puntata:
erano state aggiunte le classi Rectangle e Circle e l’interfaccia IShape, inoltre si era creata una relazione tra di esse. Dopo questo breve riassunto possiamo proseguire aggiungendo la classe Pizza, come già descritto per le altre. Inserire come campo privato _price di tipo double. Aggiungere, inoltre, il metodo getPrice che restituisca come tipo double. Per mettere in relazione la classe Pizza con l’interfaccia IShape, selezionare la prima e fare click sulla relazione DirectedAssociation, presente nella toolbox; eseguire il drag and drop dalla classe Pizza verso l’interfaccia IShape. Selezionare la freccia appena aggiunta e nel campo Name della sezione Properties inserire has-a; nel campo End1.Aggregation impostare il valore AGGREGATE. Modificare il valore di End2.Name con _shape, in questo modo sarà aggiunto automaticamente un campo privato chiamato _shape. Impostare il valore di End2.Visibility a private.
Inserimento di un costruttore
I costruttori sono dei particolari pezzi di codice utilizzati nei principali linguaggi ad oggetti per inizializzare l’istanza di una classe, quando questa viene creata. Per aggiungere un costruttore con StartUML alla classe Pizza, fare click con il tasto destro su di essa e selezionare Operation. Seguire la normale procedura per l’inserimento di un funzione, specificando però come parametri di ingresso price e IShape. La stessa procedura deve essere ripetuta anche per la classe Circle (specificare come parametro di ingresso radius) e Rectangle (specificare i parametri di input width e height). A questo punto il diagramma UML dovrebbe apparire simile a quello riportato in figura 2.
Generazione di codice Java
Per generare codice Java dal diagramma appena descritto, selezionare il menu Tools e quindi Generate Code, come mostra la figura 3.
Da questa finestra di dialogo, selezionare il modello desiderato (se non sono state apportate modifiche il suo nome sarà Model1) e fare click sul tasto Next. Scegliere l’opzione Select All per generare codice per tutte le classi definite nel diagramma e quindi fare click su Next. Indicare il percorso in cui salvare i relativi file e premere Next. Nel menu Option Setup, accertarsi che le checkbox Generate the Document by JavaDoc e Generate empty JavaDoc siano entrambe selezionate. Tutte le altre opzioni dovrebbero essere deselezionate. Quindi premere Next. StartUML genererà il relativo codice. Fare click su Finish per uscire dalla finestra di dialogo. A titolo di esempio si riporta nel listato 1 il codice di inizializzazione della classe Pizza.
// // // Generated by StarUML(tm) Java Add-In // // @ Project : Untitled // @ File Name : Pizza.java // @ Date : 04/08/2008 // @ Author : // // public class Pizza { public Object _price; public IShape _shape; public void getArea() { } public void Operation1(Object price) { } }
Listato 1 |
Ovviamente, tale codice costituisce la base per la realizzazione del programma vero e proprio. Queste istruzioni sono infatti solo il prototipo di tutti i metodi della classe, bisognerà aggiungere quello che effettivamente essa deve eseguire.
Reverse engineering
La reingegnerizzazione o ingegneria inversa (nota soprattutto con il termine inglese reverse engineering) è il processo di prendere qualcosa (un dispositivo, un componente elettrico, un programma software, etc.) e analizzar ne in dettaglio il funzionamento, solitamente con l’intenzione di costruire un nuovo dispositivo o programma che faccia la stessa cosa senza in realtà copiare niente dall’originale; ovvero realizzare un secondo dispositivo, componente o programma in grado di interfacciarsi con il primo. StartUML è in grado di creare una classe a partire da codice preesistente, ossia l’operazione inversa a quella descritta nel paragrafo precedente. Questa funzionalità è molto utile quando si dispone già di codice di cui si vuole avere una rappresentazione schematica (per fini di documentazione ad esempio) oppure se si vuole modificare del codice precedentemente creato con StartUML, con l’obiettivo di aggiornarne il relativo diagramma. Per fare questo selezionare Tools->Java->Reverse Engineer. Selezionare la directory che contiene il codice Java (estensione .java) e fare click su Add oppure Add All. Fare click su Next. Impostare il modello desiderato e selezionare Next. Accertarsi che:
» le opzioni public, package, protected e private siano selezionate;
» l’opzione Create the field to the Attribute sia selezionata.
A questo punto fare click su Run ed al termine del processo selezionare Finish.
Il caso pratico: linee guida
Con questi primi tre articoli si sono fornite sia le basi teoriche dell’UML che gli strumenti pratici per mettere in pratica quanto descritto. Il concetto fondamentale che si è cercato di fornire è che un progetto per lo sviluppo di un sistema non può basarsi sull’improvvisazione ma deve seguire un iter tecnico-logico che consenta di arrivare in tempi brevi alla soluzione migliore del problema. Come è stato messo più volte in evidenza, è necessario seguire un ben preciso iter, una sorta di “tracciato” che deve venire incontro alle esigenze del cliente. Spesso si parla di RAD (acronimo di Rapid Application Development), ovvero lo sviluppo rapido di applicazioni, che consiste, fondamentalmente, di cinque sezioni:
■ 1-raccolta delle informazioni;
■ 2-analisi;
■ 3-disegno;
■ 4-sviluppo;
■ 5-deployment.
Questa azione consiste, a sua volta, di parecchie altre azioni. Iniziamo ad analizzarle una per una tenendo presente sempre che è di fondamentale importanza capire bene i requisiti che il cliente richiede. Soltanto così si otterranno dei sistemi stabili e robusti.
Processo di scoperta del Business
In questa fase, gli analisti studiano i processi di business del cliente servendosi di colloqui specifici con il cliente stesso e chiedendogli di analizzare a fondo i processi rilevanti, passo per passo. Di solito, al termine di tale attività vengono abbozzati uno o più Activity Diagrams.
Analisi del Dominio.
L’analista intervista il cliente con lo scopo di capire bene le entità principali del dominio del cliente. Alla conversazione tra l’analista ed il cliente, prende parte anche un altro membro del team il quale prende accuratamente nota di tutto. In particolare, si cerca di porre particolare attenzione ai termini chiave del dominio che vengono appuntati come possibili Classi. Al termine di tale analisi, alcuni termini dell’analisi diverranno attributi mentre determinate azioni, che sono, anch’esse, ritenute di rilevante importanza, saranno etichettate come operazioni delle classi. Al termine di tale sezione si produce un Class Diagram ad alto livello ed una buona serie di appunti).
Identificazione della possibile correlazione tra sistemi
All’inizio del processo di sviluppo, il team di sviluppo identifica esattamente le dipendenze tra i vari sistemi, ovvero da quali eventuali sistemi esistenti il nuovo sistema dovrà dipendere e, viceversa, quali sistemi dovranno dipendere dal nuovo. Il responsabile di tale fase è, solitamente un System Engineer. Al termine di tale sezione si produrrà un Deployment Diagram.
Identificazione dei requisiti di sistema
Questa fase rappresenta la prima sessione di sviluppo misto (Joint Application Development - JAD). Infatti, ad essa partecipano i responsabili dell’organizzazione del cliente, i potenziali utenti ed i membri del team di sviluppo. Può essere utile la presenza di un supervisore che si pone come obiettivo quello di riuscire a carpire dai responsabili e dagli utenti ciò che essi realmente desiderano dal sistema. Almeno due membri del team dovrebbero prendere appunti e rifinire il Class Diagram disegnato nella precedente fase di Analisi del Dominio.
Presentazione dei risultati al cliente
Quando il team reputa concluse le operazioni di raccolta delle informazioni, il Project Manager presenta i risultati di tale analisi al cliente. A questo punto, il team è pronto per andare a fondo sui risultati ottenuti dalla raccolta delle informazioni e approfondire, dunque, la conoscenza del problema. Alcune delle azioni di Analisi iniziano, in realtà, proprio durante la fase di raccolta delle informazioni quando viene abbozzato il Class Diagram.
Comprensione dell’utilizzo del sistema
In una sessione JAD (Joint Application Development) con i potenziali utenti, il team di sviluppo lavora con gli utenti per definire gli actors che interagiscono con ogni singolo use case sia come beneficiari che come iniziatori dello stesso use case. E’ questo il momento in cui vengono prodotti gli Use Case Diagrams.
Rifinire i Class Diagrams
La persona incaricata di modellare gli oggetti, durante la sessione JAD, dovrà porre la massima attenzione alle discussioni e alle richieste dei clienti al fine di rifinire i vari diagrammi delle classi. Tale operazione può consistere nel dare dei nomi appropriati alle classi, alle associazioni, alle classi astratte, alle generalizzazioni ed alle aggregazioni (per la comprensione di tali termini si vedano le puntate precedenti). E’ questo il momento in cui il Class Diagram diviene più dettagliato.
Analizzare i cambi di stato negli oggetti Durante la creazione dei modelli, sarà importante anche porre attenzione alla descrizione di eventuali cambi di stato di un oggetto, dove questo si renda necessario. Vengono prodotti in questa fase gli State Diagrams.
Definire le interazioni tra gli oggetti
Fino ad ora il team di lavoro è arrivato a mettere giù un insieme di Use Cases e di Class Diagrams più o meno rifiniti. E’ ora tempo di definire come gli oggetti descritti interagiranno tra di loro. Il responsabile della descrizione dei modelli dovrà sviluppare un insieme di diagrammi che includano i cambi di stato. A questo punto sono prodotti i Sequence Diagrams ed i Collaboration Diagrams.
Il System Engineer
Analizzare l’integrazione del sistema da sviluppare con gli altri sistemi preesistenti. Il System Engineer, procedendo in parallelo con tutte le fasi descritte sin qui, scopre ed analizza tutti i dettagli relativi alla integrazione del sistema che si intende sviluppare con eventuali sistemi pre-esistenti o comunque sistemi con i quali sarà necessario cooperare. Le domande che sarà opportuno porsi per tale operazione saranno qualcosa del tipo: Quale tipo di comunicazione viene utilizzata? Come è fatta l’architettura della rete? Il sistema dovrà interagire con un database? Se si, con quali tipi di database? In tale fase verranno costruiti i Deployment Diagrams.