MokaByte
Numero 08 - Maggio 1997
|
|||
|
Java Program |
||
Giovanni Puliti |
|
||
Introduzione
Una delle caratteristiche
principali di Java è quella della portabilità del codice
che grazie all'astrazione della JVM permette di eseguire senza modifiche
lo stesso programma in codice
bytecode, su
ogni tipo di piattaforma che supporti la macchina virtuale definita da
Sun.
Tale
portabilità è intrinseca alla natura del linguaggio, per
cui in teoria è sufficiente utilizzare Java come piattaforma di
sviluppo per ottenere una applicazione multipiattaforma.
In realtà
le cose non sono così immediate e possono insorgere problemi legati
ad una non corretta mentalità di programmazione multipiattaforma:
non si tratta infatti di carenze del linguaggio o di bug della JVM, ma
piuttosto di problematiche derivanti dalle diversità che sussistono
fra le varie architetture su cui si vuole eseguire la propria applicazione
Java.
Sun ha pensato di affrontare il problema definendo il 100% Pure Java (100PJ) Program: tale progetto prevede, tra le altre cose, il rilascio della documentazione relativa all'analisi del problema, l'organizzazione di corsi, e la definizione di alcuni meccanismi per la certificazione 100PJ Application.
Il processo di certificazione prevede in caso di applicazioni conformi con lo standard 100%PJ la possibilità di loghizzare il pacchetto e la registrazione negli archivi Sun,
potendo
usufruire da parte della casa di forme di trattamento privilegiate.
Al momento è
presto per dire se tale iniziativa avrà successo o meno, ma anche
se l'operazione è sicuramente interessante, credo che in buona parte
possa essere considerata come l'ennesima trovata pubblicitaria, un po'
sullo stile del logo Pentium inside o dei PC marchiati per Win 95.
Tutti questi stemmi e controstemmi in alcuni casi si sono rivelati utili,
ma molto più spesso è stato il mercato a dettare le regole:
che ne dite di un PC non compatibile con Win 95? C'è bisogno di
avere lo stemma attaccato?
Il sito relativo al programma 100PJ è, un tipico esempio di quello che in genere definisco, forse senza troppa originalità, bel-web (non cercate di analizzare il significato di bel in inglese scompattando le varie lettere, significa semplicemente ed ironicamente bello): buona parte del sito ha una bella grafica, titoli accattivanti ma in definitiva è un po' inconcludente, ed i concetti sono ripetuti più volte in varie parti dei documenti ipertestuali.
La parte più interessante è contenuta nel cookbook: come suggerisce il titolo si tratta di una serie di ricette per il programmatore al fine di evitare di intraprendere strade pericolose.
Nella prima parte di questo articolo sono riportate le regole principali per progettare una applicazione 100PJ; successivamente sono analizzati i principali problemi che possono portare a codice non portabile e le tecniche per risolvere il problema. Dove possibile sono riportate anche le eventuali soluzioni alternative per scavalcare il problema.
In
questa prima parte dell'articolo parleremo dei problemi legati alla portabilità,
mentre nella seconda parte, che verrà pubblicato il mese prossimo,
parleremo degli aspetti relativi alle applet ed ai Java Beans, sperando
che nel frattempo Sun rilasci la documentazione relativa, attesa per la
metà del mese di maggio. Verrà inoltre analizzata la suite
di programmi che Sun mette a disposizione per testare le proprie classi
Java.
Definizione di 100% Pure Java
Il manuale del
cuoco provetto riporta una serie di consigli su come evitare di incorrere
in situazioni non portabili. La documentazione originale riporta una parte
introduttiva sui concetti elementari legati alla portabilità: nella
maggior parte dei casi si tratta di concetti ormai noti anche ai neofiti,
per cui penso di tralasciare questa sezione.
Portabilità e Purity
Il primo punto interessante è quello legato alla definizione di portabilità: allo stato attuale della tecnologia, la diffusione di architetture diverse fra loro, rende alquanto difficile dare una definizione univocamente valida relativamente al concetto di codice portabile.
Si potrebbe ad esempio dire che portabile è quel programma che produce gli stessi risultati su architetture diverse, ma in realtà tale definizione è alquanto imprecisa, se si pensa ad esempio ad una routine che semplicemente ricava il nome del sistema operativo e lo stampa a video. Per il tipo di obiettivo prefissato si potrebbe dire che si tratta di codice portabile per antonomasia, eppure a rigore porta a risultati differenti su ogni tipo di piattaforma diversa. Anche se l'esempio è banale, si capisce come non sia semplice proporre una definizione universalmente valida del concetto di codice portabile.
Visto che in definitiva la portabilità è legata alla funzionalità di una applicazione, Sun propone il concetto di Purity: visto che il significato di tale termine è intuitivo, per evitare imbarazzanti traduzioni, lo userò in lingua originale.
Secondo tale termine il problema della portabilità viene considerato guardando dal basso in alto dalla interfaccia della piattaforma (connessione JVM <-> hardware), piuttosto che dal punto di vista dell'utente.
La purity non è perfettamente equivalente alla portabilità, ma è un buon modo per garantirne la presenza. In modo molto diplomatico viene tralasciato il problema di fornire l'esatta definizione di purity, ed invece viene descritta una procedura per accertare se il codice in questione risponde alle caratteristiche di purity.
Il progetto 100PJ prevede una serie di test da effettuare sulla base di regole proposte da Sun e che verranno esposte in questo articolo. Vediamo adesso di analizzare precisamente le regole principali per costruire una applicazione 100PJ secondo le indicazioni fornite da Sun: per ogni aspetto sono proposte le varie soluzioni, e dove possibile la strada alternativa da seguire.
Regola numero zero: autocontenimento
Considerazioni relative alle applet e JavaBeans
Anche se le problematiche
di Purity analizzate fin ora relativamente alle application sono ripetibili
per le applet e per i JavaBeans, bisogna tener conto del fatto che una
applet viene eseguita all'interno di un browser, e che quindi prendere
in considerazione i vincoli dettati dalle varie implementazioni del security
manager ed i protocolli di comunicazioni usati in Applet/AppletContext.
Discorso analogo
può esser fatto per i JavaBeans per i quali bisogna fare ulteriore
attenzione relativamente ai protocolli di comunicazione ed alla sicurezza
dell'ambiente che li ospita.
Al momento Sun
non ha ancora ufficialmente rilasciato nessun documento ufficiale in merito
a questo argomenti, anche se si attende qualcosa per il mese di Maggio
1997.
Ricette per massimizzare la portabilità
Vediamo adesso di esporre alcuni trucchi per evitare di incorrere in implementazioni poco portabili: cercheremo dove possibile di fornire la soluzione al problema e/o una strada alternativa per scavalcare il punto critico. La schematizzazione riportata nella documentazione della Sun è molto chiara, per cui mi scuseranno i lettori più critici se anch'io seguirò tale schema a scapito di originalità.
Problema: meccanismo di scheduling dei thread
Soluzione: anche se Java permette di evitare di preoccuparsi dei dettagli legati al coordinamento del lavoro parallelo, solo attraverso l'implementazione manuale di una specifica politica di organizzazione dei thread si ha la garanzia di evitare di incorrere in soluzioni pericolose. Per chi volesse approfondire tali argomenti, si suggerisce la lettura di Concurrent Programming in Java (di Doug Lea Addison Wesley 1997 ISBN 0-201-6958-2), che affronta tali aspetti in modo specifico per Java.
Alternativa: una soluzione bruta al problema potrebbe essere quella di sincronizzare tutti i thread, in modo da forzare il flusso del programma nelle cosiddette zone critiche. Questa soluzione anche se non molto elegante, permette di individuare eventuali anomalie di progettazione, trasformando una silente ed errata interpretazione della JVM del flusso delle operazioni, in un deadlock: si tratta di una soluzione del tipo alla caccia dei bug, e richiede ulteriori modifiche al codice quando si individuano problemi.
Maggiori chiarimenti sulla programmazione multithread si possono trovare nell'articolo Threading Programming: introduzione teorica alla programmazione multithreading in Java apparso in
Soluzione: se proprio non potete evitare di utilizzare codice nativo, ecco cosa fare per ridurre al minimo i danni
Si tenga comunque conto del fatto che in ogni caso anche utilizzando il fallback il programma sarà sempre di difficile certificazione 100PJ. e sicuramente meno portabile di uno scritto interamente in Java.
Si tenga presente che la java.lang.Runtime.exec non è affatto portabile, che non tutte le piattaforme mettono a disposizione applicazioni eseguibili e che, infine, non sempre è disponibile lo standard input o output.
In ogni caso sicuramente l'applicazione compilata non è portabile, o semplicemente il formalismo di denominazione non è univoco per tutte le piattaforme.
Soluzione: siate prudenti - figliuoli ;).
Soluzione: usare sempre la classe File per ogni riferimento al filesystem, ed usare le proprietà di sistema, come ad esempio il carattere path separator, per eseguire tutte le operazioni di I/O.
Inoltre una soluzione molto portabile è quella di usare un file dialog per lasciare all'utente la responsabilità di sbagliare. Intercettare ogni tipo di eccezione legata ad errori di sintassi dei nomi è buona norma.
Soluzione: usare println in output o il carattere platform dependent line.separator. In input usare i metodi readLine legato terminazione delle linee ma
Soluzione
E' sicuramente preferibile usare interfaccie grafiche per interagire
con l'utente ove possibile, o perlomeno predisporre in alternativa anche
tale soluzione.
Per l'interpretazione
dei comandi, la soluzione migliore sarebbe non usare parametri a linea
di comando, ma in certi casi risulta essere l'unica soluzione attuabile,
come ad esempio nel caso di esecuzioni batch.
Si può
ovviare al problema usando la convenzione POSIX, che offre una notevole
standardizzazione.
In alternativa
si prenda sempre in considerazione l'uso di una GUI o di un file, dettagliatamente
documentato, contente i parametri operativi. Nel caso che si usino applet
si può fare largo uso del tag <PARAM> facilmente gestibile.
Soluzione Anche se negli ultimi tempi stanno proliferando tool di sviluppo Visual qui e Visual là, si ricordi che una delle nuove caratteristiche Java sono i cosiddetti layout manager, ma per la loro difficile messa a punto spesso si preferisce posizionare gli oggetti con tre mosse di mouse.
La programmazione visuale è senza dubbio molto comoda, e permette di creare interfaccie grafiche dall'aspetto sicuramente più accattivante. Uno dei compiti all'interno di MB è, fra le altre cose, di curare la grafica, e nello svolgere tale lavoro cerco sempre di dare un bell'aspetto alla rivista rimanendo però nei vincoli del limitato html. A che serve una bella grafica se non tutti la possono vedere, o se in alcuni casi rende scomoda la lettura? Personalmente preferisco sempre affidarmi alla stupidità del layout manager del html, compensando le varie lacune con un grosso sforzo di fantasia. Spero di non risultare troppo presuntuoso ed anzi se qualcuno di voi avesse da criticare qualcosa sull'impaginazione ecco la mia mail: puliti@infomedia.it.
In definitiva direi di non fare troppo affidamento ai magici ambienti di sviluppo visuale, ed il consiglio è quello quindi di tener ben presente il tipo di target che volete dare alla vostra applicazione, e di scegliere di conseguenza la strada da seguire. Chi volesse avere maggiori chiarimenti sui layout manager può leggere l'articolo di Marie Alm in .
Sempre per mantenere la portabilità grafica è bene ricavare gli attributi grafici di sistema attraverso routine apposite: per mezzo di chiamate a metodi come java.awt.Toolkit.getScreenSize(), o java.awt.SystemColor class si possono parametrizzare le applicazioni in funzione dell'ambiente in cui operano.
Per i font attenzione al fatto che solo alcuni sono multipiattaforma, e dal JDK 1.0 al 1.1 ci sono state delle variazioni. Alla luce di questa breve parentesi, chi di voi mi sa dire come mai ho scelto questo tipo di font per MB?
Abbiamo parlato in più punti di implementare soluzioni alternative da lanciare in funzione dell'ambiente in cui si esegue il programma. Sicuramente questo aumenta le dimensioni del codice, ed il relativo sforzo per garantire la 100PJ, ma garantisce ovviamente maggiori garanzie.
Per lanciare la routine adatta in funzione del sistema utilizzato si può ad esempio utilizzare i valori restituiti da java.class.version o os.name.
Eventualmente
bisogna decidere dove e come lanciare l'alternativa: se prevenire è
meglio che curare si può implementare una tecnica di prevenzione
utilizzando, in anticipo i valori restituiti dalle routine precedenti;
tale strategia può essere utilizzata se l'applicazione svolge compiti
mission critical o ad esempio deve gestire dati importanti in ambienti
distribuiti. Se invece non necessitano particolari attenzioni e protezioni,
intercettare le eccezioni è la soluzione più semplice da
implementare e da gestire.
Test
Abbiamo fin ora
preso in considerazione le tecniche per evitare a priori i problemi legati
alla programmazione multipiattaforma. La fase successiva prevede eventualmente
il test dell'applicazione per mezzo di routine appositamente rilasciate
da Sun per verificare la Purity del programma.
Conclusione
Concludiamo qui questa prima parte. Il mese prossimo parleremo della suite di test 100PJ, e delle nuove specifiche rilasciate da Sun: ricordo a tal proposito che la documentazione attualmente rilasciata da Sun è in continuo aggiornamento e modifica, per cui al momento in cui leggerete tale articolo sarà possibile riscontrare alcune incompatibilità con quanto rilasciato in rete.
Per chi volesse approfondire gli argomenti trattati ecco un alcuni indirizzi utili
per maggiori informazioni sull'uso di Java
|
||
|
||
MokaByte ricerca
nuovi collaboratori
|
||
|