MokaByte Numero  41  - Maggio 2000
MiniPad
Come progettare e 
implementare un editor Java 
con compilatore in linea
II parte
di 
Andrea Gini
Diagramma di Implementazione e passaggio al codice

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 e' molto piu' facile spostare qualche freccia su di un diagramma piuttosto che riscrivere centinaia di righe di codice! Quello che voglio e' definire una vera e propria riproduzione in scala di quella che divertera' 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 e' indipendente dalla volonta' 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 piu' bella e completa API grafica del mondo (YEAH!).

Una delle prerogative piu' affascinanti del package SWING e' 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 e' "New", la cui icona e' "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 piu' divertente e' 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

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



laddove la classe Gui e' 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 e' 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.)
 
 
 

Ereditarieta' e specializzazione
Prima di procedere faccio un'ultima considerazione: che differenza c'e' 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

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

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 e' il vero motore dell'innovazione nel campo dello sviluppo del software, e java consacra questo principio grazie al costrutto dell'ereditarieta', che altro non e' 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



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

A questo punto il modello e' 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 e' 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



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 dal'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 e' 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, puo' visitare il sito

www.lib.disco.unimib.it/students/ginian/jinipad
e scaricare una copia di JiniPad, che affronta (e risolve) problematiche piu' avanzate come:

- Syntax Highligth
- Gestione Multidocumento
- Supporto trasparente di java, C, C++ e HTML
- Configurabilita'
- Possibilita' di scegliere tra vari compilatori e VM (come javac e jikes)
- Interfaccia grafica avanzata, con Skin, trasparenze ecc.
- Estensibilita' tramite Plug-In

Il progetto (che amplia la struttura del MiniPad), e' interamente documentato in UML, e ogni sviluppo prevede una fase preliminare di analisi e discussione. E' 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
 

Chi volesse mettersi in contatto con la redazione 
può farlo scrivendo a mokainfo@mokabyte.it