MokaByte Numero  43  - Luglio Agosto 2000
 
Applicazioni 
stand-alone in Java
Parte prima
di 
Lavinio Cerquetti
Teoria e pratica di un’applicazione stand-alone in Java

E' questa la prima parte di una miniserie composta da tre articoli che pubblichiamo con molto piacere. Una analisi di una storia veramente avvincente oltre che sicuramente molto interessante ed istruttiva.

Introduzione
Chiunque si appresti alla lettura di questo articolo ha, molto probabilmente, un’esperienza diretta di Java: lo avrà utilizzato per realizzare almeno un applet o, più probabilmente, un servlet. Qualcuno, poi, potrebbe aver avuto l’occasione di implementare degli Enterprise JavaBean, degli agenti, o di sperimentarne le doti di integrabilità in ambienti misti C/C++, o in congiunzione a linguaggi di scripting come Perl e Python, magari nella realizzazione di soluzioni server-based. Java, infatti, è un linguaggio per sua natura multiforme, che ha saputo finora dare il meglio di sé nella realizzazione di prodotti middleware e nell’implementazione di soluzioni basate su Web ed Internet, ma comunque e sempre prive di una specifica interfaccia grafica lato utente: in altre parole, non esiste nessuna killer application stand-alone realizzata in Java, e chi si è cimentato nell’impresa – bastino i nomi di Corel ed IBM – ha dovuto ridursi a più miti consigli.
Si può discutere se il concetto di killer application mantenga ancora la sua validità in un mondo basato su applicazioni distribuite e decentralizzate, o se – addirittura – non possa essere definito come tale l’intero insieme di soluzioni CORBA/Enterprise JavaBean/Web/XML imperniate su Java, e che da esso non possono in alcun modo prescindere.
Sta di fatto, comunque, che il ruolo delle applicazioni stand-alone è, ed è destinato a rimanere per i prossimi anni, ancora centrale e ad influenzare fortemente la visione che la più parte delle persone avrà dell’informatica – specialmente di quella cosiddetta “professionale” - così come sta di fatto, purtroppo, che in questo mondo il linguaggio Java è ancora un grande assente.
I motivi di questa aporia sono, o sono stati, molteplici:
 
  1. L’oggettiva penalizzazione nelle performance causata dalla pseudo-compilazione dei programmi Java in una sorta di linguaggio macchina indipendente dalla CPU (tecnicamente detto p-code [1]) che garantisce sì la portabilità delle applicazioni realizzate con questo linguaggio, ma al prezzo di una loro sostanziale esecuzione in modalità interpretata;
  2. un ulteriore aggravio nelle prestazioni causato dall’alta flessibilità del linguaggio (reflection, introspection e caricamento ed aggiornamento dinamico delle classi) e dalla sua predilezione nei confronti degli oggetti non riusabili, cosa che porta ad un alto numero di allocazioni di memoria, per di più tutte eseguite sullo stack;
  3. l’enormità di API, interfacce e protocolli da apprendere: infatti, l’approccio multipiattaforma di Java ha obbligato Sun a realizzare un vero e proprio “sistema operativo virtuale” in grado di isolare completamente le applicazioni dal bisogno di colloquiare in prima persona con il sistema operativo sottostante, e nel caso delle applicazioni stand-alone – le quali necessitano di un’interfaccia grafica evoluta e della possibilità di gestire dati audio/video - la mole delle librerie da studiare può, senza tema di smentita, dirsi scoraggiante;
  4. il tempo necessario perché Sun riuscisse a rendere stabili le suddette API: e chi ne ha risentito maggiormente sono state proprio le API delegate alla gestione dell’interfaccia grafica e dei dati multimediali, fulcro degli applicativi stand-alone, e che, dopo un traviato percorso durato non meno di quattro anni (e ricco di vicoli ciechi ed errori di progettazione) solo negli ultimi 5-6 mesi, prima con il JDK 1.2.2 ed ora con la versione 1.3, hanno raggiunto una buona solidità ed efficienza;
  5. l’elevata richiesta di memoria degli ambienti di esecuzione dei programmi in Java, vale a dire le Java Virtual Machine, immediatamente comprensibile alla luce dei punti precedenti.


Quello che cercheremo di capire in questo articolo è se la situazione attuale costringa ancora il linguaggio Java a proporsi solamente come soluzione Web-based – nello scenario da me già descritto in [2] - o se sia invece realistico, ad un anno e mezzo di distanza, un suo utilizzo in tutte le casistiche di sviluppo e particolarmente in quelle, sino ad oggi considerate assolutamente ostiche al linguaggio di Sun, legate all’implementazione di software a carattere gestionale.
 
 
 

La scelta iniziale
Le idee e le riflessioni contenute in questo articolo si basano su un’esperienza reale, ancora in corso ed estremamente positiva: vale a dire la realizzazione di un applicativo stand-alone di tipo gestionale interamente in Java. Si tratta di una sfida che oggi si può dire vinta, ma che, nelle sue fasi iniziali, veniva considerata pura follia. Ed è proprio per spiegare le ragioni di questa sfida, per dimostrarne la sensatezza, e per convincere i lettori di MokaByte che ora i tempi sono maturi per realizzare applicativi stand-alone in Java, che non mi limiterò ad elencare tutte le scelte fatte nel corso della realizzazione del programma, ma cercherò di spiegare come e perché si arrivò a quelle scelte.
La storia di questo applicativo - il cui nome è Irmgard - inizia 9-10 mesi orsono, tra la fine di Agosto e l’inizio di Settembre 1999, quando si presentò a me ed ai miei collaboratori la possibilità di acquisire una commessa per la realizzazione di un software per la gestione di ditte di autotrasporti nazionali ed esteri.
I punti caratterizzanti di questo software avrebbero dovuto essere:

  1.  Solidità e sicurezza;
  2. potenza e facilità d’uso;
  3. una gestione a 360 gradi del workflow aziendale, dalla gestione dei documenti fiscali e dalla schedulazione ed ottimizzazione dei viaggi e degli itinerari dei mezzi di trasporto sino ad una completa e puntuale analisi dei costi, oltre a quelle attività collaterali di magazzino in conto deposito frequentemente effettuate dai trasportatori;
  4. possibilità di integrazione e di interscambio di dati in tempo reale con applicativi di contabilità commerciale ed industriale;
  5. capacità di comunicazione con applicativi di produttività personale (videoscrittura, tabelloni elettronici) per la realizzazione di circolari e rapporti analitici;
  6. disponibilità al pubblico, in tempo reale su Internet, delle informazioni di tracking sullo stato di consegna della merce.


Immediatamente cominciai a chiedermi se fosse possibile realizzare un progetto così ambizioso - una prima stima mi portò a prevedere un impegno di tre anni/uomo - in Java e, soprattutto, se fosse la scelta migliore per noi e per il cliente.
L’utilizzo cui sino a quel momento avevamo destinato il linguaggio Java era legato al Web ed alla realizzazione di servizi su Internet; quanto il know-how da noi posseduto in quel settore si sarebbe rivelato utile durante la realizzazione di un applicativo stand-alone ? Perché non continuare a seguire le nostre usuali metodologie di lavoro, utilizzando per quell’applicativo i tool di sviluppo comunemente ritenuti più consoni e performanti, quali Visual Studio e Delphi ?
Inoltre la portabilità di tale linguaggio– che sarebbe stato il motivo principale di una sua eventuale scelta per quel progetto – era poco più di un pio desiderio, in quanto non esisteva un ambiente Java di buon livello per quella che era l’unica valida alternativa a Windows - e che ora lo è ancora di più - vale a dire il Linux: in sostanza avremmo dovuto combattere con tutti i problemi del linguaggio di Sun e rinunciare alle comodità di Windows per ottenere un programma che di fatto avrebbe comunque potuto funzionare solamente sotto Windows.
Eppure, dopo diversi e sofferti giorni di riflessione mi resi conto che, se anche guardando alla situazione del momento non c’era un solo valido motivo per abbandonare strumenti e modalità di lavoro noti e consolidati ed allontanarsi dal mondo Windows, lo scenario mutava radicalmente se lo si osservava di lì a sei mesi, vale a dire quando avremmo cominciato a rilasciare le prime beta.

Infatti, i punti di forza della soluzione Java permanevano, mentre i dubbi ed i problemi sembravano perdere forza:
 

  1. Ritenni sufficientemente probabile che la questione delle performance problematiche di Java nell’utilizzo lato client, legate all’inefficienza ed alla pesantezza delle API Swing, sarebbero state risolte o dall’allora nascente tecnologia Hot Spot [3] o semplicemente dalla legge di Moore [4]: vale a dire, la CPU e la memoria richieste da Java, che allora sembravano spropositate, sarebbero state considerate accettabili entro sei mesi;
  2. IBM stava entrando con forza nei mercati Linux e Java, cosa che mi faceva ben sperare per la disponibilità di un JDK degno di questo nome anche sotto Linux;
  3. voci di corridoio riportavano di progetti da parte di Borland/Inprise, che aveva collaborato con Sun alla realizzazione del JDK 1.2 (ad esempio nella realizzazione del protocollo JavaBean), volti al porting del suo ambiente di sviluppo JBuilder sotto Solaris e Linux: questo ci avrebbe permesso eventualmente di spostare, o quanto meno di procedere in parallelo, allo sviluppo di Irmgard anche in quest’ultima piattaforma, conditio sine qua non – a mio avviso - per garantire un prodotto di qualità sotto tale sistema operativo.


In ragione di queste considerazioni, e dell’estremo interesse con cui tutto il mio team guardava al linguaggio Java – apprezzandone l’eleganza e la flessibilità, ma soprattutto il design pulito e moderno di gran parte del suo framework – decisi, tra i dubbi e gli scetticismi di molti miei colleghi, di imbarcarmi in quest’avventura.
Ci fu chiaro, fin dall’inizio, che la scelta fatta limitava molto i nostri margini di errore: non solo avremmo dovuto indovinare la scelta dei tool e delle metodologie da usare per lo sviluppo, ma – per compensare i limiti di performance del linguaggio di Sun – avremmo dovuto partire da una fase di modellazione particolarmente curata, che si sarebbe dovuta tradurre in un codice ben ottimizzato e di alta qualità, ed era già preventivabile il bisogno di ricorrere, in alcune situazioni limite, a qualche escamotage: insomma, una sorta di “ritorno all’antica” nello stile di programmazione, molto lontano dalla liberalità e dall’utilizzo a volte sproporzionato delle risorse di sistema che è patrimonio comune della programmazione in Windows.
 
 
 

Metodologie e tool di design
Se l’approccio da seguire nello sviluppo del programma non ha comportato grossi dubbi – abbiamo infatti seguito il nostro usuale approccio iterativo basato sul linguaggio UML [5], approccio descritto e raccomandato proprio dai suoi autori – leggermente più complessa si è rivelata la scelta del tool di modellazione da utilizzare.
Trovandoci a lavorare con Java ci sembrò naturale propendere per uno strumento realizzato proprio in tale linguaggio, e cominciammo quindi a vagliare ciò che il mercato poteva offrirci, tanto più che, trattandosi proprio di applicazioni in Java, studiarne il funzionamento anche solo dall’esterno ci avrebbe potuto fornire degli indizi sui problemi, di interfaccia e di performance, che di lì a breve ci saremmo sicuramente trovati a vivere in prima persona.
Purtroppo nessuno dei tool che avemmo l’occasione di testare ci convinse pienamente: alcuni erano semplicemente incompleti, altri non si dimostravano sufficientemente solidi. In particolare, ciò che ci colpì fu vedere come i tool più solidi fossero legati non solo alle API AWT (cosa che ci aspettavamo, considerando la situazione estremamente fluida in cui lo Swing si trovava in quel momento) ma anche ad una specifica JVM. In particolare, la JVM raccomandata da questi tool - e spesso inclusa direttamente all’interno della loro distribuzione - era quella di Microsoft.
I tentativi di utilizzarli con altre Java Virtual Machine, come quella Sun, si rivelarono infruttuosi: sia la velocità che la stabilità dei programmi degradava notevolmente, e ad ogni cambio di JVM si manifestavano nuovi bug nell’interfaccia, che arrivavano fino al punto di rendere l’intera applicazione inutilizzabile.
D’altro canto i tool realizzati in Swing erano notevolmente più lenti, e questa lentezza diveniva addirittura patologica nelle operazioni più pesanti per l’interfaccia grafica, quali lo scroll o il redraw delle finestre. Come se ciò non bastasse questi stessi tool mostravano dei preoccupanti bug nel disegno dell’interfaccia (menu che rimanevano aperti, sezioni di finestre non tracciate correttamente), bug che sembravano essere comuni alle diverse applicazioni, segno questo che il problema si trovava ad un livello superiore, probabilmente nello stesso Swing.
In sostanza i tool Swing ci sembrarono deludenti, per quell’impressione di “pesantezza” e di “sofferenza” che a più riprese ci comunicavano: utilizzandoli avevamo veramente l’impressione di torturare i nostri computer. Ci piacque però il design delle interfacce: esse si mostravano funzionali e pulite, così lontane dal widget bloating tipico del mondo Windows. “Con un po’ più di velocità e qualche bug in meno – ci dicemmo – questi programmi sarebbero sensazionali”.
Tirando le somme, decidemmo di continuare ad utilizzare il nostro tool di modellazione UML consueto, Rational Rose [6], ma di dare di tanto in tanto un’occhiata a quello che sembrava essere un prodotto promettente, e per di più open source: Argo UML [7].
 
 
 

Ambiente di sviluppo: strumenti e parco macchine
Era chiaro a tutti che un tassello fondamentale nel nostro progetto era la scelta degli ambienti di sviluppo, e immediata fu la scelta di puntare sul JDK 1.2 (pomposamente definito da Sun “Java 2”) optando quindi per una scelta Pure Java al 100%: infatti uno dei nostri obiettivi era sin dall’inizio quello di realizzare un’applicazione portabile, in grado di garantire un corretto funzionamento e prestazioni elevate su di una pluralità di piattaforme, e specificamente sotto Linux, non appena si fosse resa disponibile un’implementazione di qualità del JDK per il sistema operativo di Linus Torvalds..
Tuttavia anche se oggi tale scelta appare ovvia, la situazione si presentava - tra Settembre ed Ottobre dell’anno scorso - radicalmente diversa.
Le problematiche performance di Java e la constatazione del fatto che, nonostante le sue velleità multipiattaforma, il suo utilizzo lato client era limitato al mondo Windows – sia per l’orientamento che il mercato ancora aveva in quel momento, sia perché il Linux non era sufficientemente maturo come soluzione client, tanto più in ragione dell’assenza di una valida implementazione del linguaggio di Sun per tale piattaforma – avevano causato una dicotomia di fatto nel mondo Java.
Da un lato si stagliavano, con Sun, Borland/Inprise ed IBM, gli assertori del Pure Java, ovvero di soluzioni realizzate con le sole API ufficiali di tale linguaggio, e – perlomeno nelle intenzioni – portabili verso una pluralità di piattaforme.
Dall’altro lato, raccolto intorno a Microsoft, si trovava un discreto numero di ambienti di sviluppo che coniugavano il linguaggio Java con le API Windows, e spesso con una compilazione diretta delle applicazioni in file .exe, con evidenti benefici in termini di facilità di deployment e di performance. Forse qualcuno ancora ricorda lo slogan di Microsoft secondo cui Java veniva considerato, alla stessa stregua del C++, solamente come un altro linguaggio per la realizzazione di applicativi Windows. La stessa Microsoft aveva agio nel difendere tale posizione paragonando le buone prestazioni del suo ambiente di sviluppo proprietario in Java, basato sull’abbandono dello Swing e di parte delle JFC in favore di una diretta coesione con le API Windows, con tutti i problemi di performance e stabilità che affliggevano il mercato delle Pure Java IDE.
Compiuta quindi questa scelta di campo, che per nostra fortuna si è poi rivelata corretta - tutti gli ambienti di sviluppo della seconda schiera, molti dei quali erano dei veri e propri “nomi eccellenti”, oggi non esistono più o sono relegati ai margini del mercato, così come sono scomparse molte delle ditte che li producevano - bisognava però orientarsi nel mercato delle soluzioni Pure Java.
Anche qui, semplificando, si presentavano al nostro team due possibilità: utilizzare ambienti di sviluppo nativi in Windows, o puntare fin dall’inizio su IDE realizzate esse stesse interamente in Java. Di questo secondo gruppo valutammo Java Studio di Sun, prodotto in seguito lasciato morire, e NetBeans - successivamente acquisito da Sun proprio a rimpiazzo di Java Studio e ridenominato Forte For Java Community Edition [8], reso open-source [9] dalla stessa Sun all’inizio di Giugno - trovandoli entrambi assolutamente inutilizzabili: se alla lentezza ed ai bug delle applicazioni in Java si aggiungevano anche la lentezza ed i bug degli ambienti di sviluppo realizzati tale linguaggio, i problemi di performance e solidità sembravano addirittura elevarsi al quadrato, rendendo lo sviluppo un’esperienza a dir poco frustrante.
Questo costituiva per noi un grave problema: perché si potesse avverare il nostro progetto di sviluppo parallelo sotto più piattaforme era evidente che la possibilità di disporre di un ambiente di lavoro unico avrebbe facilitato enormemente le cose dal punto di vista pratico, permettendoci di concentrarci su di un unico prodotto, imparando a conoscerne al meglio pregi e difetti, ed eventualmente dandoci la possibilità – nelle tanto paventate “situazioni limite” - di sfruttarne il framework proprietario per risolvere i più gravi problemi di performance e di implementazione che prevedevamo si sarebbero presentati.
Tuttavia l’incapacità delle IDE in Java di proporsi come soluzioni efficaci al nostro problema ci spinse, per il momento, ad accantonare l’idea dello sviluppo in parallelo, e ad orientarci verso IDE Pure Java specificamente realizzate in Windows. Le tre IDE che valutammo più approfonditamente furono Visual Age for Java di IBM, Visual Café di Symantec, e JBuilder di Borland/Inprise.
Il primo si dimostrò essere un prodotto solido, e molto adatto allo sviluppo collaborativo: dovemmo però scartarlo non tanto per la sua metafora di programmazione visuale, molto potente ma secondo noi eccessivamente prolissa, quanto per la mancanza di supporto da parte di IBM al JDK 1.2, la piattaforma Java che noi avevamo identificato come strategica. Visual Age era infatti legato al JDK 1.1.8, ed IBM non sembrava intenzionata ad effettuarne un upgrade (per la cronaca, IBM ha sostanzialmente “saltato” il JDK 1.2 passando direttamente dalla versione 1.1.8 a quella 1.3, che – è notizia di pochi giorni fa - ha deciso di implementare in prima persona su diverse piattaforme, tra cui Linux e Windows, oltre a tutti i suoi ambienti “storici” quali AIX, AS/400 ed OS/390).
Per quanto riguarda Visual Café di Symantec, era un prodotto che avevo già avuto modo di utilizzare in prima persona nella realizzazione di un’applicazione AWT ai tempi della prima release del Java Media Framework [10]. Lo trovammo ricco di bug e molto scomodo, in virtù della sua interfaccia basata su un eccessivo numero di finestre indipendenti, che finivano con il sovrapporsi e nascondersi l’un l’altra; inoltre ci sembrava pendere pericolosamente verso il mondo Windows, per via del supporto per la compilazione nativa e per la presenza di alcuni componenti, in un formato tra l’altro alternativo a quello JavaBean, esplicitamente congegnati per funzionare solamente con il sistema operativo di Bill Gates. Aggiungerò infine che la stessa Symantec non era molta chiara nei suoi progetti di sviluppo futuro di Visual Café, e sembrava propendere verso soluzioni proprietarie ai problemi di Java, tanto da includere nel suo prodotto un supporto tardivo ed incompleto per il JDK 1.2 e per le API Swing.
Di JBuilder, prodotto di Borland/Inprise, avevamo avuto un’esperienza della primissima ora, con la versione 1.0 di tale IDE. Essa era di una fragilità e di una lentezza inverosimili – non degne nemmeno di una beta - tanto da convincerci ad abbandonarla completamente, e ad ignorare la versione 2.0. Ragion per cui, quando ci trovammo dinanzi la versione 3.0 di JBuilder, la approcciammo con molto scetticismo.
Dovemmo invece constatare che molte cose erano cambiate:
 

  1. JBuilder aveva acquisito stabilità: era possibile – su macchine con potenza e memoria adeguate - utilizzarlo a lungo e senza riscontrare problemi;
  2. le performance dell’ambiente di lavoro erano visibilmente aumentate, per quanto JBuilder restasse sempre un po’ più lento delle altre IDE Windows, essendo realizzato parte in Java e parte in codice nativo Windows (ed alcune piccole differenze nell’interfaccia grafica, curiosamente, rendevano possibile riconoscere ad occhio le diverse sezioni). D’altronde questo era per noi un aspetto fortemente positivo: Borland/Inprise si trovava infatti ad avere una buona IDE in grado di migrare, senza sforzi sovrumani, su altre piattaforme quando ce ne fosse stata la possibilità tecnica, situazione che si combinava perfettamente con l’idea di un ambiente di sviluppo unico per noi ancora valida in proiezione futura;
  3. più di tutti i suoi concorrenti, JBuilder sembrava essere scritto nel rispetto degli standard Java: non solo esso supportava pienamente il JDK 1.2 e le JFC, al cui sviluppo Borland/Inprise aveva collaborato assieme a Sun, ma la stessa Borland/Inprise aveva apertamente abbandonato il suo precedente framework proprietario in Java (JBCL) – che manteneva unicamente per motivi di compatibilità all’indietro - indirizzando tutti i suoi sforzi nella realizzazione della sola IDE sul mercato il cui supporto alla programmazione visuale supportasse pienamente e nel modo più corretto lo Swing (forse i lettori si ricorderanno come, in quei tempi, il supporto Swing venisse “appiccicato” nelle varie IDE sopra a quello per l’AWT causando tutt’una serie di problemi, ad esempio nella gestione dei Pane);
  4. come già detto, voci di corridoio parlavano di sforzi in atto all’interno di Borland/Inprise per il porting di JBuilder sotto Linux, cosa che lo rendeva ancora più appetibile ai nostri occhi;
  5. la soluzione JBuilder non si limitava allo sviluppo di applicazioni stand-alone, ma comprendeva un supporto completo dei protocolli standard utilizzati nella programmazione multi-tier distribuita ed Internet-based, come CORBA e servlet, vale a dire proprio l’utilizzo che noi avevamo fino a quel momento fatto di Java, e che rimaneva per noi assolutamente strategico;
  6. infine, come d’altronde già nelle precedenti versioni, JBuilder si segnalava per un’interfaccia ben progettata e funzionale, basata su un numero limitato di finestre organizzate in pannelli affiancati, che permetteva di seguire con naturalezza e facilità più progetti contemporaneamente.


Alla luce di queste considerazioni scegliemmo la versione 3.0 di JBuilder come piattaforma di sviluppo per Irmgard, sviluppo che sarebbe stato portato avanti su macchine NT.
Siccome almeno per il momento non potevamo fare a meno di lavorare su macchine Windows, decidemmo di usare anche per questo progetto Visual Source Safe di Microsoft come source code control system, riservandoci di passare a CVS [11], sotto Unix/Linux, in una fase successiva.
A livello di curiosità, dirò come fu per noi una piacevole sorpresa constatare che, al contrario di Delphi, JBuilder era in grado di “sentire” le modifiche apportate ai file sorgenti dall’esterno, e di bloccare le modifiche ad un file attraverso l’editor non appena ne veniva impostata la proprietà read-only, permettendoci così di utilizzare Source Safe – che opera proprio in questo modo - nella maniera più semplice possibile, e senza bisogno di alcun plug-in.
Consci dei requisiti richiesti da JBuilder, per lo sviluppo ci orientammo su delle macchine Pentium a 300-350 MHz, con 256 MB di RAM, dischi EIDE e Windows NT Workstation 4 SP3. Con una tale quantità di RAM JBuilder diventava sufficientemente veloce e molto affidabile: al contrario di quanto accadeva con la versione 1.0, nessuno di noi ha mai perso una sola riga di codice per un suo crash. La scelta di NT poi, per quanto sicuramente penalizzante in termini di prestazioni, ci garantiva una ancora maggiore solidità.
Come repository del programma utilizzammo il nostro server di supporto, una macchina con delle caratteristiche simili a quelle sopra elencate, con architettura SCSI e Windows NT Server 4 SP3 installato.
 
 
 

La gestione dei dati
Assieme alla versione 1.1 delle API JFC/Swing, uno dei punti qualificanti nella nostra scelta del JDK 1.2 era costituito dalla versione 2 del framework JDBC [12], framework di cui possedevamo già una ampia esperienza. Dunque, nella scelta del database da utilizzare con Irmgard il supporto delle API JDBC sarebbe stato un fattore importante, secondo solo a solidità , performance e portabilità.
Era per noi evidente che, come Irmgard avrebbe dovuto essere in grado di operare in reti con architetture diverse, basate sia su Windows che su Unix, così avrebbe dovuto essere il suo database server: un server multipiattaforma in grado di seguire i clienti nei loro percorsi di migrazione senza costringerli a scomodi, e sempre pericolosi, cambi di prodotto.
Come prima cosa, dunque, sondammo il mercato alla ricerca di soluzioni object-oriented: realizzando infatti il programma in Java, sarebbe stato necessario implementare uno strato di conversione tra gli oggetti in archivio e la loro rappresentazione in memoria, e sarebbe stato per noi un risparmio di tempo notevole trovarci con questa conversione già pronta, o perlomeno avviata.
Tuttavia emerse immediatamente un problema, e cioè che, anche se era possibile rintracciare dei database ad oggetti con le caratteristiche da noi richieste, non esistevano implementazioni JDBC in grado di supportare in maniera soddisfacente le metafore ad oggetti, e tanto meno il linguaggio OQL [13]. Difatti, sia nel parco dei database pure-object, sia in quelli ibridi object-relational, la maturazione cui questi prodotti erano arrivati nell'ultimo anno era completamente mascherata proprio dall’indisponibilità di validi driver JDBC, cosa che ci costrinse ad optare per una soluzione SQL.
Prima di optare per una classica soluzione commerciale cogliemmo l’occasione per sperimentare alcuni database SQL open-source, dovendo però constatare la loro incapacità di supportare basi di dati specificatamente gestionali. Laddove essi non mancassero addirittura di alcuni tipi di dati per noi fondamentali - come le colonne DECIMAL di ampie dimensioni richieste per la memorizzazione di valori valutari internazionali ed in Euro ma non presenti in PostgreSQL [14] - erano proprio performance e stabilità a lasciarci perplessi: trovandosi a gestire grandi moli di dati, non basta che un database SQL funzioni; occorre anche che funzioni bene, vale a dire che si basi su uno schema di memorizzazione evoluto, in grado di assicurare affidabilità in caso di crash e velocità nel reperimento e nell’archiviazione delle informazioni, oltre ad un supporto completo del linguaggio SQL, aspetti in cui tutti i database open-source testati mostravano la corda.
Da questo punto di vista una grande delusione fu per noi il database MySQL [15]: esso infatti, oltre a non essere realmente open-source, è completamente privo di qualsiasi forma di supporto transazionale. I suoi autori hanno optato, piuttosto, per un’architettura basata sul concetto di operazioni atomiche [16], scelta che garantisce una semplicità ed una velocità notevoli, ed è senz’altro adatta ad un ampio ventaglio di situazioni – prime tra tutte le basi dati Internet-based in cui, e non è un caso, MySQL si sta rapidamente affermando - ma non offre quei requisiti di solidità ed affidabilità fondamentali nel deployment di sistemi informativi gestionali e finanziari.
Aggiungerò poi come anche nelle implementazioni open-source di miglior livello il collo di bottiglia fosse rappresentato dai driver JDBC, di qualità – senza voler esagerare – poco più che hobbystica ed assolutamente inadatti alla memorizzazione delle informazioni vitali di un’azienda.
Alla luce dell’insufficienza delle proposte open-source la nostra attenzione si rivolse dunque ai database SQL commerciali, in particolare a DB2 di IBM e a Dynamic Workgroup Server di Informix, entrambi disponibili per un vasto parco di piattaforme (al tempo Informix non aveva ancora rilasciato Cloudscape [17], la sua soluzione integralmente basata su Java): la scelta di un database commerciale, inoltre, avrebbe rappresentato un’importante sorta di “compensazione” – se non altro psicologica – al rischio assunto scegliendo Java come linguaggio di sviluppo, e si sarebbe rivelata in seguito, nei momenti più difficili di questo progetto, una certezza molto importante per tutto il team di progettazione.
Sia DB2 che Dynamic Workgroup Server rappresentavano delle scelte valide: il primo era, ed è, molto noto per le sue performance e si segnalava per l’approccio Java-based della sua console di amministrazione. Il secondo al contrario era un prodotto più classico, il cui supporto Java era limitato ai driver JDBC, mentre il resto del database, console di amministrazione inclusa, era realizzato interamente in codice nativo.
Controintuitivamente però i driver JDBC realizzati da Informix si rivelarono nei nostri test superiori a quelli di DB2:
 

  1. I driver Informix supportavano il JDK 1.2 ed il JDBC 2, mentre quelli DB2 erano – come tutta IBM, d’altronde – ancora fossilizzati nel supporto del JDK 1.1.8 e del JDBC 1.1, ed i driver sperimentali per il supporto del JDBC 2 presentavano seri problemi di funzionamento;
  2. il supporto di DB2 all’ormai obsoleto JDBC 1.1 causava una serie di problemi nell’accesso ad alcuni tipi di colonne, ed in particolare a quelle BigDecimal, fondamentali nelle applicazioni gestionali;
  3. i driver Informix erano caratterizzati da un’installazione “leggera”: infatti, per abilitare i client all’accesso al database era sufficiente inserire nel CLASSPATH il solo file .jar del driver - che poteva anche trovarsi in un server di rete - mentre nel caso di DB2 occorreva installare l’intera suite DB2 client in ogni pc destinato a connettersi al database. L’alternativa consistente nel configurare il prodotto di IBM sui client in maniera da utilizzare in modalità proxy i driver installati nel server, ottenendo quindi un’installazione “leggera”, comportava un aumento inaccettabile dei tempi di accesso, i quali arrivavano sino al punto di triplicarsi o quadruplicarsi;
  4. i driver JDBC di DB2 avevano dei problemi di configurazione a livello di JBuilder, cosa che ci obbligava ad utilizzarli in modalità proxy, subendo quindi tutte le inefficienze sopra descritte.


Aggiungendo a tutto questo la mancanza, nell’SQL di DB2, di alcuni comandi di gestione delle tabelle (RENAME TABLE e DROP COLUMN) non facenti parte dello standard ANSI-SQL 92 [18], ma estremamente utili nella fase di design di una base di dati, e la considerazione di come tutto il team di sviluppo già conoscesse ed apprezzasse i prodotti Informix, su cui avevamo basato molti dei nostri progetti precedenti, e a cui tutti riconoscevamo una solidità ed una stabilità eccezionali, la scelta del Dynamic Workgroup Server appariva quasi dovuta. Nei primi mesi di sviluppo la piattaforma usata per il database fu un server NT, da cui si migrò su di una macchina Linux dopo un paio di mesi (tra Novembre e Dicembre) non appena i nostri test interni mostrarono la stabilità della versione del server Informix su tale piattaforma.
La scelta di un database relazionale SQL (per cui esistevano anche delle estensioni ad oggetti, vale a dire i moduli Informix DataBlade [19], tuttavia – ancora una volta - non accessibili tramite JDBC) ci costrinse ad implementare in prima persona lo strato di traduzione object-relational all’interno di Irmgard: si trattò di un lavoro molto impegnativo, sia in fase di design che in fase di codifica, ma che – con il senno di poi – si è rivelato sicuramente proficuo, in quanto è stato proprio a questo livello che si è potuto intervenire con importanti ottimizzazioni del codice.
Ad ogni modo prima di risolverci a realizzare questa parte del framework, sostanzialmente analoga a quanto fatto oggi da Castor [20], valutammo anche altre ricoperture del JDBC che offrivano un accesso ai dati di natura più object-oriented, come Village [21] e Town [22]: tuttavia le API da esse fornite, per quanto eleganti, si rivelarono alla prova dei fatti incomplete e caratterizzate da un’inefficienza per noi non tollerabile.
Come curiosità citerò un problema che si presentò nell’utilizzo dei driver JDBC Informix: essi infatti, per evitare possibili malfunzionamenti, controllavano che la versione del JDK al cui interno venivano eseguiti fosse almeno la 1.2, rifiutandosi di funzionare se così non era.
Purtroppo se al JDK 1.2 veniva aggiunto Hot Spot 1.01, questo riconoscimento di versione falliva, impedendo effettivamente l’avvio del programma. La soluzione, consigliata negli stessi newsgroup Informix, fu quella di forzare il valore dell’impostazione java.vm.version controllata da tali driver aggiungendo l'opzione –Djava.vm.version=1.2 (o –Djava.vm.version=1.2.2 per il JDK 1.2.2) nell’invocazione della JVM di Irmgard. Questa leggera incompatibilità non si manifestava invece eseguendo Irmgard dall’interno di JBuilder 3.0, il quale lavorava senza Hot Spot.
 
 
 

Il punto della situazione
Nella prima parte di questo articolo, appena conclusa, abbiamo esaurito l’argomento delle scelte fondamentali su cui è basato il progetto Irmgard. Nel prossimo mese esamineremo in dettaglio l’architettura della nostra applicazione, con particolare riguardo al suo framework
 
 
 

Bibliografia
[1] – P-code e UCSD p-system: http://www.ics.uci.edu/~archive/documentation/p-system/p-system.html
[2] - Lavinio Cerquetti, “Java Servlet all’opera”, Computer Programming No.77, Febbraio 1999 e MokaByte no.29, Aprile 1999: http://www.mokabyte.it/0499/servlet.htm
[3] - Hot Spot: http://java.sun.com/products/hotspot, http://developer.java.sun.com/developer/technicalArticles/Networking/HotSpot
[4] - La legge di Moore: http://www.webopedia.com/TERM/M/Moores_Law.html
[5] - UML: http://www.rational.com/uml, http://www.uml-zone.com
[6] - Rational Rose: http://www.rational.com/products/rose
[7] - ArgoUML: http://argouml.tigris.org
[8] - Forte For Java, Community Edition: http://www.sun.com/forte/ffj/ce
[9] - NetBeans Open-Source: http://www.netbeans.org 
[10] - Java Media Framework: http://java.sun.com/products/java-media/jmf
[11] - CVS: http://www.cvshome.org
[12] - JDBC: http://java.sun.com/products/jdbc
[13] - OQL: http://www-cse.ucsd.edu/classes/wi00/cse132a/oql.htm
[14] - PostgreSQL: http://www.postgresql.org
[15] - MySQL: http://www.mysql.org
[16] - Le operazioni atomiche in MySQL: http://web.mysql.com/Manual/manual.html#Missing_Transactions
[17] - Informix Cloudscape: http://www.informix.com/cloudscape
[18] - ANSI-SQL 92: http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt
[19] - Informix DataBlade: http://www.informix.com/datablades
[20] - Castor: http://castor.exolab.org
[21] - Village: http://www.working-dogs.com/village
[22] - Town: http://www.working-dogs.com/town
 
 

Lavinio Cerquetti si occupa di modellazione e sviluppo del software (prevalentemente in Java, C/C++ e Delphi) in ambienti Windows e Unix, concentrandosi sulla programmazione distribuita e di rete. Può essere contattato all’indirizzo di e-mail lavinio@poboxes.com

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