Home   |   Archivio   |   Chi siamo   |   Contatti
Andrea Gini
MiniPad - Come progettare e implementare un editor Java con compilatore in linea
II parte
di
Andrea Gini
Il mese scorso ho analizzato un problema facendo un uso elementare di alcuni diagrammi UML. Nell'ultimo diagramma illustrato avevo individuato una struttura convincente. Prima di buttarmi nell'implementazione vorrei compiere un ulteriore passaggio di analisi, e individuare in anticipo i problemi che potrebbero sorgere in fase implementativa: ormai ho capito che è molto più facile spostare qualche freccia su di un diagramma piuttosto che riscrivere centinaia di righe di codice! Quello che voglio è definire una vera e propria riproduzione in scala di quella che diventerà un'applicazione java, attingendo questa volta alla mia personale esperienza di programmatore.

Interfaccia utente

La scorsa volta avevo completamente trascurato l'aspetto grafico dell'applicazione. La mia attenzione era rivolta alla definizione del dominio applicativo, e il dominio applicativo è indipendente dalla volontà di creare un'applicazione a finestre o un programma a console. Mi spiego: Word 2000, Vi ed Emacs, per quanto siano tre programmi completamente diversi tra loro nell'aspetto e nell'interfaccia utente, sono comunque dei programmi di videoscrittura. Essi risolvono lo stesso problema, e condividono lo stesso dominio applicativo. In definitiva essi potrebbero nascere dallo stesso diagramma di specifica. Ma nel passaggio all'implementazione entrano in gioco fattori come i servizi offerti dalle API di sistema o le abitudini degli utenti.

Per nostra fortuna con Java disponiamo della più bella e completa API grafica del mondo (YEAH!).

Una delle prerogative più affascinanti del package SWING è la definizione di un nuovo approccio alla gestione degli eventi grafici. La classe AbstractAction (ovvero le sue sottoclassi) raduna in un unico posto:

  • l'azione vera e propria
  • il suo nome
  • un'icona
  • lo stato (attivato-disattivato)

Ecco una classe di esempio che definisce una Action il cui nome è "New", la cui icona è "new.gif" che la chiamata del metodo newDocument() nella classe MiniPad.

public class NewAction extends AbstractAction
{
  public NewAction()
  {
    super("New",new ImageIcon("new.gif"));
  }
  public void actionPerformed(ActionEvent e)
  {
    miniPad.newDocument();
  }
}

La cosa più divertente è che, se voglio creare un bottone che esegua questa azione, non devo fare altro che creare un'istanza di NewAction ed aggiungerla (col metodo add(Action a)) ad una JToolbar. La stessa cosa se voglio un elemento su un menu a tendina:

JToolBar toolbar = new JToolbar();  // crea la toolbar
JMenu menu = new JMenu();           // crea il menu
Action newAction = new NewAction(); // crea l'azione
// aggiunge alla toolbar un bottone che esegue l'azione NewAction
// e che viene presentato con l'immagine "new.gif"
toolbar.add(newAction);
// aggiunge un JMenuItem con il nome "New"
menu.add(newAction);

Ecco una rappresentazione della gerarchia delle MPAction:

Figura 1 - Gerarchia delle MPAction
Figura 1 - Gerarchia delle MPAction

dove MPAbstractAction definisce un costruttore e delle costanti comuni.

Per illustrare la relazione tra utente, Action, MiniPad e Gui creo il seguente diagramma:

Figura 2 - Relazione tra Action e Gui
Figura 2 - Relazione tra Action e Gui

laddove la classe Gui è una sottoclasse di JFrame che definisce i seguenti metodi:

  • getDocument() restituisce il documento su cui si sta lavorando
  • setDocument() setta il documento corrente
  • getConsole() restituisce la console

L'utente osserva la Gui (che fornisce una vista sullo stato del sistema), ma agisce sul sistema attraverso le Action. Questa separazione funzionale è invisibile all'utente, che ha l'impressione, quando preme un pulsante, di agire direttamente sull'interfaccia grafica (ho ripreso questo framework dal modello MCW delle Swing, in particolare studiando il sorgente della classe JTextArea e dei suoi antenati.)

Ereditarietà e specializzazione

Prima di procedere faccio un'ultima considerazione: che differenza c'è tra un editor Java con compilatore in linea e un editor c con compilatore in linea? Nessuna, visto che entrambi i programmi condividono lo stesso dominio applicativo!

Per creare un framework generale posso agire in questa maniera:

  • definisco una superclasse astratta AbstractMiniPad, il cui costruttore chiama i metodi createDocument(), createCompiler() e createVM().
  • creo un documento MPDocument che raccolga gli attributi e le operazioni valide per ogni tipo di documento di testo.
  • Infine definisco l'interfaccia di programmazione necessaria per implementare un compilatore e una VM.
Figura 3 - Diagramma principale
Figura 3 - Diagramma principale

In questo diagramma ho definito la classe JavaMiniPad come sottoclasse (specializzata) di AbstractMiniPad.

JavaMiniPad sovrascrive i metodi createDocument(), createCompiler() e createVM() in modo da creare al volo (senza sovrascrivere il costruttore) le classi SunJavac e SunJvm (che implementano rispettivamente le interfacce MPCompiler e MPVirtualMachine) e la classe JavaDocument, sottoclasse di MPDocument.

Figura 4 - JavaMiniPad
Figura 4 - JavaMiniPad

Con un piccolo lavoro aggiuntivo ho risolto il mio problema, e allo stesso tempo ho fornito ai miei colleghi di tutto il mondo una soluzione pronta all'uso per creare editor C, C++, Pascal o quant'altro.

Una volta ho letto questa frase: "ricorda che i bravi programmatori scrivono del buon codice, mentre i programmatori eccezionali lo copiano alla grande". In effetti il saccheggio è il vero motore dell'innovazione nel campo dello sviluppo del software, e java consacra questo principio grazie al costrutto dell'ereditarietà, che altro non è che una forma di scippo legalizzato. Per lenire i sensi di colpa cerco di progettare le mie classi in modo da semplificarne il riuso e fornisco, quando possibile, il codice sotto licenza GPL (vedi www.gpl.org)

La comunicazione tra oggetti: i Diagrammi di Sequenza

Prima di implementare posso modellare in UML gli scambi di messaggi tra oggetti. Un Diagramma di sequenza come il seguente mostra lo sviluppo dell'azione di compilazione

Figura 5 - Diagramma di sequenza della compilazione
Figura 5 - Diagramma di sequenza della compilazione

Un Diagramma di Sequenza mostra come gli oggetti comunicano tra loro durante lo svolgimento di una specifica attività. Si leggono dall'alto verso il basso e da sinistra verso destra (seguendo la numerazione). Ogni freccia (corrispondente ad una chiamata di metodo) è numerata per indicare la precisa sequenza delle azioni. I rettangoli gialli rappresentano oggetti (istanze di classi), e pertanto è possibile mostrare nello stesso diagramma istanze diverse della stessa classe, nel caso siano coinvolte in una stessa operazione.

A questo punto il modello è abbastanza dettagliato da suggerire con precisione l'implementazione:

public void compile()
{
  MPDocument doc = _gui.getDocument();
  Process  _runningCompiler=_compiler.compile(doc);
  Console c = _gui.getConsole();
  c.bindOutput(_runningCompiler,"Compiler");
}

Verso l'implementazione e oltre: la Generazione di Codice

Un'interessante funzione di Rational Rose è la generazione di codice: una volta completati i diagrammi delle classi, possiamo ottenere magicamente il codice java degli scheletri delle classi. Tutta la documentazione prodotta sul modello viene automaticamente aggiunta come javadoc!

Ho realizzato una semplice implementazione, che potete trovare qui MiniPad.zip.

Figura 6 - Screenshot dell'applicazione
Figura 6 - Screenshot dell'applicazione

Come si vede dallo screenshot, l'utente ha a disposizione una JTextArea per l'editing e una per l'output del compilatore. Le funzioni (open, save, compile ecc....) sono accessibili attraverso i pulsanti (disegnati dall'amico Andrea Anzani) e sono replicate sul menu a tendina "File". Il Programma rispetta le specifiche definite inizialmente, e rappresenta un buon punto di partenza per un Editor. Chiaramente è ancora lontano dall'essere un programma completo e ricco di funzioni: tocca a voi ora migliorarlo.

JiniPad: un progetto Open Source

Chi fosse interessato all'argomento Editor, può visitare il sito

www.lib.disco.unimib.it/students/ginian/jinipad

e scaricare una copia di JiniPad, che affronta (e risolve) problematiche più avanzate come:

  • Syntax Highligth
  • Gestione Multidocumento
  • Supporto trasparente di java, C, C++ e HTML
  • Configurabilità
  • Possibilità di scegliere tra vari compilatori e VM (come javac e jikes)
  • Interfaccia grafica avanzata, con Skin, trasparenze ecc.
  • Estensibilità tramite Plug-In

Il progetto (che amplia la struttura del MiniPad), è interamente documentato in UML, e ogni sviluppo prevede una fase preliminare di analisi e discussione. È un progetto Open Source, per cui vi invito ad utilizzarlo, a metterci le mani sopra e a scrivermi se avete critiche o suggerimenti.

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

"Occhio nel Cielo" Philip K. Dick Fanucci Editore

MokaByte® è un marchio registrato da MokaByte s.r.l. 
Java®, Jini® e tutti i nomi derivati sono marchi registrati da Sun Microsystems.
Tutti i diritti riservati. E' vietata la riproduzione anche parziale.
Per comunicazioni inviare una mail a info@mokabyte.it