Sistema self service di business Intelligence in ambito mobile

27
1 Università degli Studi di Genova Scuola di Scienze Matematiche Fisiche e Naturali Corso di Laurea in Informatica Anno Accademico 2012/2013 Prova Finale Business Intelligence in ambito mobile Candidato Matteo Fabbri Relatori Giovanna Guerrini, Giuliano Trifoglio

Transcript of Sistema self service di business Intelligence in ambito mobile

Page 1: Sistema self service di business Intelligence in ambito mobile

1

Università degli Studi di Genova Scuola di Scienze Matematiche Fisiche e Naturali

Corso di Laurea in Informatica

Anno Accademico 2012/2013

Prova Finale

Business Intelligence in

ambito mobile

Candidato Matteo Fabbri

Relatori Giovanna Guerrini, Giuliano Trifoglio

Page 2: Sistema self service di business Intelligence in ambito mobile

2

Sommario Business Intelligence in ambito mobile ............................................................................................................. 1

Introduzione ...................................................................................................................................................... 3

1 OLAP .......................................................................................................................................................... 4

Analisi dei dati ................................................................................................................................... 4

L’ipercubo OLAP ................................................................................................................................ 5

Materializzazione completa degli aggregati parziali: complessità .................................................... 5

Implementazioni di mercato ............................................................................................................. 9

Interrogazione di cubi reali .............................................................................................................. 10

1.5.1 MDX ......................................................................................................................................... 10

1.5.2 DAX .......................................................................................................................................... 11

1.5.3 Scelta del linguaggio di interrogazione .................................................................................... 11

2 Il progetto ................................................................................................................................................ 12

Scopi ed obbiettivi ........................................................................................................................... 12

Architettura del sistema .................................................................................................................. 12

Interfaccia HTML.............................................................................................................................. 13

2.3.1 User experience ....................................................................................................................... 14

2.3.2 Portabilità ................................................................................................................................ 15

2.3.3 Uso di HTML 5 .......................................................................................................................... 17

Servizio WCF .................................................................................................................................... 21

Il Gestore di Cubi ............................................................................................................................. 23

2.5.1 Estrazione dei metadati ........................................................................................................... 23

2.5.2 Caching dei metadati ............................................................................................................... 25

3 Conclusioni .............................................................................................................................................. 26

4 Bibliografia ............................................................................................................................................... 27

Page 3: Sistema self service di business Intelligence in ambito mobile

3

Introduzione

Si parla per la prima volta di Business Intelligence nel diciannovesimo secolo come: “la capacità di agire per

trarre profitto in base ad informazioni ottenute prima dei propri concorrenti” (Devens, 1865)

Nell’era dell’informazione questa definizione ha via via perso senso, subito diversi mutamenti e ad oggi

quando si parla di business intelligence si definisce un generico insieme di “concetti e metodi per migliorare

le decisioni di business usando sistemi di supporto basati su fatti” (Power, 2007)

Questo perché con 2,6 zettabyte di dati prodotti ogni anno nel mondo (IDC, 2012) il problema non è più

avere l’informazione ma estrarre le informazioni sensibili dall’enorme mole di dati a disposizione.

Si tratta quindi di implementare un ulteriore processo informativo aziendale che raccolga i dati dei sistemi

informativi pre-esistenti e ne estragga dati utili per un miglior controllo di gestione e quindi un maggiore

vantaggio competitivo.

Questo processo di analisi è molto influenzato dalla specificità del business che si va ad analizzare e

dall’organizzazione interna ed esterna dell’azienda che lo implementa per cui non esiste un modello

univoco di business intelligence ma possiamo comunque definire tre principali aree di azione che coprono

questo processo:

Reporting: capire che cosa è successo

Data mining: capire perché è successo

Previsioning: stabilire che cosa ci si aspetta che succederà

In questo lavoro andremo nello specifico ad analizzare la funzione di reporting attraverso la sua

implementazione più diffusa: l’analisi attraverso un ipercubo OLAP, ovvero l’interrogazione

multidimensionale delle performance aziendali per fornire al management un indicazione in tempo reale di

quali siano i punti di forza e di debolezza dei processi di business che compongono l’impresa.

Nello specifico analizzeremo il progetto di studio di un sistema di interrogazione di ipercubi OLAP in ambito

mobile, ovvero consultabile da tablet e smartphone, da me realizzato durante un tirocinio formativo presso

Infinity Tech Solution srl, che ha messo a nostra disposizione mezzi e risorse per valutare la fattibilità di

questo progetto come integrazione dei propri prodotti per la business intelligence rispetto a quella che è la

frontiera dei dispositivi mobile e del HTML5, attraverso lunghe e proficue interazioni e confronti sulle

tematiche di usabilità, fattibilità, implementazione, casi d’uso, necessità e politiche aziendali.

Page 4: Sistema self service di business Intelligence in ambito mobile

4

1 OLAP In questo capitolo andremo ad analizzare il mondo dei sistemi OLAP per comprendere quali sono le

tematiche e le problematiche affrontate durante questo progetto e per valutare le scelte di design che sono

effettuate e le loro motivazioni.

Inizieremo con lo specificare cosa si intende per OLAP (sezione 1.1) per poi chiarire in cosa consiste un

ipercubo OLAP (sezione 1.2), le problematiche di complessità inerenti l'interrogazione di grandi quantità di

dati multidimensionali (sezione 1.3), il come queste problematiche vengano risolte nelle implementazioni

ad oggi disponibili (1.4) ed in fine in che modo è effettivamente possibile interrogare questo tipo di sistemi.

Analisi dei dati OLAP è l’acronimo di On Line Analitical Process ovvero la capacità di effettuare analisi statistiche descrittive

su grandi moli di dati prodotti in tempo reale dalle linee aziendali.

Nato come evoluzione di OLTP (On Line Transaction Processing) risolve il problema di poter ottenere una

statistica descrittiva dei processi aziendali i cui dati sono conservati in grandi database relazionali, non

ottimizzati per questo genere di operazioni e che quindi richiederebbero uno sforzo in termini di tempo e di

accessi al disco tale da poter facilmente diventare insostenibile, mettendo così, nel peggiore dei casi, a

repentaglio l’operatività stessa dei database operativi e la funzionalità stessa dei processi aziendali che si

vogliono analizzare.

Separando la conservazione dei dati dalla loro analisi, OLAP permettere di avere una copia concentrata,

non mission-critical e facilmente consultabile di quelle che sono le metriche operative dei processi

aziendali, che vengono processati ed immagazzinati su macchine diverse rispetto ai database operativi in

modo garantire atomicità ed indipendenza dei dati.

Si tratta quindi di creare un datawarehouse separato da quelli che sono i database di produzione

dell’azienda dove immagazzinare uno o più datamart specifici per i management destinatari.

Figura 1 - Schema di architettura OLAP

Inizialmente la macro categoria dei prodotti OLAP era suddivisa in MOLAP (multidimensionale), ROLAP

(relazionale) e RTOLAP (in tempo reale) ma negli ultimi dieci anni, l’esplosione del mercato (Gartner, 2013)

Page 5: Sistema self service di business Intelligence in ambito mobile

5

e la necessità di prodotti sempre più efficienti e performanti ha portato ad una fusione di queste tre

categorie e quando si parla di OLAP correntemente si definisce un sistema ibrido che implementa la

multidimensionalità attraverso un sistema relazionale che a seconda dell’implementazione può essere

configurato per essere aggiornato in tempo reale.

L’ipercubo OLAP L’implementazione più comune di queste funzionalità ed anche quella oggetto del nostro lavoro, di un

sistema OLAP moderno è quella dell’ipercubo N-dimensionale.

Interrogando il management su quali elementi, anche complessi, dei nostri sistemi informativi vogliamo

andare ad analizzare definiremo le N dimensioni del nostro cubo e i valori che saranno posti al suo interno

detti KPI, ovvero gli indicatori chiave di prestazione che il management ha stabilito per i processi aziendali,

in modo da poter valutare, tramite l’incrocio delle dimensioni, risultati attesi, inaspettati, punti di forza e di

debolezza dei processi sotto osservazione.

Ad ogni singolo evento del processo di business analizzato il sistema andrà a creare o ad aggiornare il KPI

corrispondente a tutti i valori di quell’evento creando così un’immagine multidimensionale di quelle che

sono le prestazioni aziendali per i valori analizzati, che verranno a loro volta interrogati attraverso quelle

che sono le cinque operazione base che definiscono l’analisi multidimensionale tramite ipercubi (Council,

1995):

Dicing: ottenere un subset del cubo specificando una o più dimensioni.

Slicing: caso particolare di Dicing, specificando N-2 dimensioni si ottiene una tabella bidimensionale

Drill Down/Up: interrogare il cubo in base agli attributi di una o più dimensioni

Roll-up: ottenere un numero scalare da una funzione applicata sui valori specificati da una o più

dimensioni

Pivoting: Ruotare il cubo sull’asse di una dimensione

In questo cubo potremo così pre calcolare e memorizzare quelle che sono le statistiche parziali del processo

che vogliamo analizzare, che saranno così immediatamente disponibili, semplicemente incrociando i

termini secondo cui si vuol effettuare l’analisi.

Non sarà quindi, come viene spesso descritto, un array multidimensionale ad N dimensioni, ma un

dizionario di oggetti da una ad N chiavi, in quanto ogni valore inserito sarà indicizzato, non solo sotto le N

coordinate di inserimento, ma sotto tutte le 2^N combinazioni di queste.

Materializzazione completa degli aggregati parziali: complessità Si tratta quindi di una struttura dati particolarmente complessa, dove verranno immagazzinate grandi

quantità di valori che, data la natura del cubo, cresceranno in maniera esponenziale.

A questo punto, per chiunque abbia un minimo di affinità con la complessità spaziale, verrebbe da chiedersi

perché immagazzinare una simile quantità di dati, visto che lo scopo di un simile sistema è quella di

produrre un sunto delle transazioni effettuate.

Vediamo dunque un ipotetico caso d’uso del nostro sistema:

Il 4 Marzo del 2014 il commerciale Guido Rossi della nostra azienda effettua una vendita a Genova di

cinquecento parti meccaniche per un valore di un settemila di euro

Page 6: Sistema self service di business Intelligence in ambito mobile

6

Nei database operativi della nostra azienda questo fatto potrebbe apparire così

Tabella agenti commerciali

ID Nome Cognome Zona

GROSSI Guido Rossi Genova

Tabella delle vendite

ID Agente Data Pezzi Importo

0000000001 GROSSI 04/13/2014 500 7.000

In questo esempio la tabella degli agenti commerciali e relative zone crescerà relativamente poco, fino a

qualche migliaio di unità mentre quella delle transazioni potrebbe crescere per milioni di righe specie nel

caso di micro transazioni o di volumi particolarmente elevati quali quelli di una multinazionale.

Volendo avere un reporting preciso ed esplicativo delle vendite ci troveremo di fronte alla necessità di

dover fare diversi JOIN, SUM e GROUPBY sulle colonne del nostro database operativo.

Nel caso di milioni di transazioni, cifra che non deve sorprendere se si pensa che compagnie come

MasterCard processano e registrano trentadue milioni di transazioni al giorno (MasterCard, 2013) ci si

troverebbe di fronte all’intrinseca complessità di queste operazioni, generalmente O(N) dove N è il numero

di transazioni registrate nel nostro database.

Operativamente parlando su un database di grandi dimensioni questo si tradurrebbe in un elaborazione

particolarmente lunga, che potrebbe durare diverse ore ed essere d’ostacolo alla funzionalità stessa del

database, mettendo a repentaglio l’operatività del sistema aziendale e fornendo al management dati che

sarebbero vecchi già al momento della loro pubblicazione.

Vediamo dunque come si presenterebbe il nostro esempio applicando un teorico ipercubo OLAP

completamente materializzato al nostro database definendo come KPI fatturato e numero di pezzi venduti

e come dimensioni gli altri parametri quali zona, agente commerciale, mese, anno.

Non potendo rappresentare graficamente un ipercubo quadri dimensionale mostreremo una piccola

frazione di questo esplosa e disposta tabularmente dove il valore * è inteso come dato mancante

all’interno della tupla ed indifferente per l’eventuale query.

Agente Mese Anno Zona Pezzi Importo

* * * * 500 7000

* * 2014 * 500 7000

* * 2014 * * 7000

* * 2014 Genova 500 7000

* * 2014 Genova * 7000

* * * * 500 7000

* * * * * 7000

GROSSI Marzo * Genova * 7000

GROSSI Marzo * Genova * 7000

GROSSI * 2014 * * 7000

GROSSI * 2014 * * 7000

Page 7: Sistema self service di business Intelligence in ambito mobile

7

In questo ipotetico cubo abbiamo preallocato sedici righe al posto di una, per una singola transazione,

ottenendo però un primo importante vantaggio: nuove transazioni con le stesse dimensioni non

comporteranno l’inserimento di nuove tuple ma solo l’aggiornamento di quelle esistenti.

Se il nostro agente commerciale dell’esempio vendesse altri mille pezzi per altri quattordici mila euro nello

stesso mese le ultime due tuple del nostro cubo apparirebbero così

GROSSI * 2014 * * 21000

GROSSI * 2014 * * 21000

Il vantaggio principale però risiede nella complessità computazionale del recuperare questi dati:

Per interrogare il datamart riguardo ad una o più dimensioni non dovremo fare altro che accedere alla cella

corrispondente all’incrocio delle dimensioni che ci interessa interrogare.

Stiamo però parlando di un cubo materializzato, in cui avremo preallocato tutti i possibili parziali delle

nostre interrogazioni, andiamo a vedere quindi come funzionerebbe in pratica questa nostra struttura dati,

analizzando una semplice implementazione in-memory del nostro cubo per definire quelle che saranno

problematiche importanti al fine delle valutazioni finali del nostro progetto dei tools utilizzati.

Per semplicità di codice, omettiamo le operazioni complesse definite nella prima sezione e definiamo il

nostro cubo come un semplice dizionario con un numero illimitato di chiavi che agirà similmente a quanto

visto nell’esploso sopra.

Sarà cioè organizzato per colonne attraverso un albero di dizionari, in cui ogni livello definirà una delle

dimensioni del cubo.

Ogni nodo conterrà i KPI relativi alla propria dimensione ed il puntatore ai valori prossima dimensione

indicizzati sotto di esso.

Figura 2 – Rappresentazione parziale dell’ordinamento dei nodi

Rossi

2013

2014

Gennaio

Febbraio

Marzo

Gennaio

Febbraio

Marzo

Page 8: Sistema self service di business Intelligence in ambito mobile

8

class SimpleOlap { private Dictionary<object, SimpleOlap> Childs; private Dictionary<object, object> Values; public static readonly object Jolly; public void SetValue(object value, object[] coords, int index=0) { //Memorizza o aggiorna il valore per la coordinata corrente Values[coords[index]] = value; //Se non sono finite le coordinate passa il lavoro alla dimensione //successiva if (index < coords.Length) { OlapNode child; if (!Childs.TryGetValue(coords[index], out child)) { child = new OlapNode(); Childs.Add(coords[index], child); } index++; if (index < coords.Length) child.SetValue(value, coords,index); } } public object GetValue(object[] coords, int index = 0) { //Se la coordinata attuale è l'ultima delle richieste //ritorna il relativo valore if (index != coords.Length - 1) { OlapNode child; if (childs.TryGetValue(coords[index], out child)) return child.GetValue(coords, ++index); throw new IndexOutOfRangeException("Wrong number of coordinates " + coords); } //Altrimenti passa il compito alla coordinata successiva object value; if (values != null && values.TryGetValue(coords[coords.Length - 1], out value)) return value; throw new IndexOutOfRangeException("Missing value on coordinates "+coords); }

Assumendo O(1) come valore teorico della singola ricerca all’interno del dizionario della chiave (Cormen,

2009), l’intero cammino verso il valore del KPI sarà dato da D*O(1) = O(D) dove D differentemente da prima

non sarà più il numero enorme di righe presente nel nostro database relazionale ma il numero costante

delle dimensioni del nostro cubo.

Avremo quindi con una complessità teorica di O(1) di magnitudine quattro volte inferiore a quella del

database operativo che ci permetterà finalmente di avere i risultati richiesti in tempo reale e senza andare

ad intaccare l’operatività dei sistemi aziendali.

Page 9: Sistema self service di business Intelligence in ambito mobile

9

E’ facilmente sperimentabile vedere come anche questa semplice implementazione non riesca a sopportare

un numero congruo di dimensioni prima di esaurire la memoria disponibile, nel caso specifico il limite è

indotto dall’ambiente di sviluppo scelto, Microsoft .net framework che limita le dimensioni di ogni oggetto

ad un massimo di 2GB, indipendentemente dalla piattaforma ma anche in un ambiente di sviluppo più

libero da questo punto di vista, il margine si sposterebbe di poco a causa della crescita esponenziale del

volume del cubo.

Proviamo quindi a calcolare la complessità spaziale del nostro cubo:

Definendo come N il numero di dimensioni del nostro cubo avremo che ogni KPI sarà indicizzato da delle

tuple ordinate di N chiavi in cui ogni valore potrà essere presente oppure essere sostituito dal puntatore

Jolly (rappresentato da * nel caso d’uso)

Il numero di tuple t sotto cui verrà indicizzato il nostro KPI sarà quindi dato da:

𝑡 = 2𝑁

Definendo come K la quantità di valori che ogni dimensione può assumere possiamo calcolare il numero c

di coordinate disponibili all’interno del nostro cubo, dato dalla quantità di possibili sequenze di N valori da

zero a K:

𝑐 = 𝑁𝑘

Possiamo quindi calcolare il numero totale di tuple d’indicizzazione di un cubo ad N dimensioni ciascheduna

di K valori, semplicemente moltiplicando i due dati:

𝑞 = 𝑐 ∗ 𝑡 = 2𝑁𝑁𝐾

Applicando questa formula al nostro caso d’uso, ovvero ad un cubo quadri dimensionale possiamo

facilmente vedere come basterebbero quindici valori per ogni chiave per arrivare ad occupare più di un

terabyte.

Ci troviamo quindi davanti alla principale problematica di OLAP: facilmente il cubo diventa molto più

grande della memoria della macchina su cui è eseguito.

Implementazioni di mercato Determinata l’impossibilità di mantenere i dati in memoria vediamo quindi come è realizzato nella pratica

un sistema OLAP, per quanto non sia possibile discutere i dettagli implementativi dei sistemi maggiormente

utilizzati (Gartner, 2013) a causa dell’utilizzo di soluzioni proprietarie, possiamo comunque trarre alcune

importanti considerazioni basandoci sulla letteratura in merito e sulle specifiche pubbliche di questi

prodotti.

Per prima cosa notiamo come tutte le soluzioni più comunemente utilizzate (IBM, SAP, Oracle, Microsoft e

Mondrian) immagazzinino i dati del cubo in quello che è a tutti gli effetti un classico database relazionale.

In primis, contrariamente alla teoria, non vengono memorizzati tutti i parziali ma solo parti di essi che

vengono determinati dalle policy interne delle singole implementazioni, mentre i restanti verranno calcolati

solo se richiesta ed eventualmente salvati in cache.

All’interno del database il cubo viene diviso in N cubi quanti sono i KPI del nostro cubo originario e a loro

volta in sotto cubi di minori dimensioni per permetterne il più veloce caricamento e interrogazione.

Questi cubi, molto più piccoli di quello originario, sono infine implementati come normali database

relazionali secondo schemi a stella, a fiocco di neve o più recentemente seguendo immagazzinamenti basati

su colonne che permettono minori accesso al disco.

Page 10: Sistema self service di business Intelligence in ambito mobile

10

Questo tipo di immagazzinamento riduce in maniera sostanziale la facilità di accesso ai dati che ci

interessano ma dimezza anche la necessità di spazio rimuovendo tutti i valori assenti dalle nostre tuple

dimensionali.

Nello specifico, il motore OLAP utilizzato per il nostro progetto, Microsoft SQL Server 2008 Analysis Services

presenta alcune caratteristiche peculiari (Gorbach Irina, 2008):

Nonostante l’esposta multidimensionalità, le tabelle relative a dimensioni e KPI sono in prima

approssimazione immagazzinate una riga per volta in tabelle bidimensionali che vengono di volta in volta

iterate.

Stringhe ed altri valori complessi, vengono compressi e sostituiti con puntatori ad essi per forzare la

dimensione della singola riga ad un valore fissato.

Vengono creati una serie di indici per le diverse coppie dimensione - KPI e sottocubi relativi ai singoli valori

di dimensione più richiesti.

Interrogazione di cubi reali Non avendo quindi modo di interrogare direttamente il nostro cubo OLAP attraverso codice eseguito su di

una struttura dati in memoria e dovendoci collegare ad un motore esterno che implementi quanto visto

sopra, avremo bisogno di un linguaggio di comunicazione per poter interrogare il nostro cubo.

Vediamo quindi i linguaggi di interrogazione che abbiamo valutato per il nostro progetto comparandoli per

valutarne prestazioni ed opportunità di utilizzazione.

1.5.1 MDX Ad oggi è il linguaggio più comunemente usato per le query su queso tipo di sistemi è MDX, abbreviazione

di Multi Dimensional eXpressions.

Nato nel 1997 come linguaggio d’interrogazione dei cubi OLAP Microsoft, pur non essendo un vero e

proprio standard è stato rapidamente adottato dal ristretto gruppo dei concorrenti diventando standard de

facto.

Si tratta fondamentalmente di una versione di SQL ottimizzata per l’analisi multidimensionale, dove sono

stati aggiunti oggetti complessi, tuple ed array.

Implementa tutte le funzioni base del cubo OLAP viste nel primo capitolo ad esclusione di Dicing e Pivoting,

in quanto i risultati saranno sempre in formato tabulare a due dimensioni, che dovranno essere specificate

all’interno della query stessa.

Volendo applicare MDX al nostro caso d’uso, per conoscere il valore del nostro KPI “Vendite” (in questo

ambiente di sviluppo Misura è il termine corrente per KPI) nei vari anni sulla zona di Genova, servirà

effettuare la query:

SELECT

{[Measures].[Importo]} ON COLUMNS,

{[Date].[2002], [Date].[2014]} ON ROWS

FROM Vendite

WHERE ([Agente].[Zona].[Genova])

Specialmente in una query così semplice è facile notare l’overhead di lavoro introdotto dalla notazione

MDX rispetto a quella che in SQL sarebbe stato una query del tutto similare.

Page 11: Sistema self service di business Intelligence in ambito mobile

11

Si tratta infatti di un linguaggio di interrogazione molto potente ma anche particolarmente complesso sia

da imparare che da implementare a causa del grande numero di possibilità offerte.

1.5.2 DAX Acronimo di Data Analysis Expressions, è l’evoluzione di MDX oltre ad essere il linguaggio nativo per

formule ed interrogazioni delle motore xVertipad che sta alla base delle piattaforme Microsoft PowerPivot

e SQL Server Analysis Services Tabular.

Come MDX mantiene la restrizione dei risultati allo slicing del cubo ma semplifica il linguaggio di

interrogazione, implementando la struttura di formule dei fogli di calcolo Excel unita all’interfacciamento

con i cubi OLAP, non si tratta quindi di un vero e proprio linguaggio di query ma di un linguaggio

d’espressione.

Vengono quindi eliminate possibilità complesse quali oggetti, tuple e classi e rese implicite le operazioni di

join tra le diverse dimensioni, in questo modo viene realizzata un alta intercompatibilità tra le soluzioni

server side per il calcolo dei cubi e gli strumenti office per la loro interrogazione, oltre a fornire un

linguaggio di interrogazione più semplice ed alla portata di più persone all’interno dell’azienda estendo così

la possibilità di interrogazione al di fuori del reparto IT.

Nonostante la sua relativa semplicità è a tutti gli effetti meno conosciuto e supportato di MDX.

1.5.3 Scelta del linguaggio di interrogazione Viste le possibilità offerte dai possibili linguaggi, vediamo come è perché è stato infine scelto di

implementare le query in DAX.

Si tratta di query totalmente trasparenti all’utente, quindi non ce sono necessità di fornire all’utente un

ambiente a lui familiare ma solo di cogliere quello che riterremo più comodo per la nostra

implementazione.

Come abbiamo visto sopra, DAX non fornisce interfacce per effettuare query complesse ma non è il nostro

caso, facendo selezionare dalla GUI dimensioni e KPI, le possibili query che andremo a comporre saranno

sempre nella forma “SELECT WHERE”.

Facciamo quindi un piccolo confronto su questo tipo di query, dove si intende solamente selezionare un

valore date determinate dimensioni, nei due possibili linguaggi, sul datamart d’esempio fornito con Analysis

Service:

MDX

SELECT NON EMPTY [Currency].[CurrencyName].[CurrencyName].MEMBERS* [Customer].[Customer Id].[Customer Id].MEMBERS ON 1 ,[Measures].[Internet Total Sales] ON 0 FROM [AdventureWorks_Test]

DAX

EVALUATE SUMMARIZE('Internet Sales','Currency','Customer',Internet Total Sales’) ORDER BY 'Currency', 'Customer'

La facilità di composizione della query rende evidente il motivo della scelta di DAX per la generazione

automatica delle query.

Page 12: Sistema self service di business Intelligence in ambito mobile

12

2 Il progetto In questo capitolo andremo ad analizzare scopi, obbiettivi, tecniche e risultati del progetto di studio svolto.

Inizieremo col definire quali siano gli obbiettivi che si sono volevano raggiungere (sezione 2.1) per poi

proseguire con descrizione dell’architettura che si è andati ad implementare (sezione 2.2) che verrà poi

analizzata nel dettaglio delle sue componenti: interfaccia web HTML (sezione 2.3), servizio dati (sezione 2.4)

ed interfacciamento al sistema OLAP (sezione 2.4)

Scopi ed obbiettivi Scopo del nostro progetto è stato quello di studiare la possibilità di fornire un sistema permettere al

management destinatario della nostra analisi di consultare i dati di un generico ipercubo olap, presso

qualunque dispositivo connesso ad internet, attraverso un interfaccia semplice ed efficiente che non

richieda la conoscenza di linguaggi di interrogazione.

Per realizzare questo scopo si scelto di realizzare una web application accessibile da qualunque web

browser e di effettuare le interrogazioni attraverso il semplice drag and drop degli elementi che si desidera

visualizzare.

Per semplificare al massimo l’interazione con il sistema, è stato deciso di realizzare la nostra web

application come quella che viene detta una single-page application (SPA) ovvero un applicazione web

composta da una singola pagina HTML che implementi al suo interno tutte le funzionalità richieste

dall’applicazione, caricando attraverso script i risultati forniti dal server e fornendo le interfacce richeiste

attraverso una programmazione esclusivamente lato client.

Architettura del sistema Dovendosi interfacciare a sistemi aziendali pre esistenti basati su Microsoft Analysis Service e Microsoft SQL

Server il sistema è stato costruito sul framework Microsoft .Net utilizzando Windows Comunication

Foundation (WCF) come back end e Microsoft ActiveX Data Objects (ADO) per le interrogazioni al cubo

OLAP.

Questi sistemi supportano correntemente sia MDX che DAX, ma per semplicità di implementazione e per

compatibilità con i sistemi futuri è stato scelto DAX come linguaggio di interrogazione.

Per la nostra web application abbiamo quindi scelto la classica architettura three-tier composta da

rispettivamente da:

Un’interfaccia HTML e Javascript: per la gestione degli eventi generata dagli utenti

Un servizio WCF: per la business logic relativa a metadati e query

Analysis Service con un gestore di cubi: per la memorizzazione dei meta dati necessari e le

interrogazioni

Page 13: Sistema self service di business Intelligence in ambito mobile

13

Figura 3 – Rappresentazione della nostra architettura di sistema e relativi messaggi

Legenda:

Dimensioni e KPI

Query

Risultati

Sul server il gestore dei cubi andrà a creare una cache con i metadati relativi ai diversi cubi gestititi, quali

dimensioni, KPI e stringhe di connessione mentre il servizio WCF li renderà disponibili su chiamata del client

incapsulandoli all’interno di oggetti in formato JSON facilmente interpretabili dal client.

Sul client una semplice interfaccia HTML verrà riempita dinamicamente da degli script Javascript che

andranno ad interrogare il servizio WCF ed in base alle interazioni di mouse e touch-screen andranno a

generare automaticamente le rispettive query DAX con cui interrogare il servizio.

Interfaccia HTML Front end della nostra applicazione è l’interfaccia HTML, la quale si occuperà di mostrare all’utente

dimensioni e KPI del cubo corrente perché possano essere selezionate dando origine ad una nuova

interrogazione.

Vediamo quindi la struttura della nostra unica pagina, composta di quattro zone principali:

Tools

Risultati

Dimensioni KPI

Ai bordi della pagina vengono generati due menù a scomparsa per mostrare dimensioni e KPI del cubo

corrente, l’utente cliccando sulle rispettive voci potrà espandere i valori che gli interessano (Drill-down) ed

eventualmente trascinarli nell’area “Risultati” per aggiungerli alla query d’interesse.

L’area centrale, volutamente molto più grande delle altre per permettere il trascinamento, sarà

inizialmente vuota e successivamente verrà riempita con i risultati tabulari della query.

In cima alla pagina sono disponibili alcune opzioni per permettere di selezionare il cubo che si vuole

interrogare.

Browser Servizio

WCF

Gestore di cubi

Analysis Service

Page 14: Sistema self service di business Intelligence in ambito mobile

14

2.3.1 User experience La prima difficoltà che ci si trova ad affrontare nel progettare un sistema d’interfaccia come questo, che

abbia la possibilità di connettersi ed interrogare un cubo generico di cui non si conosce la natura né il

significato dei KPI rappresentati, è l’impossibilità di fornire un cruscotto grafico adeguato.

Scopo della business intelligence è infatti non solo quello di estrapolare e fornire dati ma anche di renderli

comprensibili all’utente, non necessariamente qualificato, che deve consultarli.

Il modo più antico e comune di rappresentare dei dati per renderli comprensibili è ovviamente utilizzarli per

produrre un grafico.

Questa possibilità è stata quindi ovviamente studiata per deciderne la possibilità o meno dell’effettiva

realizzazione, purtroppo con esisto negativo.

In primis, trovandosi di fronte a dati multidimensionali, per quanto espressi in forma tabulare ci si

troverebbe davanti all’impedimento fisico di non poter rappresentare più di tre dimensioni, occorrerebbe

perciò, date le N dimensioni dei risultati della query effettuata, andare a generare una grande quantità di

grafici, al più tridimensionali dove rappresentare, per ogni combinazione di tre dimensioni, ognuno dei KPI

richiesti.

Con N dimensioni dei risultati e K numero di KPI, dovremmo andare a generare e mostrare un numero g di

grafici richiesti

𝑔 = 𝐾 ∗ (𝑁

3)

Nel nostro caso d’uso, con un solo KPI e solo cinque possibili dimensioni ci troveremo a dover generare, al

più dieci grafici ma se andassimo a prendere un cubo come quello che viene fornito d’esempio insieme a

Microsoft Analysis Service potremo facilmente avere a che fare con più di ottanta dimensioni e più di trenta

KPI, la quantità di grafici da dover gestire diventerebbe facilmente ingestibile.

Anche ammettendo la possibilità di fornire questi grafici, il problema si sposterebbe sull’utente che si

troverebbe sia a dover consultare dei grafici probabilmente non adatti al tipo di dato che si vuole

consultare.

Non conoscendo l’effettiva natura di questi dati non sarebbe possibile scegliere in maniera univoca il

miglior rappresentazione visuale, oltre a costringere l’utente a consultare svariati grafici, ognuno dei quali

con una singola porzione della risposta alla propria domanda.

Per rendere maggiormente l’idea della problematica vediamo come potrebbe apparire la nostra

applicazione se avessimo adottato, nonostante i problemi sopra esposti, la soluzione grafica:

Page 15: Sistema self service di business Intelligence in ambito mobile

15

Figura 4 – Concept grafico di come potrebbe essere visualizzato un grafico nella nostra applicazione

Anche con un solo grafico diventa evidente la genericità della risposta e la difficoltà di interpretare questi

dati.

Per queste ragioni è stato adottato un semplice sistema di risposta in cui i dati vengono espressi in forma

tabulare, nello stesso formato in cui vengono restituiti dall’interrogazione al cubo e visualizzati con font e

stili che ne facilitino la lettura, nello specifico utilizzando formati e stili forniti dalla Twitter Corporation

nella libreria Twitter Boostrap di libero utilizzo.

2.3.2 Portabilità Trattandosi di un sistema che deve essere usato in mobilità, l’interfaccia deve prevedere la possibilità di

essere mostrata su dispositivi di diverse dimensioni e capacità.

Per risolvere questo problema è stato adottato un design detto responsive ovvero che utilizzando

l’istruzione media introdotta con la terza versione dei fogli di stile CSS ci permette di adattare gli stessi

elementi della pagina ai diversi tipi di schermi senza la necessità di dover costruire una nuova web

application per i diversi tipi di dispositivi.

L’applicazione funziona quindi perfettamente su qualunque dispositivo di dimensioni medie o grandi

mentre per i dispositivi più piccoli, pur mantenendo la funzionalità, sono state evidenziate difficoltà

implicite nell’utilizzo del sistema.

Qui possiamo vedere come apparirebbe l’applicazione su di un mini tablet della dimensione di questa

pagina

Page 16: Sistema self service di business Intelligence in ambito mobile

16

Figura 5 – Screenshot dell’interfaccia grafica della nostra applicazione utilizzata su un cubo d’esempio

Per quanto sia perfettamente funzionale e ci sia ancora a disposizione abbastanza spazio per il drag and

drop degli elementi è facile vedere come lo spazio a disposizione per i risultati della query si sia ridotto

notevolmente, rendendo necessario lo scrolling della tabella, in questo caso in senso orizzontale e

rendendo disagevole la lettura dei dati.

Sui dispositivi ancora più piccoli quali gli smartphone, non essendo presente lo spazio fisico per poter

effettuare il drag and drop degli elementi, questa funzionalità viene sostituita dalla possibilità di selezionare

gli elementi con un doppio click.

Ciò nonostante, la ridotta dimensione dello schermo va comunque ad aumentare in maniera ancora più

drastica la difficoltà di comprensione ed utilizzo e non trovando soluzioni plausibili questa possibilità di

accesso è stata accantonata.

Figura 5 – Screenshot da smartphone dell’interfaccia grafica della nostra applicazione utilizzata su un cubo d’esempio

Page 17: Sistema self service di business Intelligence in ambito mobile

17

2.3.3 Uso di HTML 5 Uno degli obbiettivi richiesti dall’azienda per questo progetto era quello di valutare la fattibilità di questo

progetto utilizzando le funzionalità introdotte con HTML 5 e quindi la possibilità di utilizzare questa nuova

tecnologia in sostituzione di vecchi prototipi realizzati con Microsoft Silverlight.

Fortunatamente, in questo caso, l’analisi ha portato ad una conclusione positiva e alla possibilità di ridurre

notevolmente la dimensione della code base e complessità del progetto in analisi, rendendolo più fruibile e

più facilmente mantenibile.

Inizialmente era stato imposto come standard l’utilizzo di Kendo Framework, una libreria di controlli

avanzati HTML e Javascript rilasciata sotto licenza AGPL da Telerik LTD per conformità e consistenza con lo

stile delle altre applicazioni realizzate da Infinity Tech Solution srl.

Nelle prove effettuate dall’azienda prima dell’inizio di questo progetto, Kendo Framework veniva utilizzato

per ogni aspetto della nostra web application, dalla strutturazione della pagina (“scaffolding”) alla gestione

dei menu di scelta e dei relativi drag and drop.

Questo tipo di approccio ha rivelato, durante le prove effettuate nel tirocinio, diverse problematiche:

Caricamento: si tratta di un framework particolarmente complesso e pesante, che viene distribuito

in una serie di librerie non indipendenti per un totale di oltre 40MB di codici Javascript e CSS che

devono essere caricati dal browser

Portabilità: Lo scaffolding realizzato con Kendo Framework non è responsive

Overhead: Le funzioni di nostro interesse, come la gestione del drag and drop e il caricamento di

documenti JSON, sono attualmente implementate nativamente dai browser HTML 5 con risultati

migliori

Per queste ragioni, su consiglio della stessa Telerik LTD, l’utilizzo del framework è stato limitato puramente

ai fogli di stile, affidando lo scaffolding responsive al framework Twitter Boostrap mentre per la gestione

degli eventi si è ricorsi ad uno script da me prodotto, basato sulle funzioni nativi disponibili, che andiamo

ora a vedere nelle sue funzioni principali:

2.3.3.1 Generazione dei menu laterali

Al caricamento di un cubo, dal menu in testa alla pagina, viene invocata la funzione loadCube alla quale

viene passato il nome del cubo con il quale essa andrà ad interrogare il nostro servizio REST per ottenerne i

metadati.

Verrà quindi ritornato un oggetto JSON che descriverà valori e attributi delle dimensioni e dei KPI del nostro

cubo, interpretando questo oggetto, la funzione provvederà alla costruzione dei menu laterali.

Per non inserire codice HTML all’interno del nostro script e rendere più facilmente mantenibile e

personalizzabile la nostra applicazione, i menu HTML non verranno generati direttamente dal codice

Javascript ma estratti da dei semplici templates ed inseriti dinamicamente all’interno del codice HTML della

nostra singola pagina.

I template utilizzati seguono la convenzione di formattazione delle stringhe di C#, dove i numeri racchiusi

tra parentesi graffe (esempio: “{0}”) vengono sostituiti dai parametri passai al template in ordine

posizionale.

Sono stati usati per poter generare gli identificativi degli elementi HTML necessari alla gestione del drag

and drop e i loro valori come membri della query DAX che andremo a comporre.

Page 18: Sistema self service di business Intelligence in ambito mobile

18

Ricordando che in Javascript le funzioni di input/output sono asincrone, per cui è necessario passare come

parametro la funzione che si intende chiamare al completamento della richiesta, vediamo per sommi capi il

funzionamento della generazione dei menu laterali.

function loadCube(name) { // Andiamo ad interrogare la funzione GetCube del nostro servizio REST // Incapsulando il nostro parametro “name” all’interno di un oggetto JSON $.ajax( { url: serviceRoot+"/GetCube", type: "POST", cache: false, data: JSON.stringify({ name: name }), contentType: "application/json; charset=utf-8", dataType: "json", processData: true, success: function (json) { //Ritrasforma la stringa ricevuta in un oggetto Javascript var data = JSON.parse(json); var attributeCounter = 0; //Carica il template HTML relativo alle dimensioni $.get("/contents/templates/dimension.html", function (dimensionTemplate) { //Carica il template HTML relativo agli attributi delle dimensioni $.get("/contents/templates/dimension.attribute.html", function (attribute) { //Per ogni dimensione e per ogni attributo in quella dimensione //genera un nuovo id HTML per l’elemento e appende il codice alla pagina for (dim in data.Dimensions) { for (attributedimension in dim.Attributes) { //… } } }); }); //Carica il template HTML relativo ai KPI $.get("/contents/templates/kpi.html", function (dimensionTemplate) { //Carica il template HTML relativo agli attributi dei KPI $.get("/contents/templates/kpi.attribute.html", function (attributeTemplate) { //Per ogni kpi e per ogni attributo in quel kpi //genera un nuovo id HTML per l’elemento e appende il codice alla pagina for (index in data.Kpis) { for (attributekpi in kpi.Attributes)

{ //… } } }); }); }, });

}

Page 19: Sistema self service di business Intelligence in ambito mobile

19

2.3.3.2 Drag and drop

Realizzare questa funzionalità in HTML5 è molto facile, basta infatti assegnare l’attributo “draggable” agli

elementi che si vuole rendere disponibili per il trascinamento.

<div id="{0}" data-unique-name="{0}" draggable="true" ondragstart="drag(event,'#{0}')">

Ad operazione completata, HTML5 non consente però di ricavare direttamente l’oggetto che è stato

trascinato, ma solo il valore della variabile “event”, si rende perciò necessaria la funzione “drag” che

all’inizio del trascinamento, andrà a memorizzare all’interno di questa l’identificativo del nostro tag HTML

che potremo così recuperare in seguito.

function drag(ev, id) { if (dragInProgress) return; dragInProgress = true; ev.dataTransfer.setData("Text",id); }

Il valore booleano “dragInProgress” impedisce il drag and drop contemporaneo di due o più oggetti che

viene erroneamente rilevato dal browser se si afferra lo stesso oggetto con più dita su di un dispositivo

multi-touch.

Analogamente a quanto fatto per le voci di menu che si vuole trascinare, per abilitare il rilascio degli oggetti

sulla nostra area dei risultati non dovremo fare altro che dichiararlo nel relativo tag.

<div id="workingArea" ondragover="allowDrop(event)" ondrop="drop(event)" >

Per impostazione di default, nessun oggetto della nostra pagina HTML5 può essere obbiettivo di un

trascinamento, prevenendo questo comportamento abilitiamo di fatto la possibilità di rilasciare oggetti

sulla nostra area dei risultati con la funzione “allowdrop”.

Quando la voce di menu verrà rilasciata, il browser invocherà l’evento “ondrop” dove recupereremo il

nostro tag originario e a seconda che si tratti di una dimensione o di un KPI lo andrà a memorizzare

nell’array corrispondente per poter poi generare la query da passare al servizio.

function allowDrop(ev) { ev.preventDefault(); } function drop(ev) { ev.preventDefault(); var data = $(ev.dataTransfer.getData("Text")); if (data.hasClass("dimension")) { queryDimension.push(data.attr("data-unique-name")); } else { queryKpi.push(data.attr("data-unique-name")); } dragInProgress = false; Query(); }

Page 20: Sistema self service di business Intelligence in ambito mobile

20

2.3.3.3 Interrogazione e risultati

Ottenuta la lista delle dimensioni e dei KPI che si intendono visualizzare, non dovremo fare altro che

comporre la nostra query ed utilizzarla per interrogare il nostro servizio, ottenendo così un array

bidimensionale dei valori ricevuti che andremo a rappresentare a schermo sotto forma di tabella.

Per come è strutturata l’applicazione, ogni singolo drag and drop determina la generazione di una nuova

query e la sostituzione dei risultati eventualmente già presenti con quelli appena ottenuti.

Questo comporta che fino a quando l’utente non avrà selezionato tutti i valori di suo interesse ci troveremo

ad avere una query incompleta, mancante delle dimensioni o dei KPI.

Qualora a mancare fossero le dimensioni non ci sarebbe alcun problema, Analysis Service ci restituirebbe

comunque il valore dei KPI lungo tutte le dimensioni, se invece venissero a mancare i KPI la query

risulterebbe invalida, generando un errore.

Per questo motivo, qualora l’utente non avesse ancora specificato alcun KPI andremo ad usare la lista

completa di questi, ignorando i loro attributi per evitare un sovraccarico di informazioni e fornendo i valori

di tutti i KPI lungo le dimensioni selezionate.

Purtroppo in questo caso, non è stato possibile utilizzare una struttura template come fatto per i menu

laterali, per separare quanto più possibile il codice degli script dal HTML che andremo a generare sul

browser.

A causa della struttura dei dati che andiamo a ricevere all’origine da Analysis Service, ovvero un semplice

un semplice insieme di righe ognuna delle quali di natura e dimensione sconosciuta, il nostro servizio lato

server non è in grado di fornirci alcun informazione aggiuntiva.

Siamo dunque costretti a scorrere quello che in JSON è stato trasformato in un array bidimensionale,

generando volta per volta le celle che andremo a trovare.

In un contesto di questo genere, il nostro semplice sistema di template si rivelerebbe ancora più

difficoltoso da usare per cui abbiamo optato, considerando la relativa dimensione di questa parte di codice,

di generare direttamente righe e colonne della nostra tabella dei risultati senza passare per un

elaborazione esterna.

function Query() { var query; //generazione della query DAX if (queryKpi.length > 0) { query = "EVALUATE SUMMARIZE(" + queryKpi.join() + ")"; if (queryDimension > 0) { query = query + " ORDER BY " + queryDimension.join(); } } else { query = "EVALUATE SUMMARIZE(" + KPIs.join() + ")"; if (queryDimension > 0) { query = query + " ORDER BY " + queryDimension.join(); } }

Page 21: Sistema self service di business Intelligence in ambito mobile

21

var json = JSON.stringify({ query: query, cube: $("#cubeList").val() }); $.ajax( { url: serviceRoot + "/Query", type: "POST", cache: false, data: json, contentType: "application/json; charset=utf-8", dataType: "json", processData: true, success: function (json) { var data = JSON.parse(json); var content = "<table>"; //costruiamo l’header della tabella var headers = "<tr><th>#</th>"; for (dimIndex in queryDimension) { headers = headers + "<th>" + queryDimension[dimIndex] + "</th>"; } headers = headers + "</tr>"; var body = ""; //ed il suo corpo for (rowIndex in data) { body = body + "<tr>"; for (cellIndex in data[rowIndex]) { body = body + "<td>" + data[rowIndex][cellIndex] + "</td>"; } body = body + "</tr>"; } content = content + headers + body + "</table>"; //mostriamo a schermo i risultati $("#workingArea").html(content); } }); }

Servizio WCF Centro della business logic della nostra web application è il servizio Windows Comunication Foundation che

si occupa di soddisfare le richieste dei nostri script lato client.

Adottando questo tipo di servizio per gestire e richieste del client, non ci dovremo preoccupare di gestire lo

stack di chiamate HTTP al nostro server, compito che verrà eseguito automaticamente dal server Windows

dove andremo ad installare il nostro servizio.

Il nostro servizio andrà dunque a servire sulla rete i quattro metodi fondamentali che stanno alla base della

nostra web-application, che verranno richiamati in base all’URL richiesto

string GetCube(string name): Ritorna dimensioni e KPI del cubo richiesto

string[] ListCubes(): Ritorna l’elenco dei cubi gestiti

string AddCube(string connectionString): Aggiunge un cubo alla collezzione

string Query(string cube, string query): Esegue la query sul cubo specificato

Page 22: Sistema self service di business Intelligence in ambito mobile

22

Per lo standard imposto da WCF il servizio dovrà essere definito come una classe, DAXQueryService, che

implementi le parti di codice da richiamare e un interfaccia, IDAXQueyService che definisca tipo di trasporto

ed URL su cui verranno esposti i metodi.

Per poter esporre questa interfaccia come servizio WCF, l’interfaccia deve implementare l’attributo

ServiceContract, così come tutti i tipi non primitivi di Microsoft .Net che si vorranno impiegare, mentre ogni

metodo esposto dovrà implementare l’attributo OperationContract.

[ServiceContract] public interface IDAXQueryService { [OperationContract] string GetCube(string name); }

Come detto in precedenza, il nostro servizio funzionerà ricevendo ed inviando messaggi in formato JSON,

codifica language agnostic che è stata scelta per la facilità con cui viene gestita dal codice Javascript lato

client.

Il formato JSON non è però disponibile di default per i servizi WCF e deve essere abilitato, sempre

attraverso gli attributi dell’interfaccia.

[OperationContract] [WebInvoke(Method = "POST", UriTemplate = "GetCube", BodyStyle = WebMessageBodyStyle.WrappedRequest, ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json )] string GetCube(string name);

Contrariamente a quanto accade in un servizio RESTful, i dati arrivo dovranno essere incapsulati dentro ad

oggetti JSON che le implementino come membri dell’oggetto, anziché come variabili POST della sessione

HTTP.

Quindi, per essere interrogato, il nostro metodo GetCube dovrà ricevere la stringa di input, incapsulata in

un oggetto come questo:

{“name”:”MyCube”}

Per i dati in uscita, di ritorno al client che ha interrogato il servizio, non succede però la stessa cosa, nel caso

di JSON, il framework WCF serializza esclusivamente gli oggetti complessi mentre tipi primitivi come numeri

e stringhe vengono restituiti come semplici valori testuali, nel caso delle stringhe sottintendendo che la

stringa ritornata sia già effettivamente in formato JSON.

Questa mancanza di consistenza da parte del framework WCF si è rivelata comunque molto utile per poter

ridurre l’overhead di serializzazione della nostra web application come vedremo nella sezione successiva.

Page 23: Sistema self service di business Intelligence in ambito mobile

23

Il Gestore di Cubi Funzionalità principale della nostra web application sarà quella di andare a recuperare dimensioni e KPI del

cubo che interessa interrogare.

Questa funzionalità è realizzata dal CubeManager che si occuperà di recuperare questi dati ed

immagazzinarli localmente.

2.5.1 Estrazione dei metadati Per recuperare i metadati del nostro cubo Analysis Service è necessario utilizzare un driver di connessione

specifico detto AdoMd che fornisce esclusivamente questa funzionalità senza possibilità di effettuare

interrogazioni.

Come visto nel primo capitolo, Analysis Service implementa l’ipercubo attraverso diverse strutture dati,

molte delle quali non sono nascoste e che dovremo iterare per andare a recuperare i pochi dati che ci

interessano.

Per prima cosa dovremo andare a scartare i sotto cubi generati per ogni KPI e quelli temporanei generati

come cache dei risultati.

Otterremo così la definizione del nostro ipercubo che conterrà una parte dei metadati che ci interessa

recuperare e da essa il cubo vero e proprio.

public static void Import(string connectionString) { //Apre la connessione ad Analysis Service var data = new Server(); data.Connect(connectionString); var metadataExtractor = new AdomdConnection(connectionString); metadataExtractor.Open(); foreach (CubeDef definition in metadataExtractor.Cubes) { //Escludiamo i sotto-cubi dalla nostra ricerca if (definition.Name[0] == '$') continue; //Dalla definizione del cubo passiamo al cubo vero e proprio Cube realCube = data.Databases[metadataExtractor.Database].Cubes[definition.Name]; //Iteriamo il cubo per estrarne dimensioni e KPI var cubeData = new CubeDescription(definition, realCube,connectionString); //Salviamo i dati ottenuti var path = CubePath(cubeData.Name); File.WriteAllText(path,JSON.Serialize(cubeData)); } }

Incrociando i dati di Cube e CubeDef andremo quindi a generare un nostro albero di dati che conterrà solo i

metadati utili alla nostra web application sotto il nome di CubeDescription.

Page 24: Sistema self service di business Intelligence in ambito mobile

24

La nostra descrizione del cubo conterrà il nome del cubo stesso, la stringa di connessione con cui

successivamente sarà possibile interrogarlo, le dimensioni che saranno estratte della definizione ed i KPI

che saranno invece estratti dal cubo vero e proprio.

Alcuni nomi di oggetti sono specificati attraverso il nome completo del loro tipo anziché a causa delle

sovrapposizioni di nomi all’interno dei due namespace Microsoft.AnalysisServices e

Microsoft.AnalysisServices.AdomdClient utilizzate dalle diverse parti del framework che andiamo ad

utilizzare.

[DataMember] public DimensionDescription[] Dimensions; [DataMember] public KpiDescription[] Kpis; [DataMember] public string Name; [DataMember] public string ConnectionString; public CubeDescription(CubeDef definition,Cube cube, string connectionString) { ConnectionString = connectionString; Name = definition.Name; var tmpDimensions = new List<DimensionDescription>(); //estriamo le dimensioni del cubo dalla CubeDef foreach (Microsoft.AnalysisServices.AdomdClient.Dimension dim in definition.Dimensions) { if (dim.DimensionType != DimensionTypeEnum.Measure) { tmpDimensions.Add(new DimensionDescription(dim)); } } Dimensions = tmpDimensions.ToArray(); // estraiamo i KPI dal cubo var tmpKpis = new List<KpiDescription>(); foreach (MeasureGroup group in cube.MeasureGroups) { tmpKpis.Add(new KpiDescription(group)); } Kpis = tmpKpis.ToArray(); }

A loro volta le descrizioni di KPI e dimensioni andranno ad iterare le proprietà fornite da Analysis Service

per andare a memorizzare i propri attributi, con il proprio nome e il proprio path all’interno della

dimensione o del KPI.

Page 25: Sistema self service di business Intelligence in ambito mobile

25

2.5.2 Caching dei metadati I dati che andiamo a memorizzare, per ogni cubo, corrispondono più o meno al due percento di quelli

forniti da Analysis Service, questo processo ha perciò un collo di bottiglia nel processo di estrazione.

Durante le prove effettuate, è inoltre emersa una scarsa efficienza del serializzatore JSON fornito con WCF,

che impiegando un tempo eccessivo per trasformare la nostra semplice descrizione del cubo ed i suoi

metadati, dava l’impressione di un blocco nella nostra web application, nel migliore dei casi, una risposta in

tempi non consoni.

Sfruttando la mancanza di consistenza vista alla fine del sezione 2.4, ovvero che i valori restituiti dal nostro

servizio verranno serializzati in formato JSON dal framework WCF solo se complessi, mentre una stringa

verrà interpretata come già in questo formato e quindi non re-incapsulata, abbiamo optato per una

serializzazione a monte dei nostri metadati.

La struttura di un ipercubo, per sua natura non ha cambiamenti frequenti, secondo i dati forniti dall’azienda

si ha una modifica mediamente ogni due mesi, per cui anziché generare i dati del cubo al suo caricamento

nel browser, andremo a generarli quando questo sarà aggiunto alla collezione dei cubi che ci interessa

consultare (mostrata nella barra di navigazione in testa all’interfaccia HTML) ed eventualmente ricaricarli

qualora ce ne fosse il bisogno.

Non potendo richiamare direttamente il serializzatore JSON del framework WCF, ne abbiamo importato

uno scritto da me (Fabbri, 2011) come fork del progetto open source fastJSON (Gholam, 2011) e

correntemente utilizzato da alcuni anni su server di produzione.

Questo verrà richiamato dal CubeManager nella funzione Import vista nel sezione 2.5.1

public static void Import(string connectionString) { //Connessione ad Analysis Service foreach (CubeDef definition in metadataExtractor.Cubes) {

//Generazione dei metadati //Salvataggio dei metadati var path = CubePath(cubeData.Name); File.WriteAllText(path,JSON.Serialize(cubeData)); } }

Non avendo a disposizione un secondo database server su cui andare a memorizzare questi dati, si è scelto

di salvarli localmente su file, in attesa di sviluppi futuri.

Grazie a questo meccanismo di caching, siamo riusciti quindi a rendere disponibili e funzionali i dati

nell’interfaccia HTML in pochi millesimi di secondo, contrariamente a quanto accaduto durante le prove

svolte dove si poteva facilmente superare il minuto di tempo di attesa.

Page 26: Sistema self service di business Intelligence in ambito mobile

26

3 Conclusioni Da quanto visto fin ora possiamo trarre alcune importanti conclusioni sul lavoro svolto fin ora, sui tools

utilizzati e sui possibili sviluppi futuri.

Nel complesso, il progetto si è rivelato efficace ed ha raggiunto buona parte degli obbiettivi che si erano

prefissati, l’architettura three-tier e la sua implementazione si sono rivelate assolutamente adatte allo

scopo, mentre è possibile fare alcuni commenti puntuali sulle tre componenti della web application per

determinarne debolezze e features implementabili o desiderabili.

Interfaccia web

Nel suo complesso l’interfaccia e la user experience si sono rivelate efficaci e funzionali allo scopo ma lo

sviluppo a singola pagina ne ha limitato fortemente le possibilità di interazione, sarebbe perciò consigliabile

lo studio di un sistema più complesso, composto da più pagine, anche generate tramite script server-side,

che vadano ad integrare il sistema attuale per migliorarne la gestione attraverso interfacce

d’amministrazione e permessi d’accesso.

La visualizzazione tabulare consente una buona lettura dei dati, che diventa però disagevole sugli schermi

più piccoli e come visto nella sezione 2.3.1 la presenza di grafici e cruscotti dedicati sarebbe desiderabile, si

potrebbe perciò aggiungere la possibilità di sostituire determinati gruppi di dimensioni e KPI con interfacce

grafiche appositamente create e caricate sul sistema.

Il design responsive ha dato ottimi risultati su qualunque piattaforma ad eccezione degli smartphone,

sarebbe quindi da valutare la possibilità di costruire una seconda interfaccia dedicata esclusivamente a

questo tipo di dispositivi, secondo una user experience diversa.

Servizio dati WCF

Si tratta di un servizio molto semplice ma basato su di un framework molto complesso e pesante, che

durante le prove effettuate ha rivelato un corposo overhead e prestazioni non desiderabili in termini di

tempi di risposta e di carico della macchina su cui era eseguito.

Pur supportando la serializzazione JSON, mal si adatta a questo tipo di utilizzo, che non è il suo scopo

principale d’utilizzo.

Il consiglio pertanto è quello di sostituire questo servizio con uno simile, basato però su di un design

RESTful e fondato su di un ambiente più leggero.

Gestione di metadati e cubi

In questa parte del progetto non sono state rivelate particolari problematiche sul versante del nostro

progetto, mentre ne sono state riscontrate diverse riguardanti le librerie AdoMd per accedere ai metadati

del cubo e riguardanti lo stesso Analysis Service.

Sarebbe dunque consigliabile cercare un driver di connessione alternativo, possibilmente che espanda i

server accessibili anche ad altre marche di prodotti OLAP.

Infine, sarebbe inoltre consigliabile implementare la gestione dei metadati attraverso un

immagazzinamento su database anziché su file

Page 27: Sistema self service di business Intelligence in ambito mobile

27

4 Bibliografia Cormen, T. H. (2009). Introduction to Algorithms. Massachusetts Institute of Technology.

Council, O. (1995). OLAP and OLAP Server Definitions.

Devens, R. M. (1865). Cyclopædia of Commercial and Business Anecdotes. Londra: Appleton and company.

Fabbri, M. (2011). NetFluid Source Code Repository. Tratto da GitHub:

https://github.com/matteofabbri/netfluid/tree/master/NetFluid/Serialization

Gartner. (2013). Olap 2013. Gartner.

Gholam, M. (2011). fastJSON. Tratto da CodePlex: http://fastjson.codeplex.com/

Gorbach Irina, B. A. (2008). Microsoft SQL Server Analysis Services Unleashed. Sams.

IDC. (2012). IDC Predictions 2013. Framingham: IDC Corporate USA.

MasterCard. (2013). MasterCard Report 2013.

Power, D. (2007). A Brief History of Decision Support Systems. DSS Resources.

Un sentito ringraziamento a tutto lo staff del DISI, di Infinity, ai più o meno giovani goliardi, ai miei

compagni fuori corso, ai miei amici, ai miei genitori ed al mio Ammmore :p

Un grosso mucchio di persone che mi ha supportato e sopportato per tutto questo tempo!