|
Java: Arte e tecnica
Come si scrive un applet
Dario de Judicibus
Scriverne uno semplice, magari del tipo “Hello,
World!”, Φ una delle prime prove che si fanno quando si impara Java. Proveremo a
farlo anche noi, ponendoci un obiettivo un po’ pi∙ ambizioso: quello di costruire un
vero e proprio modello su cui basare tutti gli applet che scriveremo in futuro
Scrivere un applet non Φ difficile. Scriverne uno buono lo pu≥
essere, o almeno richiede un po’ di cura e una certa disciplina. Se poi stiamo
scrivendo un applet da distribuire via Internet, magari includendo il sorgente, allora
dobbiamo fare le cose per bene. Ed Φ esattamente lo scopo che ci prefiggiamo in
quest’articolo. Ma andremo anche oltre; infatti vi proporremo un possibile modello di
applet che potrete usare come base per i vostri programmi. Per quanto semplice, cercheremo
di fornire uno scheletro abbastanza completo che tenga conto di diverse possibilitα quali
poi potranno servire in applet di un certo spessore. Il codice completo del modello e
tutti i file a esso collegati sono riportati sia nel CD-ROM allegato alla rivista sia sui
siti della testata e dell’autore. Per ragioni pratiche, la descrizione
dell’articolo conterrα solamente alcuni spezzoni di codice fra quelli ritenuti pi∙
significativi. Se possibile, vi consigliamo di stampare il codice AppletTemplate.java prima di leggere l’articolo. Il codice Φ stato scritto utilizzando un
normale editore di test, poi Φ stato caricato in VisualCafΘ 2.0 per il collaudo,
evitando di fare uso di classi o funzioni specifiche di questo prodotto, cos∞ da
permettere il suo utilizzo in qualunque 100% Pure Java IDE. A ogni modo, dato che la
versione 2.0 di VisualCafΘ si basa sul JDK 1.1.3, questo sarα il livello di riferimento.
Al momento in cui scriviamo dovrebbe essere in circolazione la 1.1.5 e ovviamente la beta
della 1.2. Per il momento la cosa Φ ininfluente. Nello scrivere il modello sono stati
presi in considerazione due aspetti. Innanzi tutto si Φ curato l’aspetto di
documentazione dell’applet, sia per quello che riguarda i commenti nel codice, vuoi
quelli standard vuoi quelli utilizzabili dal comando javadoc, sia per quello che riguarda
le funzioni di aiuto in linea dell’applet stesso. In secondo luogo, si Φ definita
una struttura standard che contiene sia metodi fondamentali, quali init() e paint(), sia alcune tecniche sviluppate appositamente per questo articolo. In realtα,
il modello contiene anche alcuni esempi su come si realizzano certi accorgimenti, e non Φ
quindi uno scheletro puro, ma un vero e proprio mini-tutore per gli applet Java. I
commenti sono stati scritti volutamente in inglese, dato che chi di solito distribuisce il
sorgente via Internet si rivolge fondamentalmente a un’audience internazionale.
C’Φ codice e codice
Prima di affrontare il codice vero e proprio, spendiamo due parole su javadoc. Questo
comando Φ un semplice programmino capace di leggere il codice che avete scritto e di
produrre una prima documentazione in Html pi∙ o meno sullo stile di quella fornita con il
JDK. Θ molto utile se si sviluppano vere e proprie API che dovranno poi essere utilizzate
da altri. Il programma, oltre a generare il codice Html relativo alle vostre classi e
metodi, produce paragrafi che possono essere definiti dal programmatore utilizzando
speciali commenti nel codice sorgente. Tali commenti devono essere compresi fra una
sequenza di apertura "/**" e una di chiusura "*/". All’interno di
questi commenti, oltre ai normali tag Html, possono essere utilizzati degli ulteriori tag
che verranno esplosi dal programma come riportato nella tabella 1.
Si consiglia tuttavia di evitare tag del tipo <H1> e
<H2> dato che essi sono utilizzati giα da javadoc nello strutturare la
documentazione. Per vedere in pratica cosa si ottiene lanciando questo programma a fronte
dell’applet qui presentato, andate nella stessa directory in cui c’Φ il
sorgente AppletTemplate.java che avete stampato e caricate nel vostro browser i vari
.html. Pu≥ essere inoltre utile confrontare le varie pagine con il sorgente originale per
verificare come javadoc abbia trattato i commenti speciali. Il comando pu≥ essere
utilizzato per generare sia la documentazione relativa a una specifica classe, come nel
nostro caso, sia per generare la documentazione per tutte le classi di un package, e quindi di una gerarchia di classi. In quest’ultimo caso javadoc produce
un file Html per ciascuna classe, uno per ciascun package, pi∙ tre
file Html per l’intera gerarchia: packages.html (che contiene
la lista di tutti i package di cui la gerarchia Φ composta),
tree.html (che contiene lo sviluppo a albero della gerarchia stessa) e AllNames.html che rappresenta un vero e proprio indice analitico di tutte le classi della
gerarchia con i loro metodi. Nel nostro caso, oltre ai tre file generali abbiamo solo il
file per l’applet, dato che la nostra classe non fa parte di alcun package. La documentazione Φ generata per tutti i pacchetti, le classi, le interfacce,
le eccezioni, i metodi e le variabili pubbliche o protette, ma non per quelle private, a
meno che non sia esplicitamente richiesto con l’apposita opzione. Questo perchΘ il
comando Φ stato pensato per documentare le API a quanti dovranno usarle i quali, in
preciso accordo con i principi della programmazione orientata agli oggetti, non dovrebbero
aver bisogno di conoscere i dettagli interni di un oggetto per poterlo usare. Quando
lanciate, il risultato che otterrete si deve presentare pi∙ o meno cos∞:
[I:\devel\Java\INews\Mag98]
javadoc AppletTemplate.java
Symantec Java! JustInTime Compiler Version 210.063 for JDK 1.1.3
Copyright (C) 1996-97 Symantec Corporation
Generating package.html
Generating documentation for class AppletTemplate
Generating index
Sorting 9 items...done
Generating tree
Commenti specializzati
Le opzioni pi∙ importanti di questo comando sono: -d directory, che permette di
generare i file Html in una directory differente da quella corrente, -sourcepath path,
che permette di specificare il cammino di ricerca dei sorgenti da documentare, e –verbose,
che fornisce quanta pi∙ informazione possibile durante il caricamento e la generazione
delle pagine Html. La lista completa dei comandi Φ riportata in tabella 2.
E veniamo ai commenti speciali utilizzati nel modello.
Generalmente, Φ bene scrivere un commento per ogni classe o interfaccia, e uno per ogni
metodo; se sono presenti variabili pubbliche o protette sarebbe opportuno utilizzare un
commento speciale anche per ognuna di esse. Di solito, non Φ invece necessario
specificare dei commenti speciali per tutte quelle componenti private o locali che non
sono visibili esternamente alla classe. Un esempio di commento speciale per un metodo Φ
il seguente:
/** * Decode a color string whose format must be "#RRGGBB" * @param color
Default color if string cannot be decoded * @param colorString String to decode
* @return Decoded color */
Per quello che riguarda i commenti interni al codice, cioΦ che servono a renderlo
semplicemente pi∙ leggibile, ma che non vengono utilizzati da javadoc, il sorgente inizia
con un’intestazione la quale, oltre a riportare alcune utili informazioni sul
programma, contiene anche quelle affermazioni legali che servono a dichiarare i diritti
d’autore e eventuali protezioni sui possibili danni derivanti dall’uso del
programma. Se pensate di distribuire il vostro sorgente, vi consigliamo di aggiungere
sempre affermazioni di questo tipo; se, viceversa, intendete distribuire solo il codice
oggetto o l’eseguibile, aggiungete queste affermazioni in due file di testo a parte
che provvederete a chiamare copyright.txt e legal.txt, oppure direttamente nel read.me.
Fra i commenti utilizzati per rendere pi∙ leggibile il sorgente, Φ buona abitudine
mettere accanto a ogni variabile di classe e di oggetto un breve commento che ne spieghi
l’utilizzo, per esempio:
private String ivText = null ; // text to display
private String ivString =
"domain.net" ; // variable part of text
private int ivInteger = 42 ; // insets private
char ivCharacter = ‘@’ ; // separator for ivText
Abbiamo inoltre utilizzato la convenzione di far iniziare le variabili di classe con cv
e quelle dell’istanza con iv in modo da distinguerle immediatamente nel sorgente
dalle variabili locali.
Un altro aspetto, squisitamente di documentazione per un applet, Φ quello di scrivere
sempre due metodi standard che potranno essere richiamati da altre classi per ottenere
informazioni sull’applet stesso. Il primo si chiama getAppletInfo() e ha lo scopo di
ritornare una stringa che contiene una breve descrizione dell’applet e eventualmente
informazioni di copyright e/o sull’autore. Il secondo si chiama getParameterInfo(), e
ritorna la lista dei parametri utilizzati dall’applet con una breve descrizione del
tipo di parametro e del suo significato. Tanto per intenderci, questi sono i parametri che
vengono specificati nel codice Html con il tag <PARAM> all’interno del blocco
<APPLET></APPLET>; per esempio:
public String[][] getParameterInfo( ){ String[][] info = { { "aString" , "string" , "just a string of text - def: domain.net" }
, { "anInteger" ,
"integer" , "just an integer - def: 42" }
, { "aCharacter"
, "character",
"just a character - def: @" }
, { "aColor" ,
"color" , "just a color - def: white" }
} ; return info ;
}
Gli esempi non mancano
Per quanto riguarda il codice vero e proprio, il nostro modello utilizza un thread per
garantire un buon funzionamento del codice anche quando lo stessa applet Φ caricato pi∙
volte nella stessa pagina. Tuttavia ci≥ implica che, se utilizzate questo modello per
accedere a risorse esterne, dovrete assicurarvi che i metodi coinvolti abbiano il
modificatore synchronized per evitare che due diverse istanze dello stesso applet si diano
vicendevolmente fastidio. In futuro approfondiremo anche quest’argomento, per ora, se
volete, potete anche eliminare il codice relativo a ivAppletThread, specialmente se
pensate di utilizzare un applet solo di questo tipo per ogni pagina. Nel metodo init()
abbiamo poi mostrato alcuni esempi di lettura dei parametri specificati con il tag
<PARAM>. Oltre a parametri semplici, come le stringhe, che non richiedono alcuna
conversione, abbiamo introdotto un esempio di conversione effettuata con la tecnica del wrapping,
e precisamente a un intero, un esempio di conversione effettuata direttamente con una
chiamata a un metodo, ottenendo un carattere, e una in cui un oggetto complesso (come un
colore) viene ricavato dalla sua rappresentazione RGB esadecimale utilizzando un metodo
privato appositamente scritto: decodeColor(), ovverosia
private Color decodeColor( Color
color, String colorString ){
Color test ; try { test = Color.decode( colorString ) ; }
catch( NumberFormatException exc )
{
test = color ;
}
return test ;
}
Altri due utili metodi sono getPreferredSize() e stringLocation(); permettono di
calcolare automaticamente le dimensioni ideali dell’applet in funzione del suo
contenuto. Nel caso di un’applet semplice garantiscono un dimensionamento corretto
solo quando viene caricato, ma non nel caso che il suo contenuto vari. Tuttavia, essi
permettono di calcolare la dimensione pi∙ adatta di un oggetto grafico anche quando
cambia purchΘ faccia parte di un layout, come vedremo quando parleremo delle classi AWT.
Infine, abbiamo proposto un esempio di paint(). Questo metodo Φ il cuore degli applet
grafici non basati sulle classi AWT, ed Φ spesso importante anche per queste ultime. ╚
infatti il metodo che disegna fisicamente l’applet. Nel nostro caso esso disegna la
stringa di testo formata dal concatenamento di una stringa statica, del carattere di
separazione fornito come parametro, e della stringa di testo data in ingresso
all’applet, il tutto reso su un fondo il cui colore Φ quello ottenuto con il metodo
decodeColor().
Un’ultima considerazione. In due dei metodi della classe AppletTemplate, viene
intercettata un’eccezione chiamata NullPointerException. Tale operazione si rivela
necessaria in quanto i metodi in questione non sono chiamati solo dal codice
esplicitamente, ma potrebbero essere eseguiti dietro richiesta del sistema, dato che
getPreferredSize() Φ anche un metodo standard della classe Container, di cui Applet Φ
una sotto-sottoclasse, e che potrebbe venire automaticamente chiamato se il contenitore fa
parte di un layout qualora quest’ultimo dovesse modificare le sue dimensioni. In
questo caso Φ possibile che tali metodi vengano eseguiti quando ivText Φ ancora nullo,
generando cos∞ l’eccezione in questione che, se non intercettata, manderebbe in
abend il programma. Ecco che ancora una volta si pu≥ toccare con mano la robustezza e
l’affidabilitα del linguaggio Java, che costringe il programmatore a prevedere fin
dall’inizio eventuali situazioni anomale, dato che il compilatore non accetta di
generare la classe se l’eccezione non Φ in qualche modo gestita.
(ddejudicibus@tecnet.it)
Tag |
A fronte di |
Genera |
@see classe |
Classe
Variabile |
Collegamento
ipertestuale alla classe, al metodo, o alla classe specificata del tipo “See
also”. I parametri di un metodo vanno separati da uno spazio bianco, per esempio: @see ddj.applet.LogonPanel
@see LogonPanel
@see LogonPanel#getPassword
@see LogonPanel#setPassword(String)
@see LogonPanel#ANONYMOUS
@see <a href="logon.html">Logon Info</a> |
@version versione |
Classe |
Versione della classe.
Questa Φ semplicemente una stringa a vostro piacere. Potete utilizzare livelli del tipo
1.5.2, date, o qualunque altro identificativo vogliate, tipo "BETA" o
"Golden"; per esempio: @version 1.5.8
– 15 Jan 1999 |
@author autore |
Classe |
Nome dell’autore.
Per pi∙ autori ripetete il tag, uno per ogni nome, per esempio: @author Dario de Judicibus |
@param parametro
descrizione |
Metodo |
Nome di un parametro
passato a un metodo e sua descrizione, per esempio: @param width Width of the logon panel |
@return descrizione |
Metodo |
Descrizione
dell’oggetto restituito da un metodo, per esempio: @return True if user is authorized |
@exception classe
descrizione |
Metodo |
Nome e descrizione
dell’eccezione che "potrebbe" essere emessa dal metodo in questione. ╚
bene specificare sia le eccezioni generate direttamente dal metodo sia quelle non gestite
e passate al chiamante, per esempio:
@exception
PasswordNotSuppliedException if a non-anonymous
user did not provide a password
|
@since testo |
Classe
Metodo
Variabile |
Indica che
l’elemento in questione Φ stato introdotto a partire da (since) una ben
specifica versione o data, per esempio: @since
version 1.4.7 – 19 Oct 1997 |
@deprecated
testo |
Classe
Metodo
Variabile |
Indica che un certo
elemento, sebbene ancora supportato, non dovrebbe pi∙ essere utilizzato e andrebbe
sostituito da un altro elemento analogo, per esempio: @deprecated Replaced by getUserid() |
Tabella 1 - Tag utilizzati da javadoc
- Opzione
|
- Significato
|
-public |
Genera la documentazione
solo per le classi, i metodi e le variabili pubbliche. |
-protected |
Genera la documentazione
sia per le classi, i metodi e le variabili pubbliche, sia per quelle protette. Questa Φ
la norma. |
-package |
Genera la documentazione
solo per le classi, i metodi e le variabili pubbliche, protette e di pacchetto. |
-private |
Genera la documentazione
per tutte le classi, i metodi e le variabili. |
-Jflag |
Passa flag
direttamente al sistema, per esempio, per far s∞ che il sistema riservi 16MB per
memorizzare la documentazione generata, bisogna scrivere
- javadoc -J-mx32m -J-ms32m
<classes> ...
|
-encoding name |
Indica eventuali
specifiche di codifica, quali , per esempio, EUCJIS\SJIS , differenti da quelle standard. |
-docencoding name |
Specifica il nome di
codifica del file Html generato. |
-version |
Aggiunge alla
documentazione un tag @version, dato che non Φ previsto un default se non Φ presente
nel sorgente. |
-author |
Aggiunge alla
documentazione un tag @author, dato che non Φ previsto un default se non Φ presente
nel sorgente. |
-noindex |
Non produce
l’indice dei pacchetti, altrimenti generato. |
-notree |
Non produce la gerarchia
delle classi e delle interfacce, altrimenti generata. |
-d directory |
Specifica la directory
dove javadoc dovrα memorizzare i documenti generati. |
-verbose |
Richiede
l’emissione di tutti i messaggi relativi alle operazioni di produzione della
documentazione. |
-sourcepath path |
Specifica il cammino di
ricerca per i file sorgente, quelli cioΦ con estensione java. |
-classpath path |
Specifica il cammino di
ricerca per le classi che servono a eseguire javadoc. In genere non
c’Φ bisogno di specificare questa opzione. |
-nodeprecated |
Esclude i paragrafi
marcati con il tag @deprecated. |
Tabella 2 - Opzioni di javadoc
|