CP pensare–progettare–programmare — n.137 — luglio-agosto 2004 Microsoft Business Intelligence Framework: Analysis Services di Lorenzo Braidi La visione della Business Intelligence secondo Microsoft ha come cuore i servizi per l’analisi dei dati di SQL Server, che rappresentano il principale strumento per la gestione di database di grandi dimensioni. Lorenzo Braidi ` E responsabile dell’area Progetti presso la Data Service Technologies di Parma. Si occupa della progettazione e realizzazione di software Data Based. Tiene corsi di formazione professionale sulle problematiche legate ai database ed alla loro gestione. Partecipa ai Beta Test Program delle ` nuove funzionalita di Microsoft SQL Server. pubblicato su WWW.INFOMEDIA.IT stampa digitale da Lulu Enterprises Inc. stores.lulu.com/infomedia Infomedia ` Infomedia e l’impresa editoriale che da quasi venti anni ha raccolto la voce dei programmatori, dei sistemisti, dei professionisti, degli studenti, dei ricercatori e dei professori d’informatica italiani. Sono pi` di 800 gli autori che hanno realizzato per le teu state Computer Programming, Dev, Login, Visual Basic Journal e Java Journal, molte migliaia di articoli tecnici, presentazioni di prodotti, tecnologie, protocolli, strumenti di lavoro, tecniche di sviluppo e semplici trucchi e stratagemmi. Oltre 6 milioni di copie distribuite, trentamila pagine stampate, fanno di questa impresa la pi` grande ed u influente realt` dell’editoria specializzata nel campo della a programmazione e della sistemistica. In tutti questi anni le riviste Infomedia hanno vissuto della passione di quanti vedono nella programmazione non solo la propria professione ma un’attivit` vitale e un vero a divertimento. ` Nel 2009, Infomedia e cambiata radicalmente adottando ` un nuovo modello aziendale ed editoriale e si e organizzata attorno ad una idea di Impresa Sociale di Comunit` , a partecipata da programmatori e sistemisti, separando le attivit` di gestione dell’informazione gestite da un board a comunitario professionale e quelle di produzione gesti` te da una impresa strumentale. Questo assetto e in linea con le migliori esperienze internazionali e rende Infomedia ancora di pi` parte della Comunit` nazionale degli u a sviluppatori di software. ` Infomedia e media-partner di manifestazioni ed eventi in ambito informatico, collabora con molti dei pi` imporu tanti editori informatici italiani come partner editoriale e fornitore di servizi di localizzazione in italiano di testi in lingua inglese. L’impaginazione automatica di questa rivista e realizzata al ` 100% con strumenti Open Source usando OpenOffice, Emacs, BHL, LaTeX, Gimp, Inkscape e i linguaggi Lisp, Python e BASH For copyright information about the contents of Computer Programming, please see the section “Copyright” at the end of each article if exists, otherwise ask authors. Infomedia contents is © 2004 Infomedia and released as Creative Commons 2.5 BY-NC-ND. Turing Club content is © 2004 Turing Club released as Creative Commons 2.5 BY-ND. Le informazioni di copyright sul contenuto di Computer Programming sono riportate nella sezione “Copyright” alla fine di ciascun articolo o vanno richieste direttamente agli autori. Il contenuto Infomedia e © 2004 Infome` dia e rilasciato con Licenza Creative Commons 2.5 BYNC-ND. Il contenuto Turing Club e © 2004 Turing Club ` e rilasciato con Licenza Creative Commons 2.5 BY-ND. Si applicano tutte le norme di tutela dei marchi e dei segni distintivi. ` E in ogni caso ammessa la riproduzione parziale o totale dei testi e delle immagini per scopo didattico purch´ e vengano integralmente citati gli autori e la completa identificazione della testata. Manoscritti e foto originali, anche se non pubblicati, non si restituiscono. Contenuto pubblicitario inferiore al 45%. La biografia dell’autore riportata nell’articolo e sul sito www.infomedia.it e di norma quella disponibi` le nella stampa dell’articolo o aggiornata a cura dell’autore stesso. Per aggiornarla scrivere a
[email protected] o farlo in autonomia all’indirizzo http://mags.programmers.net/moduli/biografia database Microsoft Business Intelligence Framework: Analysis Services La visione della Business Intelligence secondo Microsoft ha come cuore i servizi per l’analisi dei dati di SQL Server, che rappresentano il principale strumento per la gestione di database di grandi dimensioni di Lorenzo Braidi A bbiamo visto nella precedente puntata [3] come far confluire tutte le informazioni aziendali verso un unico punto di aggregazione e come creare una base dati sicura ed integrata; di solito, tuttavia, una base dati contenente tutte le informazioni di cui si necessita è estremamente ricca e complessa e l’approccio tradizionale risulta essere troppo lento rispetto alle esigenze di utilizzo. Se si aggiunge il fatto che un’eventuale applicazione analitica che agisse sulla base dati porterebbe di fatto ad un rallentamento significativo delle altre applicazioni, ci si rende conto che è necessario trovare una strada alternativa. Questa strada è rappresentata dai database multidimensionali. ▼ FIGURA 1 Cube editor Database multidimensionali Il primo scopo dei database multidimensionali è quello di semplificare la struttura dei dati per facilitarne la fruizione da parte degli utenti finali. Possiamo pensare che un ipotetico database relazionale in cui un’azienda tenga traccia delle sue vendite avrà un certo livello di complessità e non sarà di facile comprensione, se non da parte del personale tecnico specializzato. Sappiamo anche, però, che all’ufficio marketing non interessa tanto sapere che il database è così complesso perché è stato studiato per garantire la “non ridondanza” delle informazioni o per ottenere prestazioni di un certo tipo per applicazioni specifiche; a quell’ufficio serve semplicemente sapere cosa si è venduto, quando, e a chi! Lo scopo del nostro database sarà quindi quello di rendere disponibili all’utente le informazioni relative alle vendite aggregate per tre semplici informazioni: • Tempo • Cliente • Prodotto Il secondo scopo di questo tipo di database è quello di garantire prestazioni accettabili su moli significative di dati. Il raggiungimento di questo obiettivo è possibile grazie al fatto che il database multidimensionale provvederà a calcolare in anticipo tutta una serie di informazioni aggregate, che saranno così immediatamente disponibili nel momento in cui verranno richieste. Un database multidimensionale (o OLAP: On Line Analytical Processing) si compone di Cubi. I Cubi rappresentano per i database OLAP quello che le tabelle sono per i database relazionali. Un cubo si compone di tre fondamentali elementi: • Fatti: si tratta delle informazioni che si intende monitorare. I Fatti sono rappresentati da una tabella o da una vista del database relazionale da cui si parte. • Misure: sono i dati che si vogliono analizzare ed aggregare. Esse sono rappresentate da una o più colonne della tabella dei fatti. • Dimensioni: specificano le modalità di aggregazione delle informazioni e determinano i criteri con cui sarà possibile consultare i dati presenti nel database. Le dimensioni sono di differenti tipologie e sono costituite ciascuna da una o più tabelle (o viste) del database relazionale di partenza. Computer Programming • n. 137 - Luglio/Agosto 2004 Lorenzo Braidi
[email protected] È responsabile dell’area Progetti presso la Data Service Technologies di Parma. Si occupa della progettazione e realizzazione di software “Data Based”. Tiene corsi di formazione professionale sulle problematiche legate ai database ed alla loro gestione. Partecipa ai Beta Test Program delle nuove funzionalità di Microsoft SQL Server. 48 PROGRAMMING ▼ FIGURA 2 Wizard per l’ottimizzazione dei cubi conterrà il codice del prodotto venduto che farà riferimento al codice presente sulla tabella “tbAnagProdotti” che rappresenta la dimensione Prodotti. Un caso particolare delle dimensioni a stella è rappresentato dalle dimensioni temporali: queste, infatti, sono rappresentate da una sola colonna di una tabella (che può essere anche quella dei fatti) che deve essere di tipo DATE. In questo modo la dimensione assumerà automaticamente tutti i livelli tipici di una data: • • • • Anno Trimestre Mese Giorno Il database che si andrà a creare sarà, quindi, una copia di quello di partenza con le informazioni distribuite in maniera da garantirne la fruibilità in termini di semplicità e di prestazioni. Utilizzando Analysis Services, un cubo può essere creato utilizzando il Cube Editor (Figura 1) o mediante l’apposito Wizard. In entrambi i casi le informazioni che si devono identificare sono le medesime. • Tabella dei Fatti: Come abbiamo detto, si tratta di una tabella o di una vista del database di partenza ed è quella su cui risiedono le informazioni che si vogliono analizzare ed aggregare per l’analisi che si sta costruendo. Il fatto che si possa indicare anche una vista è molto utile, perché consente di trattare in modo omogeneo informazioni che risiedono su differenti tabelle, rendendo così possibile confronti più complessi. • Misure: Le colonne che possono essere scelte come misure del cubo sono ovviamente solo quelle di tipo numerico. Il cubo che si crea conterrà i valori di tali colonne sia in forma di dettaglio, sia in forma già aggregata rispetto alle dimensioni definite. • Dimensioni: Come detto, le dimensioni rappresentano i “punti di vista” del cubo ed influenzano le logiche di aggregazione dei dati. Se per esempio si è scelta come misura il venduto del giorno e come dimensione il tempo, il cubo risultante conterrà tutti i dati del venduto dei giorni presenti nel database ed i totali per mese, per trimestre e così via. La definizione di una dimensione richiede, oltre all’identificazione della o delle tabelle che la rappresentano, di specificare i livelli di profondità della stessa. Se per esempio stiamo definendo la dimensione “Prodotto”, dovremo stabilire che tale dimensione è rappresentata dalla tabella “tbAnagProdotti” e che i suoi livelli di profondità saranno rappresentati in ordine dalle colonne “MacroCategoriaProdotto”, “SubCategoriaProdotto” e “Nome prodotto”. Questo significa che poi potremo accedere ai dati sia a livello di singolo prodotto, ma anche aggregando per categorie (Sub e Macro). Le dimensioni possono essere di differenti tipologie, ciascuna delle quali ha caratteristiche che derivano dalla sua stessa struttura. Una dimensione a stella è rappresentata da una sola tabella (o vista) che ha un collegamento diretto con la tabella dei fatti. Tornando al nostro esempio, la tabella dei fatti Computer Programming • n. 137 - Luglio/Agosto 2004 Una dimensione a fiocco di neve coinvolge più tabelle legate tra loro. Viene utilizzata quando i dati che identificano i livelli di profondità della dimensione ed i codici che la legano alla tabella dei fatti non risiedono sulla stessa tabella. È possibile, mediante la creazione di apposite viste, ricondurre questo tipo di dimensione alla categoria precedente. Le dimensioni ricorsive, invece, sono rappresentate da una sola tabella che ha un riferimento verso se stessa di tipo ricorsivo. Questo tipo di dimensione è utile per rappresentare strutture gerarchiche tipo “organigramma aziendale” o situazioni analoghe. Le dimensioni sono sì una caratteristica dei cubi, ma mantengono comunque una loro indipendenza: vale a dire che una dimensione può essere associata ad un numero illimitato di cubi differenti senza che le informazioni in essa contenute siano duplicate o che sia necessario ripeterne la definizione. Gestione di un database OLAP Come abbiamo detto, i database multidimensionali rappresentano di fatto una copia delle informazioni contenute in un database OLTP (On Line Transactional Processing). Per questa ragione è necessario che ogni singolo cubo ed ogni singola dimensione sia periodicamente “ricalcolata”, così da acquisire le variazioni che nel frattempo sono state apportate al database di origine. Se nel momento in cui si termina la definizione di un cubo e delle sue dimensioni si tenta di interrogarne il contenuto, si riceverà una segnalazione che riporterà che non è presente alcun dato. Per far sì che il cubo sia effettivamente utilizzabile è necessario elaborarlo. Quando si effettua questa operazione per la prima volta, l’utente è chiamato a definire anche la tipologia di storage che si vuole dare alla struttura appena definita. I cubi possono essere di tre differenti tipologie: ▼ FIGURA 3 DTS: elaborazione dei cubi 49 database ▼ FIGURA 4 Visione tridimensionale dei dati • Agire su query che hanno tempi di esecuzione superiori ad un valore stabilito; • Agire su query che vengono richieste con una frequenza superiore alla soglia indicata. La necessità di ricalcolare periodicamente ed automaticamente i cubi e le dimensioni è risolta dai DTS di SQL Server (Figura 3). In essi, infatti, sono presenti due attività specifiche per l’elaborazione dei database OLAP. È bene specificare che se si procede al ricalcolo di un cubo, questa operazione non necessariamente richiede che siano ricalcolate anche tutte le sue dimensioni. Nel caso, però, che siano intervenute variazioni anche a livello di dimensione, questo sarà necessario. Se per esempio, nel ricalcolo del cubo vengono rilevate informazioni relative ad un cliente che non è presente nella dimensione apposita, questo determinerà un errore e farà fallire il processo. Per questo motivo è consigliabile procedere prima al ricalcolo delle dimensioni e solo successivamente a quello dei cubi. Nei DTS è anche presente un’attività relativa all’elaborazione dei modelli di Data Mining. Descriveremo in seguito il loro utilizzo e significato, per ora basti sapere che essi sono subordinati ai cubi, pertanto devono essere ricalcolati solo dopo aver eseguito l’elaborazione dei cubi stessi. L’ordine da utilizzare per l’elaborazione degli oggetti dei DB OLAP risulta quindi essere: • Dimensioni • Cubi • Modelli di Data Mining • MOLAP: database OLAP Multidimensionale. Ha la caratteristica di duplicare tutte le informazioni presenti nel database relazionale all’interno della propria struttura e di arricchirle con tutte le possibili aggregazioni già precalcolate. Questo tipo di soluzione garantisce le prestazioni ottimali in termini di tempi di risposta a scapito, però, dell’utilizzo di spazio disco. • ROLAP: database OLAP Relazionale. Questo tipo di struttura, non fa altro che definire l’interfaccia di utilizzo per l’utente finale, mentre tutte le informazioni rimangono nel database di origine. È applicabile esclusivamente a piccolissime moli di informazioni, dal momento che tutte le aggregazioni vengono calcolate nell’istante della richiesta da parte dell’utente. • HOLAP: database OLAP Ibrido. È di fatto la sintesi dei primi due: tutte le informazioni di dettaglio risiedono nel database relazione di origine, mentre le aggregazioni sono state precalcolate. Rispetto ai database MOLAP consente un notevole guadagno in termini di utilizzo dello spazio disco, ma porta un deterioramento delle prestazioni. Nelle versioni precedenti a SQL Server 2000, i cubi MOLAP presentavano grossi inconvenienti con l’aumentare delle informazioni immagazzinate. Tali inconvenienti erano dovuti al fatto che si assisteva ad una progressione geometrica del numero di dati presenti, così da determinare il fenomeno noto con il nome di “Data Explosion”. La versione 2000, invece, risolve il problema introducendo la funzionalità di calcolo parziale delle aggregazioni. Questa funzione prevede che non tutte le aggregazioni siano calcolate nel momento dell’elaborazione del cubo, ma solo quelle ritenute di più comune utilizzo, a seconda di alcuni parametri richiesti all’utente. In questo modo, se l’utente finale richiede le aggregazioni che sono presenti nel cubo, queste gli saranno restituite immediatamente; in caso contrario saranno calcolate al momento ed aggiunte a quelle presenti. A parte l’elaborazione iniziale, è anche possibile effettuare una messa a punto delle prestazioni, che consiste nel ricalcolare il cubo inserendovi le aggregazioni a seconda delle statistiche di utilizzo della struttura stessa (Figura 2). La funzione “Ottimizzazione guidata basata sulle statistiche di utilizzo” permette di: • Valutare l’utilizzo di un certo range temporale; • Valutare l’utilizzo di un determinato utente o gruppo di utenti; 50 Il linguaggio MDX Per usare un’espressione matematica, l’MDX sta ai database OLAP come l’SQL sta a quelli relazionali. Il linguaggio MDX (Multi Dimensional extension), infatti, è lo strumento da utilizzare per la consultazione delle strutture di questo tipo di database. Le query MDX hanno una struttura del tutto simile a quelle SQL anche se presentano caratteristiche inesistenti nelle loro “cugine relazionali”. Per prima cosa l’MDX consente di estrarre le informazioni dandone una visione non solo vettoriale o tabellare, ma anche tridimensionale o multidimensionale. ▼ FIGURA 5 Editor per le query MDX Computer Programming • n. 137 - Luglio/Agosto 2004 PROGRAMMING ▼ FIGURA 6 Modelli di Data Mining L’istruzione SELECT Venduto ON AXIS (0), Cliente ON AXIS (1), Prodotto ON AXIS (2) FROM NomeCubo WHERE Anno.2004 estrae una visione tridimensionale (Figura 4) delle informazioni richieste. Le query possono estrarre le informazioni su un numero di assi che può arrivare fino a 256. Al fine di aumentare la leggibilità delle query che andiamo a scrivere, è possibile nominare i primi 5 assi con la codifica che il linguaggio offre: • • • • • Asse 0 = COLUMNS Asse 1 = ROWS Asse 2 = PAGES Asse 3 = SECTIONS Asse 4 = CHAPTER numero di informazioni che si vogliono estrarre, mentre nel linguaggio MDX essa assume un significato per certi aspetti differente. Inserendo una o più restrizioni alla nostra query, infatti, non andremo ad agire sul numero di righe, colonne o pagine da estrarre, ma semplicemente sul numero di aggregazioni che verranno calcolate per la creazione della visione multidimensionale. Se per esempio estraiamo il venduto (ON COLUMNS) ed i prodotti (ON ROWS), anche mettendo come clausola restrittiva il fatto che vogliamo solo il venduto del 2004, otterremo sempre una griglia che riporta come colonna gli importi e come righe tutti i prodotti presenti nella dimensione apposita. Le query MDX possono essere specializzate grazie all’utilizzo delle numerosissime funzioni che il linguaggio offre. Le principali e più utilizzate sono: • Members: estrae tutti i membri di una dimensione; • Children: estrae tutti i membri figli di un membro di partenza; • Crossjoin: estrae tutte le combinazioni tra due dimensioni date; • Union: somma i valori di due dimensioni; • Intersect: estrae solo i valori comuni a due dimensioni date; • Expect: estrae solo i valori che non trovano corrispondenza in due dimensioni (funzione contraria di Intersect). È possibile utilizzare l’MDX editor (Figura 5) per scrivere, validare ed eseguire le query con questo linguaggio. Lo 51 pertanto le query SELECT NomeMembro ON AXIS (0)... e SELECT NomeMembro ON COLUMNS... hanno esattamente lo stesso significato. La clausola WHERE nelle istruzioni SQL ha lo scopo di limitare il Computer Programming • n. 137 - Luglio/Agosto 2004 database strumento mette a disposizione una serie di facilitazioni che guidano nella scrittura delle istruzioni, ma mostra limiti tutt’altro che trascurabili. La rappresentazione grafica di una query con più di 2 dimensioni non è per niente banale, per questo l’MDX editor non esegue questo tipo di interrogazioni. Tutte le istruzioni che generano risultati a 2 assi vengono eseguite e vengono riportati i risultati in forma tabellare, mentre quando si superano le 2 dimensioni, l’editor si limita a validare la correttezza sintattica e formale dell’istruzione, ma non è in grado di eseguirla. Oltre alle interrogazioni, il linguaggio MDX è in grado di gestire anche le operazioni di DDL (operazioni di definizione della struttura del database) quali la creazione, la distruzione o la modifica delle dimensioni, dei cubi e degli altri oggetti del database OLAP. Tenuto conto, però, della complessità del linguaggio e dell’estrema semplicità di utilizzo delle interfacce di Analysis Manager e dei suoi Wizard, questa seconda strada è sicuramente preferibile per la gestione delle strutture OLAP. PROGRAMMING livello di dettaglio che evidenzia due nuove fasce: i clienti sposati e quelli single (Figura 6.C). L’algoritmo di DM si è accorto che la scelta della carta di credito dei clienti di questa fascia è di fatto influenzata dal loro stato civile: i clienti sposati preferiscono la carta Golden, mentre i single quella Silver. Se si esegue la stessa analisi per la fascia di reddito da 10.000 a 30.000 dollari all’anno si nota che questo livello di dettaglio non è presente in quanto non vi sono altre informazioni che influiscono in maniera significativa sulla scelta delle carte. Come si può intuire dall’esempio riportato, i modelli di DM sono uno strumento interessantissimo per l’analisi di grandi moli di dati. Si deve, però, fare particolare attenzione al numero di informazioni su cui essi operano: un modello Decision Tree applicato ad un numero esiguo di dati può determinare tendenze che non hanno riscontro nella realtà, ma che sono il risultato esclusivamente dalla cattiva scelta del campione. È quindi necessario che il numero di informazioni a disposizione sia sufficientemente elevato da garantire un adeguato campione statistico. L’esempio di cui abbiamo parlato vede la fascia di reddito “Oltre 150.000 dollari all’anno” composta da un centinaio di clienti. Questo significa che ogni singolo cliente influisce per l’1% sul risultato. Tale percentuale è troppo elevata perché si possa essere certi dell’analisi effettuata e possiamo dire che se il campione fosse stato composto da 1000 clienti, probabilmente il modello avrebbe dato risultati diversi e – siamo sul piano delle ipotesi – non avrebbe evidenziato l’ulteriore suddivisione per “stato civile”. Data Mining Quando la mole di informazioni diventa estremamente elevata, anche le strutture di tipo OLAP possono risultare insufficienti per l’individuazione di determinate informazioni. A questo scopo nascono i modelli di Data Mining (scavare/scovare i dati) che hanno l’obiettivo di analizzare in maniera sistematica le informazioni per determinarne le tendenze intriseche. Analysis Services mette a disposizione dell’utente due diversi modelli di Data Mining: • Decision tree: che costruisce un albero su cui suddivide le informazioni presenti nel cubo di partenza; • Cluster: che suddivide le informazioni in fasce. La definizione di un modello di DM (anche questa mediante un semplicissimo Wizard da Analysis Manager) richiede di selezionare il cubo su cui applicare il modello stesso e di identificare il dato che si vuole monitorare. Una volta fatto ciò, sarà il motore analitico dello strumento ad individuare quali siano le informazioni che influenzano i diversi valori di tale dato ed a costruire conseguentemente una struttura ad albero in cui suddividere tutte le informazioni presenti. L’esempio di Figura 6 riporta un modello Decision Tree applicato al cubo Sales del database FoodMart2000 (il “Northwind” di Analysis Services). Tale modello è stato definito sul dato che identifica la tipologia di carta di credito utilizzata dal cliente per il pagamento. In prima battuta il motore ha stabilito che il dato che più di ogni altro ha influenza sulla scelta della carta di credito è il reddito annuo del cliente (Figura 6.A), ed ha quindi proceduto a suddividere la totalità dei clienti in fasce. Il colore dei rettangoli che rappresentano le fasce di reddito è indicativo della densità della fascia stessa: più il rettangolo è scuro, più la percentuale che vi appartiene è alta. Se si seleziona una fascia di reddito vengono visualizzate le percentuali relative alle diverse tipologie di carte utilizzate dal sottoinsieme di clienti rappresentati, così come, se si seleziona una determinata tipologia di carta, vengono rielaborate le fasce di reddito a seconda della densità che hanno in merito a quella singola carta (Figura 6.B). L’esempio di cui parliamo evidenzia il fatto che i clienti che appartengono alla fascia di reddito massimo (oltre i 150.000 dollari all’anno) preferiscono la carta Golden. La cosa interessante è che se si analizza questa fascia reddituale, si nota che essa può essere “esplosa” ad un ulteriore 52 Conclusioni Analysis Services di Microsoft SQL Server 2000 rappresenta senza dubbio un buon punto di riferimento per la costruzione di applicazioni per la Business Intelligence: è al tempo stesso efficace e facile da utilizzare e garantisce sempre solidità e prestazioni soddisfacenti. Nel corso degli anni questo strumento è maturato notevolmente (abbiamo parlato del performance tuning dei cubi) ed è arrivato ad un livello di maturità tale da collocarlo come punto di riferimento per le applicazioni del settore. Microsoft annuncia grosse novità su questo fronte a partire dalla prossima versione di SQL Server (Yukon) che verrà rilasciata probabilmente a fine 2004 e che porterà un ulteriore potenziamento delle funzionalità di Business Intelligence ([4]). Già dalla versione attuale di SQL Server, però, Microsoft affianca alla potenza di back-end di Analysis Services la versatilità di Reporting Services che analizzeremo nella prossima puntata. BIBLIOGRAFIA & RIFERIMENTI [1] Robert Vieira, “Professional SQL Server 2000 Programming”, Wrox Press [2] “Microsoft SQL Server Books on line”, Microsoft Corporate [3] Lorenzo Braidi, “Microsoft Business Intelligence Framework: Data Transformation Services”, Computer Programming n. 136 [4] Lorenzo Braidi, “Aspettando Yukon…”, Computer Programming n. 129 CODICE ALLEGATO ftp.infomedia.it Analysis Computer Programming • n. 137 - Luglio/Agosto 2004