Introduzione
Nel
corso dei mesi estivi ho sviluppato il progetto in modo da aggiungere nuove
importanti funzioni (gestione di piu' di un documento, supporto esteso
al C, configurabilita', utilizzo delle Swing ecc) fino ad arrivare a quel
momento cruciale in cui un software collassa per le troppe modifiche. Era
giunta l'ora, mi accorsi mio malgrado, di gettare tutto alle ortiche e
di ricominciare da capo.
Questa
operazione, nota in letteratura come reengineering, consiste nel costruire
qualcosa di nuovo che svolga la stessa funzione di qualcosa di esistente
ma che lo faccia in maniera radicalmente diversa. L'esperienza accumulata
nello sviluppo del prototipo e' decisiva per definire le basi del nuovo
progetto.
Prima
di gettarmi in questa nuova impresa pero' ho voluto intraprendere lo studio
dell'Ingegneria del Software, ed e' cosi' che sono venuto a conoscienza
dell'Unified Modeling Language, noto anche con l'acronimo UML.
Con
questo articolo voglio proporre un'esperienza di progettazione Object Oriented
riprendendo in mano l'idea iniziale di costruire un semplice editor, ricorrendo
fin dal principio al supporto dell'UML.
Allo
scopo di rendere questo articolo utile ad un pubblico quanto piu' vasto
possibile, non faro' nessuna assunzione su conoscenze preesistenti di UML,
e cerchero' di produrre codice java commentato e di facile comprensione.
Prologo: preparazione
dell'ambiente di lavoro
Oltre
all'indispensabile JDK1.2 (o superiore), tengo sempre con me la documentazione
ufficiale e i sorgenti delle API (potete trovarli nel file src.jar nella
root del jdk dopo averlo scompattato con WinZip)
Infine
occorre un modeler UML: il Rational Rose Student Edition (www.rational.com/rose
sezione download) e' gratuito e va benissimo per cominciare.
UML in poche parole
UML
e' una notazione grafica utile nel processo di progettazione Object Oriented.
Utilizzando i diagrammi UML (ne esistono sette tipi, ma in questo caso
ne usero' solo tre) si possono modellare i diversi aspetti di un sistema
software.
Un
primo enorme vantaggio di tale notazione e' che dona una sorta di
"esistenza materiale" al software, permettendo di gestirne meglio la fase
di progettazione e di manutenzione.
Si
possono realizzare diagrammi UML con l'ausilio di appositi tool di sviluppo
(simili a programmi di disegno) che eseguono anche un certo controllo
semantico.
Il
piu' famoso di questi tool e' Rational Rose.
Iniziamo i lavori:
definiamo il problema
Vorrei
un programma che mi permetta di editare un sorgente Java (alla maniera
del Wordpad), salvarlo, compilarlo ed eseguirlo con la semplice pressione
di un pulsante. Vorrei anche vedere l'output del compilatore su una
finestra separata da quella dell'editor.
La
richiesta e' molto vaga, ma corrisponde a quanto un ipotetico committente
potrebbe richiedere. Per prima cosa provo a costruirne un modello con uno
Use Case Diagram.
L'omino
e' un Attore, i palloni sono Use Case, mentre le frecce mostrano una connessione
tra i primi e i secondi o tra uno Use Case ed un'altro.
Il
nostro utente puo' creare un nuovo documento, aprirne uno esistente, salvare
quello corrente, editarlo, compilarlo e farlo partire. Alcune di queste
azioni hanno come conseguenza l'avvio di un altro Use Case.
Questo
diagramma fornisce una visione ad altissimo livello del progetto: ho definito
cosa fa il programma, ma non ho fatto ancora nessuna assunzione sul come.
Persino un programma complesso come Photoshop puo' essere ridotto ad una
famiglia di diagrammi simili a questo, senza scendere nel dettaglio.
Con
un diagramma di questo tipo posso esporre la mia visione del sistema ad
un ipotetico committente, e assicurarmi di aver capito cosa mi e' stato
richiesto. Durante una colazione con amici ho riscontrato come un paio
di questi semplici disegnetti sia di per se sufficiente per provocare un
interessante brainstorming.
Cerchiamo un po'
di aiuto
Prima
di cominciare a lavorare si puo' cercare qualche scorciatoia, tipo una
API o una libreria che aiuti a risolvere una parte del problema. Il componente
JTextArea del package javax.Swing svolge "gratis" tutte le funzioni di
editing che servono in questa occasione, e pertanto lo includo fin dal
principio nel progetto.Possiamo dedicarci allo sviluppo del progetto da
un livello piu' alto, senza la preoccupazione di gestire l'editing di testo
a basso livello (un problema niente affatto banale!)
Il dominio applicativo:
definizione delle prime classi
Un'analisi
dell'enunciato puo' essere di aiuto nello scovare le classi del Dominio
Applicativo, vale a dire gli oggetti "del mondo reale" con cui il nostro
programma dovra' interagire. L'unica cosa che so per ora e' che devo trattare
i seguenti oggetti:
-
Un sorgente Java (un file *.java)
-
Un Compilatore (javac)
-
Una JVM (java)
ognuno
dei quali racchiude il comprtamento di un qualcosa di preesistente. Per
modellare in UML queste classi posso ricorrere ai Diagrammi di Classe
I tre
rettangoli qui sopra sono caratterizzati da un nome (in alto) da attributi
(in mezzo) e da operazioni (in basso). Accanto ad ogni attributo c'e' un
lucchetto che li caratterizza come privati. Il simbolo accanto alle operazioni
le denota come pubbliche.
Di
Javac e di JVM so per certo che dovranno, rispettivamente, compilare ed
eseguire un sorgente java.
Il
JavaDocument racchiude il testo di un sorgente (attributo source), il File
in cui verra' salvato, il nome della classe e quello del sorgente. Come
operazioni definisco insertString() e remove() per agire sul testo, getFile()
e setFile() per richiedere o modificare il file di destinazione, getClassName()
e getSourceName() per chiedere il nome del sorgente e della classe.
Le
frecce tratteggiate indicano che le classi Javac e JVM eseguono operazioni
sulla classe JavaDocument (si puo', ad esempio, immaginare che Javac chieda
al JavaDocument il nome del file da compilare).
Alcune classi
di supporto
Il
seguente diagramma ne fornisce una vista molto stilizzata del componente
JTextArea.
C'e'
una classe Document che racchiude un testo (inteso come una "collezione
di caratteri"). La classe JTextArea fornisce una vista grafica sul Document
di sua proprieta' (il possesso e' simboleggiato dalla freccia solida).
Le operazioni cut(), copy() e paste() provocheranno un cambiamento nel
Document attraverso una opportuna combinazione di insertString()
e remove().
La
classe EditorKit contiene alcune operazioni utili a maneggiare il documento.
A me interessano solo read() e write() che permettono di caricare un file
da disco e di salvare il documento corrente.
Mi
serve anche un oggetto Console che mostri all'utente l'output del compilatore.
Senza scendere nei dettagli la rappresento cosi'
Per
tenere insieme il sistema e fornire un interfaccia utente creo una classe
MiniPad
Mettiamo tutto
insieme
A
questo punto posso provare a mettere tutto assieme e a vedere cosa emerge
C'e'
una classe MiniPad che fornisce all'utente di le operazioni newDocument(),
openDocument(), save(), saveAs(), exit(), compile(), runProgram() e stopProgram();
una classe Console che permette all'utente di vedere l'output del compilatore
(non sappiamo ancora come), una classe JTextArea che da' modo all'utente
di leggere e scrivere il JavaDocument.
Seguendo
le frecce si puo' anche immaginare come avviene la comunicazione tra i
componenti: ad esempio se l'utente chiama il metodo compile() il MiniPad
eseguira' le seguenti operazioni (in pseudo-java):
JavaDocument
doc = JTextArea.getDocument();
Javac.compile(doc);
Di
conseguenza il Javac chiamera' il metodo bindOutput() sull'oggetto Console.
In
verita' questo diagramma e' ancora distante dall'implementazione (anche
se sotto certi aspetti la suggerisce) poiche' non fornisce un grado di
dettaglio adeguato.
In
compenso e' semplice e chiaro, e potete provare ad illustrarlo a vostra
madre avendo una buona probabilita' di farle capire cosa intendete fare
(il discorso non vale se vostra madre e' Ingegnere Nucleare!)
Martin
Fowler (autore di UML Distilled) definisce diagramma di classe con questo
livello di dettaglio Diagramma di Specifica.
Il
mese prossimo procedero' verso un Diagramma di Classe Implementativo.
Quindi
procedero' a creare il modello di comunicazione tra oggetti usando i Diagrammi
di Sequenza. E per finire presentero' una implementazione completa e funzionante
di questo progetto.
Bibliografia e
Letture Consigliate
"UML
Distilled" second edition Martin Fowler
ADDISON-WESLEY
"Open
Sources Voices from the Open Source Revolution"
Edited by Chris DiBona, Sam Ockman & Mark Stone O'Reilly
"Tutto
Sherlock Holmes" Arthur Conan Doyle
Newton Compton Edition
disponibili anche su http://members.tripod.com/~msherman/holmes.html
|