SlideShare a Scribd company logo
1 of 77
Download to read offline
Universit`a degli Studi di Parma
Dipartimento di Matematica e Informatica
La persistenza poliglotta:
analisi di un’applicazione
in un contesto aziendale
Candidato:
Gabriele Etta
Relatore:
Prof. Enea Zaffanella
Correlatore:
Alessandro Alpi
Anno Accademico 2015 - 2016
22 Dicembre 2016
2
Ad Alessandro, Daniela, Giordano e Martina.
Indice
1 I database NoSQL e la persistenza poliglotta 7
1.1 Caratteristiche strutturali dei database NoSQL . . . . . . . . . . . . 7
1.1.1 Flessibilit`a nella manipolazione dei diversi tipi di dato . . . . 7
1.1.2 Performance elevate . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2 Caratteristiche architetturali dei database NoSQL . . . . . . . . . . . 8
1.2.1 Il teorema CAP (Consistency, Availability, Partition Tolerance) 10
1.3 Categorie di database NoSQL . . . . . . . . . . . . . . . . . . . . . . 12
1.3.1 Database di tipo Key - Value . . . . . . . . . . . . . . . . . . 12
1.3.2 Database documentali . . . . . . . . . . . . . . . . . . . . . . 14
1.3.3 Database a grafo . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.4 La persistenza poliglotta . . . . . . . . . . . . . . . . . . . . . . . . . 18
2 Tecnologie, strumenti e pattern utilizzati 21
2.1 Tecnologie utilizzate . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.1.1 Framework .NET . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.1.2 ASP.NET MVC . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.2 Strumenti utilizzati . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.2.1 Visual Studio . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.2.2 Microsoft Azure . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.2.3 SQL Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.2.4 SQL Server Management Studio . . . . . . . . . . . . . . . . . 23
2.2.5 DBMS NoSQL utilizzati . . . . . . . . . . . . . . . . . . . . . 23
2.2.6 Git . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.2.7 RedGate SQL Source Control . . . . . . . . . . . . . . . . . . 24
2.2.8 Entity Framework . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.3 Pattern utilizzati . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.3.1 Model View View-Model (MVVM) . . . . . . . . . . . . . . . 25
2.3.2 Kanban . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
3 Il contesto applicativo 27
3.1 Descrizione e scopi dell’applicazione . . . . . . . . . . . . . . . . . . . 27
3.2 Struttura dell’applicazione . . . . . . . . . . . . . . . . . . . . . . . . 28
3.3 La soluzione monolitica . . . . . . . . . . . . . . . . . . . . . . . . . . 34
3.3.1 Registrazione di una nuova azienda . . . . . . . . . . . . . . . 34
3.3.2 Modifica dei dati di un’azienda . . . . . . . . . . . . . . . . . 37
3.3.3 Visualizzazione del pannello di controllo di un utente . . . . . 38
3.3.4 Inserimento di un prodotto . . . . . . . . . . . . . . . . . . . . 39
3.3.5 Aggiornamento delle informazioni di un prodotto . . . . . . . 41
3
4 INDICE
3.3.6 Ricerca dei prodotti in base alla descrizione e aggiunta al
carrello. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
3.3.7 Visualizzazione dei prodotti all’interno del carrello . . . . . . . 42
3.3.8 Finalizzazione dell’acquisto . . . . . . . . . . . . . . . . . . . . 45
3.3.9 Accesso al sistema . . . . . . . . . . . . . . . . . . . . . . . . 48
3.3.10 Disconnessione dal sistema . . . . . . . . . . . . . . . . . . . . 50
3.4 La soluzione poliglotta . . . . . . . . . . . . . . . . . . . . . . . . . . 50
3.4.1 Architettura della soluzione . . . . . . . . . . . . . . . . . . . 50
3.4.2 Accesso al sistema . . . . . . . . . . . . . . . . . . . . . . . . 52
3.4.3 Inserimento e modifica dei dati di un’azienda . . . . . . . . . . 52
3.4.4 Inserimento e modifica delle informazioni relative ad un prodotto 52
3.4.5 Ricerca dei prodotti in base alla sua descrizione . . . . . . . . 53
3.4.6 Inserimento di prodotti all’interno del carrello . . . . . . . . . 53
3.4.7 Visualizzazione dei prodotti presenti nel carrello . . . . . . . . 53
3.4.8 Finalizzazione di un acquisto . . . . . . . . . . . . . . . . . . . 53
3.4.9 Analisi e consiglio sui prodotti potenzialmente interessanti
all’utente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
4 Confronti e analisi 57
4.1 Ricerca di prodotti . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
4.2 Analisi predittiva per il consiglio di prodotti . . . . . . . . . . . . . . 66
5 Conclusioni 69
5.1 Conclusioni e sviluppi futuri . . . . . . . . . . . . . . . . . . . . . . . 69
Appendici 71
A Glossario 73
Introduzione
Nel seguente lavoro di tesi verr`a presentato un prototipo di una piattaforma di
e-commerce, sviluppata all’interno dell’azienda in cui `e stato svolto il tirocinio for-
mativo, che utilizza due architetture diverse per assicurare la persistenza dei dati
al suo interno. Nella prima soluzione, indicata nelle pagine a seguire con il termi-
ne monolitica, verr`a utilizzato un solo database relazionale per salvare ogni tipo di
informazione necessaria, mentre nella seconda soluzione, indicata con il termine po-
liglotta, verr`a estesa quella precedente facendo affidamento ai database appartenenti
alla categoria NoSQL (Not Only SQL) e al concetto di persistenza poliglotta da cui
prende il nome. Lo scopo della tesi sar`a quello di mostrare che, in caso di applica-
zioni aziendali che utilizzano un’elevata mole di dati diversi tra loro, l’utilizzo di un
database relazionale pu`o portare ad inefficienze dal punto di vista delle operazioni
svolte al suo interno, preferendo soluzioni in cui la presenza di pi`u tipologie di da-
tabase offre la possibilit`a di suddividere il dominio della base di dati assegnando a
ciascuno di essi uno specifico sottodominio che coincider`a con quello per cui sono
stati ottimizzati, incrementando le perfomance complessive.
Le pagine che seguiranno sono state organizzate su quattro capitoli introducendo
al lettore i fondamenti teorici del mondo dei database NoSQL in modo tale da poter
parlare delle tecnologie e dello sviluppo vero e proprio delle due soluzioni senza
ambiguit`a. Avremo quindi:
• il primo capitolo dedicato alla descrizione dei database NoSQL, mostrando
le tipologie pi`u utilizzate con le loro caratteristiche, e al concetto di persistenza
poliglotta di cui sono attori.
• il secondo capitolo sar`a dedicato alla descrizione delle tecnologie, dei pat-
tern e degli strumenti di sviluppo utilizzati nella creazione dell’applicazione
gettandone le basi dal punto di vista teorico.
• il terzo capitolo racchiuder`a lo sviluppo vero e proprio dell’applicazione a
partire dalla sua struttura generale, per poi passare a descrivere lo sviluppo
delle funzionalit`a fornite nelle due soluzioni.
• il quarto capitolo mostrer`a i confronti eseguiti tra le due soluzioni rispetto
ad alcune funzionalit`a principali, mettendo in evidenza vantaggi e svantaggi
in esse presenti.
• nella conclusione verr`a riassunto il lavoro svolto con un verdetto sull’efficacia
dei due approcci, introducendo gli sviluppi futuri dell’applicazione.
5
6 INDICE
Capitolo 1
I database NoSQL e la persistenza
poliglotta
In questo capitolo introdurremo la categoria dei database denominata NoSQL, de-
scrivendone le caratteristiche principali e fornendo una loro tassonomia, introducen-
do successivamente il concetto di persistenza poliglotta su cui verter`a il lavoro di
tesi.
1.1 Caratteristiche strutturali dei database No-
SQL
NoSQL `e un termine utilizzato per descrivere quella categoria di database in cui i dati
sono organizzati seguendo un modello diverso dai tradizionali database relazionali.
Per comprenderne al meglio le differenze e le motivazioni all’uso verr`a fornita una
descrizione delle sue caratteristiche principali.
1.1.1 Flessibilit`a nella manipolazione dei diversi tipi di dato
La molteplicit`a dei tipi di dato, dovuta alle variazioni del mercato su cui operano
le applicazioni e al repentino cambiamento della natura del software, `e ormai un
argomento di importanza centrale nell’implementazione e nella gestione delle ap-
plicazioni il cui approccio tradizionale si rivolge spesso ad un solo tipo di storage,
generalmente costituito da database relazionali. I DBMS a cui fanno riferimento
infatti non sono abbastanza flessibili per gestire una elevata mole di dati di tipo
diverso tra loro e, per questa ragione, gran parte delle aziende hanno seriamente
considerato di valutare soluzioni di storage differenti al fine di dare una risposta
efficace. Questa “nuova” categoria di database permette di gestire le diversit`a intro-
dotte senza dover imporre restrizioni sullo schema di rappresentazione del dato al
punto da ottenere dalla comunit`a informatica l’etichetta di schema-less. Tale carat-
terizzazione, tuttavia, `e corretta solo in parte, poich`e nel mondo NoSQL lo schema
di un database `e definito intrinsecamente dall’applicazione. Spetter`a infatti ad essa
il compito di codificare e decodificare il flusso di dati ricevuti dal DBMS al momento
dell’invio o della lettura. Questa caratteristica mette altres`ı in evidenza il fatto gli
che eventuali errori dovuti alla discordanza tra lo schema definito a livello di appli-
cazione e i dati prelevati dal database siano una responsabilit`a dello sviluppatore.
7
8 CAPITOLO 1. I DATABASE NOSQL E LA PERSISTENZA POLIGLOTTA
Al contrario, nel contesto dei DBMS relazionali (o RDBMS), la presenza di uno
schema modellato a priori assicura ed impone una maggiore rigorosit`a sull’insieme
di dati e delle strutture da gestire.
1.1.2 Performance elevate
Il modello relazionale memorizza le informazioni organizzandole secondo il concetto
di tupla che, in certi casi, risulta essere una struttura dati limitata, non potendo
ad esempio inserirne una all’interno di un’altra al fine di ottenere annidamenti. I
database NoSQL a tal proposito mostrano un approccio differente: essi partono dal-
l’idea che i dati abbiano una struttura pi`u complessa di una semplice tupla e, per
tale ragione, identificano il concetto di aggregato, ovvero una collezione di “oggetti”
legati tra loro su cui vengono eseguite operazioni. Ognuno di essi `e visto dal moto-
re dei database NoSQL come una singola unit`a, atomica, indipendentemente dalla
loro struttura interna. Questa caratteristica, unita al fatto che gran parte di questi
DBMS non supporta transazioni di tipo ACID, permette di avere performance po-
tenzialmente elevate sia in lettura che in scrittura, senza togliere all’applicazione la
possibilit`a di annidare pi`u sorgenti di dati secondo un proprio schema.
1.2 Caratteristiche architetturali dei database No-
SQL
In questa sezione forniremo un confronto tra il mondo relazionale e quello No-
SQL, ponendo particolare attenzione alle caratteristiche architetturali di quest’ul-
tima realt`a. Prima di cominciare `e tuttavia necessario introdurre il concetto di
scalabilit`a a cui faranno riferimento le successive considerazioni. Esso, in ambito
database, indica la caratteristica con cui vengono gestite le richieste di lettura e
scrittura all’aumentare sia della dimensione della base di dati che del numero di
operazioni stesse. Pi`u generalmente, si pu`o affermare che la scalabilit`a `e il fattore di
crescita o diminuzione di un sistema al variare delle necessit`a e delle disponibilit`a.
Essa pu`o essere di due tipi: verticale, per la quale cambiano le caratteristiche del
sistema atto a contenere il database (in termini di risorse CPU, RAM, e cosi via),
oppure orizzontale, che si ottiene aggiungendo ulteriori nodi all’infrastruttura, visti
come istanze del DBMS gestore, macchine virtuali o server. Entrambi gli approcci
hanno vantaggi e svantaggi sia in termini economici che di complessit`a. Tuttavia,
la scalabilit`a orizzontale non risente dei limiti strutturali della prima, andando per`o
ad incidere sulla consistenza del dato: a titolo di esempio, replicare un dato su pi`u
nodi pu`o far s`ı che durante le operazioni di scrittura si possa incappare in letture
di informazioni non ancora aggiornate. Questo rovescio della medaglia comporta la
necessit`a di scegliere preventivamente la natura dei dati da utilizzare poich`e, in caso
di inconsistenza, il danno causato sia il minore possibile (letture sporche, fantasma,
non aggiornate).
In generale, la scalabilit`a, sia essa orizzontale o verticale, pu`o essere implementata
tramite:
• partizionamento: di tipo orizzontale nel caso in cui si suddividano gli og-
getti, che rimangono strutturalmente identici, all’interno dello stesso database
in base alla qualit`a (valore) del dato. Il suo accesso `e definito da logiche di
1.2. CARATTERISTICHE ARCHITETTURALI DEI DATABASE NOSQL 9
business che canalizzano il flusso dei chiamanti verso la sorgente pi`u oppor-
tuna. Nel caso di partizionamento verticale si opta invece per suddividere le
propriet`a in pi`u oggetti: si pensi ad un entit`a da modellare molto grande per il
quale `e possibile effettuare la suddivisione in pi`u oggetti diversi. In tal caso si
opera identificando le diverse aree funzionali presenti al suo interno isolandole
al fine di ottenere pi`u sottoinsiemi di granularit`a minore.
• sharding (frammentazione): in questo caso la scalabilit`a orizzontale si
realizza dividendo il contenuto dei diversi database tra i nodi atti a gestirli.
Vengono quindi ”installate” pi`u istanze del DBMS potenzialmente su altret-
tante macchine (economiche, anche virtuali) facendo in modo che esse possano
condividere dati tra loro. Questa suddivisione `e resa possibile da una chiave
detta di “segmentazione”. Il problema principale di questa soluzione sta nel
fatto che uno di questi nodi pu`o essere momentaneamente non disponibile. Per
evitare ci`o, assicurando al tempo stesso un maggiore livello di business con-
tinuity, viene generalmente utilizzata la replica per la quale un dataset viene
copiato su pi`u nodi. Questa tecnica pu`o essere realizzata mediante l’impiego di
diverse architetture, anche se fra tutte `e possibile identificarne due principali:
– master - slave: questa architettura di replica vede la presenza di un
nodo principale, detto master, in relazione ai restanti nodi detti slave. Al
suo interno, le modifiche effettuate su un nodo di tipo master vengono
propagate a tutti gli altri nodi slave, migliorando la scalabilit`a di lettura
dal momento che queste richieste possono essere smistate su pi`u fronti.
Questo meccanismo ha come svantaggio quello di dare origine ad un unico
punto di fallimento: in caso di malfunzionamento di un nodo, le letture
continueranno ad essere servite correttamente ma gli aggiornamenti dei
data set non saranno disponibili. Per tali ragioni, un’architettura di tipo
aster - slave `e utile nei casi in cui i data set hanno un alto traffico in
lettura ma non in scrittura.
Figura 1.1: Rappresentazione dell’architettura master-slave.
10 CAPITOLO 1. I DATABASE NOSQL E LA PERSISTENZA POLIGLOTTA
– peer to peer: questa architettura risolve il problema descritto al punto
precedente. Al suo interno, tutti i nodi hanno la medesima importanza
e sono in grado di gestire sia le richieste di lettura che di scrittura. In
caso di fallimento di un nodo non viene intaccata la business continuity
dell’infrastruttura, ed anzi, si ha la possibilit`a di aggiungere dei nuovi
nodi senza dover incorrere a tempi di inattivit`a del sistema.
Figura 1.2: Rappresentazione dell’architettura peer to peer.
1.2.1 Il teorema CAP (Consistency, Availability, Partition
Tolerance)
Ora che sono state introdotte le caratteristiche comuni a tutti i sistemi distribuiti di
tipo NoSQL, definiamo un teorema che ne caratterizza la struttura conosciuto come
Teorema CAP (CAP Theorem). Formulato da Eric Brewer nel 2000, esso afferma
che `e possibile ottimizzare contemporaneamente solamente due caratteristiche tra
consistenza (consistency), disponibilit`a (availability) e tolleranza al partizionamento
(partition tolerance). Le prime due caratteristiche sono gi`a state precedentemente
discusse, mentre l’ultima indica la capacit`a di un cluster nel sopravvivere ai vari
malfunzionamenti che impediscono alle sue partizioni di comunicare tra loro.
1.2. CARATTERISTICHE ARCHITETTURALI DEI DATABASE NOSQL 11
Figura 1.3: Rappresentazione dei risultati del teorema CAP
Il teorema dimostra che per i database distribituiti di tipo NoSQL possono esi-
stere tre diversi scenari in base alla coppia di caratteristiche su cui si `e deciso di
investire:
• CP (Consistency - Partition tollerance): in sistemi di questo tipo i dati
letti sono sempre aggiornati all’ultima scrittura e le partizioni di un cluster
hanno rarissimi problemi di comunicazione. Per contro, le richieste in lettura
e scrittura provenienti dall’esterno su un singolo nodo potrebbero non fornire
una risposta o, nel caso lo facessero, impiegherebbero tempi non ragionevoli
mettendo in pericolo la disponibilit`a dell’intera infrastruttura.
• AP (Availability - Partition tollerance:) in sistemi di questo tipo la
risposta alle richieste di lettura e scrittura `e sempre garantita insieme alla
comunicazione interna tra le partizioni del cluster. Per contro, la mancanza di
consistenza pu`o creare problemi di aggiornamento dei dati tra i diversi nodi
di un cluster, dando luogo a fenomeni di letture sporche (dirty read) per cui i
dati prelevati non appartengono al dataset pi`u aggiornato.
• CA (Consistency - Availability): sono i classici DBMS relazionali in cui
i database sono salvati in un’unica partizione. Nel caso di decidesse di incre-
mentare le partizioni si ricadrebbe in un sistema di tipo CP a causa del fatto
che la garanzia delle transizioni ACID andrebbe a compromettere la continua
disponibilit`a del dato.
Facendo un confronto tra questo teorema e le propriet`a ACID si pu`o notare una
notevole differenza, a cominciare dal punto di vista semantico. La lettera ”C” e la
lettera ”A” del teorema appena visto rappresentano concetti diversi da quelli presenti
in ACID: in ambito NoSQL, la consistenza indica che un insieme di dati `e copiato
e disponibile su tutti i nodi in cui `e replicato, a differenza dell’ambito relazionale in
cui si fa riferimento allo stato di un database prima e dopo una transazione. Tale
diversit`a `e presente anche nella lettera ”A” dei due acronimi: in ambito NoSQL si
12 CAPITOLO 1. I DATABASE NOSQL E LA PERSISTENZA POLIGLOTTA
intende la disponibilit`a del dato, replicato su pi`u nodi, mentre in ambito relazionale
si intende l’atomicit`a di una transazione.
Tutte queste differenze hanno portato, nel corso degli anni, a definire un acro-
nimo per i sistemi NoSQL distribuiti che `e complementare alle propriet`a ACID
dei database relazionali. Esso prende il nome di BASE ed `e formato dai seguenti
termini:
• BAsically available (Disponibilit`a di base): indica che il sistema offre
una disponibilit`a di base, secondo quanto definito nel teorema CAP.
• Soft state (Stato mutabile:) indica che il dataset pu`o cambiare nel corso
del tempo anche in assenza di scritture.
• Eventual consistency (Consistenza futura): poich´e l’aggiornamento su
tutti i nodi di un cluster non `e sempre garantito, questo termine indica che
il sistema risulter`a consistente solo quando smetter`a di ricevere dati in input.
Durante la sua esecuzione non verr`a per`o fatto alcun controllo sulla consistenza
rispetto ad altre transazioni eseguite in contemporanea.
1.3 Categorie di database NoSQL
In questa sezione verranno presentati i principali tipi di database NoSQL dispo-
nibili, caratterizzandoli in merito alla gestione della consistenza, delle transazioni,
alle caratteristiche delle query che utilizzano, alla scalabilit`a e alle strutture dati
utilizzate.
1.3.1 Database di tipo Key - Value
E’ la categoria di database NoSQL pi`u semplice dal punto di vista strutturale. Es-
si non sono altro che una tabella hash formata da due colonne: una chiave, che
contiene per ogni record inserito un valore univoco su cui vengono effettuate le ope-
razioni di hashing, e un valore, generalmente rappresentato da un BLOB (Binary
Large OBject) che contiene un insieme di dati al quale l’applicazione dovr`a dare un
significato sempre secondo l’ottica schemaless caratteristica dei NoSQL.
Figura 1.4: Un esempio di database di tipo key- value.
1.3. CATEGORIE DI DATABASE NOSQL 13
Oltre a questo, tali database offrono generalmente la possibilit`a di salvare dati
per un determinato periodo di tempo predisponendoli a contenere informazioni la
cui natura `e volatile o sensibile ai fini dell’applicazione in cui verranno utilizzati.
Da un punto di vista pi`u pratico invece, abbiamo tre tipologie di operazioni esegui-
bili:
• get(chiave): preleva il valore associato alla chiave.
• put(chiave, valore): inserisce o aggiorna il valore associato alla chiave for-
nita.
• delete(chiave): rimuove il valore associato alla chiave.
La struttura e la tipologia di operazioni eseguibili permette di fare diverse con-
siderazioni sulle caratteristiche elencate ad inizio sezione, parlando quindi di:
• consistenza
La consistenza `e applicabile solo alle operazioni su chiave singola ed `e garantita
nelle implementazioni distribuite di questi sistemi. Dal momento che il dato
viene replicato su pi`u nodi, esistono due modi principali per risolvere i conflitti
durante un aggiornamento: dando precedenza all’operazione di scrittura pi`u
recente o ritornando all’utente entrambi i risultati dell’operazione lasciando
ad esso la decisione su quale mantenere.
• transazioni
Generalmente questi tipi di database danno la possibilit`a di implementare le
transazioni in modo differente purch´e si basino sul concetto di quorum, facen-
do s`ı che non ci siano garanzie sulla scrittura. Questo termine, tipico degli
scenari NoSQL, indica che all’aumentare dei nodi coinvolti in una richiesta
diminuisce anche la possibilit`a di avere inconsistenza tra loro. Esso definisce
inoltre il numero di nodi necessari al fine di garantire una consistenza forte
(strong consistency), basandosi sul fatto che in un contesto di dati replicati
su pi`u nodi non `e necessario che le operazioni di scrittura vadano a buon fine
sulla loro totalit`a ma solo sulla loro maggioranza. Questa propriet`a prende il
nome di Quorum per la scrittura (write quorum) e indica che, in un’operazio-
ne di scrittura, il numero di nodi che partecipano all’operazione di scrittura
(indicati con W ) deve essere maggiore della met`a dei nodi su cui viene fatta la
replica dei dati (N ), ovvero W>N/2. Analogamente, esiste anche il concetto
di quorum di lettura (read quorum) che definisce il numero di nodi necessari
per avere maggiore sicurezza di avere accesso ad una determinata porzione di
dati aggiornati alla loro ultima versione. Essa non `e sempre definibile me-
diante una disuguaglianza come sopra descritto, poich´e dipende dal numero di
nodi che devono confermare l’avvenuta scrittura. Nonostante ci`o, `e possibile
affermare che il totale tra il numero dei nodi interrogati in ciascuna lettura
(indicati con la lettera R) e scrittura (indicati sempre con la lettera W ) deve
essere maggiore del numero dei nodi coinvolti nella replica dei dati (N ), ovve-
ro W+R>N. La suddetta implementazione nei database di tipo Key - Value
si concretizza nella capacit`a di poter operare anche con un numero di nodi
disponibili minore del totale (N ) purch´e si rispetti il quorum dell’operazione
eseguita. Ad esempio, in caso di cluster con un fattore di replica pari a 5 (N ),
14 CAPITOLO 1. I DATABASE NOSQL E LA PERSISTENZA POLIGLOTTA
con 3 nodi adibiti alla scrittura (W ), `e ammissibile il malfunzionamento di al
pi`u 2 di essi pur garantendo consistenza sulla scrittura.
• caratteristiche delle query
Tutti i database di tipo key-value offrono la possibilit`a di eseguire query at-
traverso il valore della chiave, avendo come svantaggio quello di non poter
ricavare un determinato record cercando in base al contenuto e, nella maggior
parte dei casi, di non poter nemmeno prelevare la lista delle chiavi presenti
al suo interno. Nonostante alcuni DBMS offrano la possibilit`a di effettuare
una ricerca in base al contenuto, risulta evidente che la scelta del tipo di dati
da inserire debba essere fatta prestando attenzione alla gestione della chiavi,
sia del metodo con cui vengono generate (mediante algoritmi, campi univoci
come gli identificativi, email e cos`ı via) che di quello con cui vengono salvate.
Per questo motivo, tali database vengono generalmente utilizzati per salvare
sessioni di navigazione di un utente, carte di credito e in generale per dati
sensibili o temporanei la cui persistenza pu`o essere programmata.
• struttura dei dati
In questo tipo di database non viene fatto nessun controllo di integrit`a rispet-
to al contenuto presente nell’attributo valore in ogni coppia <Chiave,Valore>.
Esso pu`o essere quindi un BLOB, una stringa, un JSON o qualsiasi altro forma-
to, che per buona pratica deve essere esplicitato dall’applicazione al momento
della scrittura al fine di ottimizzarne la memorizzazione.
• scalabilit`a
La maggior parte di questi database scala in modo orizzontale mediante la
tecnica della frammentazione (sharding) vista precedentemente. Con essa, il
valore di una chiave determiner`a il nodo da cui prelevare il dato, mettendo
in evidenza il problema che si avrebbe nel caso in cui il nodo contenente una
determinata coppia non fosse pi`u disponibile. Esso `e comunque risolvibile, o
quanto meno minimizzabile, grazie ai risultati del Teorema CAP e al concetto
di quorum.
1.3.2 Database documentali
I database documentali nascono con lo scopo di inserire e prelevare documenti, che
possono essere di tipo JSON, XML o formati di questo genere il cui contenuto `e
auto descrittivo, rappresentato internamente con una struttura gerarchica ad albero
che pu`o includere valori scalari, liste o collezioni di dati in generale. I database che
appartengono a tale tipologia conservano anch’essi la propriet`a schemaless, e quindi
sono in grado di salvare al loro interno documenti strutturalmente diversi. A diffe-
renza dei DBMS relazionali inoltre, la rappresentazione degli attributi si comporta
in modo diverso in presenza di valori nulli: nei documenti non esistono attributi sco-
nosciuti e, nel caso non ne venisse trovato uno, si assume che esso non sia rilevante
ai fini del documento preso in esame. L’introduzione di un nuovo attributo inoltre
non deve rispettare alcun vincolo rispetto a quelli gi`a presenti negli altri documenti,
eccetto il fatto che il suo nome sia univoco. Facendo un paragone con quanto visto
in precedenza, possiamo dire quindi che i database documentali sono una forma di
1.3. CATEGORIE DI DATABASE NOSQL 15
database di tipo key-value per cui il contenuto `e esaminabile e non appartenente ad
un preciso schema.
Figura 1.5: Un esempio di database documentale in cui gli stessi documenti
possono appartenere a diverse collezioni.
Andiamo ora ad introdurre le caratteristiche principali di questi database come
fatto nella sezione precedente. Parleremo sempre di:
• consistenza
La consistenza `e garantita dal fatto che essi implementano l’architettura master-
slave. Grazie ad essa `e possibile indicare, durante le operazioni di scrittura,
il numero di slave su cui il nodo master dovr`a apportare le modifiche, con-
siderando l’operazione conclusa solo dopo l’aggiornamento dell’ultimo nodo
coinvolto nell’operazione. Il tutto pu`o essere rafforzato con una replica del
dato su un numero di nodi slave che soddisfi il quorum di scrittura. Questo
ha per`o come svantaggio il tempo di esecuzione delle operazioni di aggiorna-
mento. Esse vengono serializzate infatti su ciascun nodo coinvolto andando ad
incidere negativamente sulle performance nel caso di scritture frequenti di dati
che allo stesso tempo verranno letti da altri nodi. In ultima analisi, `e possibile
riscontrare problemi di disponibilit`a del dato sia nel contenuto che nei tempi
di attesa.
• transazioni
Nel mondo dei database documentali, le transazioni che coinvolgono un sin-
golo documento sono considerate atomiche e in generale non `e possibile coin-
volgerne pi`u di uno per volta. Le operazioni ammissibili sono le tradizionali
appartenenti all’acronimo CRUD (Create, Read, Update, Delete) per cui `e
possibile:
– Creare un documento il cui contenuto appartiene ad uno tra i tipi visti
in precedenza.
– Modificare un documento.
– Prelevare il contenuto di uno o pi`u documenti, dando luogo ad una micro-
transazione per ogni documento letto.
16 CAPITOLO 1. I DATABASE NOSQL E LA PERSISTENZA POLIGLOTTA
– Cancellare un documento.
• disponibilit`a
I database documentali di base cercano di aumentare la disponibilit`a del dato
replicandoli secondo l’architettura master-slave con l’utilizzo degli Insiemi di
replica (replica sets). Tali insiemi, introdotti dal DBMS documentale Mon-
goDB [5], prevedono che due o pi`u nodi partecipino alla replica dei dati in
modo asincrono, scegliendo tra loro il nodo master secondo diverse propriet`a
come la quantit`a di RAM, la priorit`a assegnata e cos`ı via. Tutte le richieste
saranno indirizate al nodo master replicando i dati aggiornati ai nodi slave con
una differenza: nel caso in cui il nodo principale venisse a mancare, il sistema
provveder`a ad eleggere un nuovo nodo master a cui gli altri faranno riferi-
mento. Nel caso in cui il nodo precedentemente assegnato a master tornasse
operativo, esso diventer`a un nodo slave allineandosi con i contenuti aggiornati
dal nuovo nodo principale.
Tale caratteristica di autogestione si riflette anche nel comportamento attuato
dall’applicazione. A connessione stabilita infatti, l’applicazione avr`a bisogno
di un solo nodo all’interno dell’insieme di replica, master o meno, per com-
piere le proprie operazioni, scoprendo i restanti automaticamente. Essa non
dovr`a neanche prendersi l’onere di gestire il fallimento della comunicazione con
il database o l’elezione di un nuovo nodo master. Risulta evidente pertanto
l’alta disponibilit`a dell’infrastruttura che risponde in modo solido a tutte le
necessit`a relative alla ridondanza del dato, alla consistenza in lettura e al-
le problematiche di tipo catastrofico (disaster recovery, manutenzione senza
tempi di inattivit`a, ecc..).
• caratteristiche delle query
I database documentali forniscono diverse caratteristiche nelle loro query. No-
nostante non appartengano alla categoria dei database relazionali, essi possono
far riferimento alle ciste materializzate, create e salvate su disco, su cui possono
eseguire funzioni di aggregazione. Inoltre, come detto all’inizio, tali database
possono effettuare ricerche nel contenuto dei documenti, senza doverli prima
prelevare completamente, come accade normalmente nei database key-value.
• scalabilit`a
Basandosi sul modello master - slave, tutte le considerazioni riguardanti la
scalabilit`a devono essere fatte in relazione ai due possibili scopi per cui si
utilizza questa architettura, ovvero:
– al fine di avere un’elevata disponibilit`a in lettura: aggiungendo pi`u nodi
di tipo slave in modo tale che le letture possano essere dirette ad essi.
All’aggiunta di un nuovo nodo, esso si sincronizzer`a con gli altri esistenti
e cominceranno ad essere disponibili per le letture senza nessun tempo di
inattivit`a dovuto all’operazione.
– Al fine di avere un’elevata disponibilit`a in scrittura: applicando il concet-
to di frammentazione visto in precedenza con la differenza che, in questo
tipo di database, il dato pu`o essere suddiviso in base al campo tra i vari
1.3. CATEGORIE DI DATABASE NOSQL 17
nodi disponibili ed il DBMS si prender`a carico del loro corretto bilancia-
mento. I diversi frammenti ottenuti dai nodi possono dar vita a singoli
data set appartenenti ad un unico cluster frammentato.
1.3.3 Database a grafo
Questa categoria di database, basata sulla teoria dei grafi, permette di rappresenta-
re le entit`a sotto forma di vertici che possono essere legati tra loro mediante archi.
Il vantaggio del loro utilizzo rispetto ai database relazionali risiede nella capacit`a
di scalare pi`u facilmente al crescere del dataset dal momento che essi non utiliz-
zano operazioni di join. Una query eseguita da questi DBMS infatti rappresenta
l’attraversamento di un grafo secondo diverse relazioni: ciascun nodo pu`o averne in
numero teoricamente illimitato e con diversa navigabilit`a. Il fatto di appartenere
alla categoria dei NoSQL inoltre rende questi database adatti a gestire i casi in cui
`e necessario modificare ed evolvere frequentemente il loro schema.
Figura 1.6: Un esempio di database a grafo.
Come fatto per le precedenti categorie, descriviamo le caratteristiche pi`u impor-
tanti di un database a grafo:
• consistenza
Dal momento che i database a grafo lavorano su istanze di entit`a connesse tra
loro, la loro distribuzione non `e supportata dalla maggior parte dei DBMS.
Nel caso di un unico nodo, le propriet`a ACID delle transazioni sono garantite,
evitando quelle situazioni in cui uno o entrambi i vertici di una relazione
vengano a mancare (dangling relationships). La cancellazione di un vertice `e
quindi possibile solo se non `e coinvolto in nessuna relazione.
• transazioni
Come descritto in precedenza, questi database rispettano le propriet`a ACID
delle transazioni. Prima della modifica di un vertice o dell’inserimento di una
relazione tra due esistenti `e necessario iniziare una transazione, ad eccezione
delle operazioni di lettura che non ne richiedono una creazione.
• disponibilit`a
Questo tipo di database utilizza tipicamente l’architettura master-slave al fine
di garantire un buon livello di disponibilit`a, con la differenza che anche i nodi
18 CAPITOLO 1. I DATABASE NOSQL E LA PERSISTENZA POLIGLOTTA
di tipo slave possono gestire le scritture. Nel caso in cui venissero coinvolti
in queste operazioni infatti, essi dovranno sincronizzare la scrittura con l’at-
tuale nodo master effettuando prima un commit delle modifiche verso di lui
e poi con se stessi. Esistono per`o casi di database a grafo con un modello
di memorizzazione dei nodi distribuito: in questi casi le considerazioni fatte
in precedenza non valgono pi`u, trattandosi di un database NoSQL a tutti gli
effetti.
• caratteristiche delle query
A causa della loro natura, questi database supportano un proprio linguaggio
con cui scrivere le query. Nei capitoli successivi della tesi verr`a mostrato
l’utilizzo del linguaggio Cypher, appartenente al database Neo4J, mettendo
in evidenza le diverse modalit`a e usi degli attraversamenti dei nodi al fine di
rilevare statistiche e comportamenti dei nodi.
• scalabilit`a
I database a grafo non supportano la tecnica della frammentazione dal momen-
to che non esiste il concetto di aggregato ma di relazione. A questo proposito
`e possibile definire tre diverse modalit`a con cui scalare un database a grafo:
1. aggiungendo pi`u RAM alla macchina che contiene il database, ricoprendo
tutti quei casi elementari in cui il dataset cresce con un tasso per il quale
si ritiene che non superer`a mai i limiti fisici attuali dell’elaboratore che
lo contiene.
2. aggiungendo pi`u nodi di tipo slave al fine di aumentare la scalabilit`a nelle
letture, facendo comunque confluire tutte le scritture al nodo master.
Questa tecnica `e ottima nel caso in cui il dataset sia di una dimensione
tale da non poter essere interamente salvata nella memoria RAM di una
macchina ma al tempo stesso abbastanza piccola da essere replicata su
pi`u macchine.
3. optando comunque per la frammentazione nel caso in cui la replica del
dataset renda l’applicazione inutilizzabile, suddividendo i dati secondo
un criterio che dipende dal loro dominio.
1.4 La persistenza poliglotta
Nel 2006 Neal Ford, CEO dell’azienda ThoughtWorks, ha coniato per la prima volta
il termine di persistenza poliglotta (polyglot persistence). Con esso, Ford voleva
esprimere l’idea tramite cui le applicazioni dovrebbero essere scritte un insieme di
linguaggi in modo tale da utilizzare, in base alla tipologia del problema da risolvere,
quello pi`u adatto allo scopo. Questo concetto col tempo `e stato introdotto anche al
mondo dei database, nel quale le applicazioni dovrebbero sfruttare diverse tipologie
di database al fine di poter far affidamento su molteplici tecnologie di storage capaci
di far fronte alle necessit`a presenti.
L’introduzione di questo termine ha portato negli anni a seguire un cambiamento
dal punto di vista dell’approccio alle applicazioni di tipo enterprise: la scelta classica
di un solo storage non `e pi`u l’unica ad essere valutata. Al contrario, si dovrebbero
valutare nuove soluzioni per cui, a fronte delle diverse esigenze funzionali del progetto
1.4. LA PERSISTENZA POLIGLOTTA 19
si prova a far corrispondere il tipo di database pi`u adatto, avvicinandosi ad una
metodologia sempre pi`u incline a quella dei Software As A Service (SAAS) che in
quegli anni ha visto un’ascesa marcata nel mondo informatico.
20 CAPITOLO 1. I DATABASE NOSQL E LA PERSISTENZA POLIGLOTTA
Capitolo 2
Tecnologie, strumenti e pattern
utilizzati
In questo capitolo verranno introdotte le tecnologie e gli strumenti utilizzati durante
lo sviluppo del progetto, descrivendo e motivando le loro scelte al fine di offrire una
panoramica il pi`u possibile completa riguardo all’infrastruttura dell’applicazione.
2.1 Tecnologie utilizzate
2.1.1 Framework .NET
.NET `e un tipo di framework per lo sviluppo di applicazioni software prodotto da
Microsoft, composto principalmente da due componenti:
• Common Language Runtime (CLR)
`E la macchina virtuale alla base del framework il cui compito principale `e quel-
lo di gestire il codice in esecuzione fornendo una serie di servizi appartenenti
al linguaggio utilizzato, tra cui la gestione della memoria, la gestione della
sicurezza dell’applicazione, il caricamento di librerie e la compilazione. Essa
`e caratterizzata da una fase iniziale in cui si ottiene un codice managed rac-
chiuso all’interno di un assembly, rappresentato da un file eseguibile (.exe) o
da una libreria (.dll), insieme a dei metadati contenenti informazioni sui tipi e
sull’applicazione stessa. Questo codice managed non `e altro che un linguaggio
intermedio (IL) che, nel momento in cui il CLR carica l’assembly, viene con-
vertito nel codice nativo della macchina grazie ad un compilatore Just In Time
presente al suo interno. Nonostante le varie operazioni, l’assembly contenente
la maggior parte del codice originale viene mantenuto rendendone pi`u facile
l’ispezione e la generazione dinamica del codice.
• libreria delle classi
`E una libreria di tipo object oriented compatibile con l’insieme dei linguaggi
della famiglia .NET. Essa permette di creare diverse tipologie di applicazioni,
che vanno dai servizi di Windows alle applicazioni web vere e proprie, con la
possibilit`a di farle comunicare tra loro anche all’interno di uno stesso progetto.
21
22 CAPITOLO 2. TECNOLOGIE, STRUMENTI E PATTERN UTILIZZATI
2.1.2 ASP.NET MVC
ASP.NET [4] `e un framework open source per lo sviluppo Web a lato server prodotto
da Microsoft come evoluzione del motore di scripting ASP (Active Server Pages) in
cui `e stata introdotta la possibilit`a di programmare in un qualsiasi linguaggio della
famiglia .NET grazie al supporto dato dal CLR visto in precedenza. Nel contesto
di sviluppo del progetto, `e stato scelto di utilizzare una sotto categoria chiamata
ASP.NET MVC con lo scopo di separare le diverse logiche dell’applicazione dalle
pagine di visualizzazione vere e proprie. Tale tecnologia infatti si basa sul pattern
architetturale Model View Controller (MVC), in cui le applicazioni vengono suddi-
vise in tre tipi di componenti le cui responsabilit`a all’interno di questo framework
differiscono in alcuni casi da quanto si `e abituati a vedere. Parliamo quindi di:
• Model: rappresentano i diversi modelli dell’applicazione gestendo tutte le
operazioni relative alla manipolazione dei loro dati.
• View: sono responsabili della visualizzazione delle interfacce utente. Tipica-
mente riflettono la struttura dei diversi modelli dell’applicazione e per questo
motivo sono legate ad essi dal punto di vista della comunicazione.
• Controller: gestiscono le richieste dell’utente ogniqualvolta essi desiderano
visualizzare una pagina. Tipicamente, un utente interagisce con una View
che al suo interno genera una richiesta ad uno specifico URL, richiamando
indirettamente un controller il cui compito `e quello di visualizzare la pagina
desiderata.
Un’ulteriore caratteristica introdotta in ASP.NET MVC `e il Routing. La mo-
tivazione `e data dal fatto che grazie ad esso non vi `e pi`u la necessit`a di associare
ad ogni URL un file fisico specifico, definendo cos`ı una regola di routing che andr`a
ad interrogare un determinato controller. Per esempio, nel caso in cui si decides-
se di registrare un nuovo cliente all’interno dell’applicazione, in ASP.NET classico
sarebbe stato necessario riferirsi ad una precisa pagina che rispondeva all’indiriz-
zo http:/sito/Customer/Register/Registration.aspx, mentre adesso baster`a indicare
il controller e l’azione che si vuole eseguire, ottenendo un URL della forma /Cu-
stomer/Register. La mappatura di queste regole deve essere fatta all’interno di un
file presente nei progetti ASP.NET MVC chiamato RouteConfig.cs in cui `e possi-
bile specificare quali controller e quali dei loro metodi sono incaricati a rispondere
rispetto ad una determinata chiamata HTTP.
Oltre al routing, concludiamo la descrizione generale di questo framework intro-
ducendo un ultimo elemento: Razor. Esso non `e altro che una sintassi utilizzata
per creare pagine web dinamiche mediante l’impiego dei linguaggi C e Visual Basic
.NET le cui porzioni di codice verranno eseguite a lato server. La pagine web che
vorranno implementare questa tecnologia avranno l’estensione .cshtml, inserendo
porzioni di codice precedute dal carattere ”@”.
2.2 Strumenti utilizzati
Prima di procedere alla descrizione dello sviluppo e delle funzionalit`a dell’applica-
zione, descriviamo tutti gli strumenti che ne hanno reso possibile la creazione.
2.2. STRUMENTI UTILIZZATI 23
2.2.1 Visual Studio
Per poter sviluppare un’applicazione con le tecnologie descritte nella precedente se-
zione, `e stato necessario l’utilizzo dell’IDE Visual Studio [15]. Questo prodotto, oltre
alle funzionalit`a di base necessarie per poter testare ed eseguire il codice prodotto,
offre al suo interno il NuGet Package Manager, un gestore di pacchetti fondamentale
per includere nel progetto le diverse librerie e moduli utilizzati nella comunicazione
con i diversi servizi esterni all’applicazione.
2.2.2 Microsoft Azure
Microsoft Azure [16] `e la piattaforma cloud sviluppata da Microsoft che offre una
variet`a di strumenti resi disponibili come servizi ai diversi utilizzatori. Nell’ambito
del progetto `e stato utilizzato come piattaforma su cui utilizzare i diversi DBMS
NoSQL secondo un’ottica di Software As A Service (SaaS). Tale scelta `e motivata
dalle seguenti caratteristiche:
• scalabilit`a interna dei servizi eseguiti: Azure offre come caratteristica quella di
gestire automaticamente la scalabilit`a verticale dei servizi offerti, senza la ne-
cessit`a di dover impiegare ulteriori risorse per rendere efficienti le infrastrutture
che li eseguono.
• Georeplica dei servizi in esecuzione: ogni servizio eseguito su Azure `e replicato
globalmente e in modo autonomo all’interno dei diversi datacenter, garantendo
un’elevata affidabilit`a rispetto ai guasti.
2.2.3 SQL Server
SQL Server [7], nella versione relativa all’anno 2012, `e un RDBMS sviluppato da
Microsoft e utilizzato per poter gestire la base di dati relazionale all’interno del
progetto. Esso `e stato utilizzato sotto forma di servizio all’interno della piattaforma
Azure.
2.2.4 SQL Server Management Studio
SQL Server Management Studio `e un’applicazione sviluppata da Microsoft per poter
interagire con il DBMS SQL Server, offrendo strumenti per l’analisi e la creazione
di query.
2.2.5 DBMS NoSQL utilizzati
Andremo ora ad indicare i DBMS utilizzati appartenenti alla categoria NoSQL. Per
comprendere il loro comportamento e le interazioni con l’applicazione, si rimanda al
capitolo successivo.
Si `e utilizzato:
• Redis Cache: DBMS di tipo key-value in esecuzione come servizio su Azure,
utilizzato per contenere il carrello degli acquisti dell’utente. [8]
24 CAPITOLO 2. TECNOLOGIE, STRUMENTI E PATTERN UTILIZZATI
• Azure Blob Storage: `e un servizio di tipo file system per il salvataggio di
BLOB, oggetti non strutturati di dimensioni generalmente non piccole. La
sua struttura interna `e basata su contenitori, raggruppamenti di un numero
di BLOB teoricamente infinito secondo una logica imposta dall’utente . Esso
`e utilizzato all’interno dell’applicazione per il salvataggio delle foto relative ai
prodotti venduti e per i PDF delle fatture.
• Neo4J: `e un DBMS a grafo distribuito, installato come servizio in locale alla
macchina in cui viene eseguita l’applicazione. Esso `e utilizzato per esegui-
re operazioni di previsione sui possibili prodotti a cui un utente pu`o essere
interessato in base a ci`o che ha recentemente acquistato o visualizzato. [9]
• ElasticSearch: `e un DBMS documentale distributo utilizzato per il salvataggio
di testi su cui vengono effettuate ricerche in base alla loro struttura. Anch’esso,
insieme al DBMS Neo4j, `e eseguito in locale alla macchina. [10]
2.2.6 Git
Git `e un software di controllo di versione utilizzato per tenere traccia dei cambia-
menti nel corso dello sviluppo dell’applicazione. Esso `e stato usato per organizzare
il codice sorgente secondo due branch (letteralmente ”rami”): nel primo, chiamato
monolitic, `e stata sviluppata e versionata l’applicazione che utilizzava un solo data-
base relazionale per tutte le tipologie di operazioni, mentre nel secondo, chiamato
polyglot, era presente il sorgente dell’applicazione che si interfacciava con le diverse
tipologie di database NoSQL precedentemente descritte. [14]
2.2.7 RedGate SQL Source Control
`E uno strumento per il versionamento degli RDBMS sviluppato da RedGate [12]
ed integrabile in SQL Server Management Studio. Il versionamento `e realizzato
sempre attraverso Git, aggiungendo funzionalit`a importanti nell’ambito dei database
relazionali tra cui:
• la possibilit`a di versionare specifiche colonne di una tabella lasciando fuori
quelle che contengono dati modificati di frequente.
• l’inserimento di dati nelle tabelle prelevandoli da file esterni, utilizzato per
attingere dati da file Excel in formato CSV.
• il mantenimento dei record presenti nelle diverse tabelle sotto forma di comandi
INSERT INTO, potendo gestirli e modificarli senza dover eseguire dei comandi
di ALTER TABLE.
2.2.8 Entity Framework
`E un framework open source utilizzato per interfacciare le entit`a di un database rela-
zionale a delle classi presenti all’interno di applicazioni basate sul framework .NET.
Esso permette due tipologie di approcci: nel primo, chiamato Code First, le entit`a
vengono scritte inizialmente da codice sotto forma di classi per poi essere riportate
2.3. PATTERN UTILIZZATI 25
su database relazionali mantenendo nomi, tipi e vincoli, mentre nel secondo, chia-
mato Database First, si parte da un modello relazionale gi`a presente su database da
cui si genera una serie di classi all’interno dell’applicazione che lo rispecchiano. Nel
contesto dell’applicazione `e stato utilizzato il secondo approccio. [13]
2.3 Pattern utilizzati
Descriviamo la terza e ultima sezione di questo capitolo inerente ai pattern utilizzati
nello sviluppo dell’applicazione, sia dal punto di vista architetturale che da quello
metodologico.
2.3.1 Model View View-Model (MVVM)
L’utilizzo di Entity Framework e la struttura delle applicazioni basate su ASP.NET
MVC introducono la necessit`a di dover isolare l’interfaccia grafica dal resto del-
l’applicazione dal momento che non si ha pi`u un controllo totale sul suo modello.
Per questa ragione, `e stato deciso di utilizzare il pattern Model View View-Model
(MVVM) che `e composto dai seguenti componenti:
• Model: `e uguale al Model del pattern MVC presentato in precedenza, che in
questo contesto si concretizza con le classi generate da Entity Framework.
• View: anch’esso composto dalle classi e dalle pagine relative alla visualizza-
zione delle interfacce utente.
• View-Model: si pone tra il Model e la View. Ogni View nel prelevare i dati
si rifar`a ora al View-Model, spostando in esso tutte le logiche di business,
interagendo con il Model solo per prelevare i dati iniziali non ancora lavorati.
Figura 2.1: Rappresentazione del pattern MVVM nell’ambito di un’applicazione
ASP.NET MVC.
2.3.2 Kanban
Il lavoro che ha portato allo sviluppo del progetto `e stato organizzato con un me-
todologia evolutiva chiamata Kanban ispirata alla filosofia della programmazione
snella (Lean Production). La caratteristica principale risiede nell’utilizzo di una ta-
bella chiamata Kanban Board, composta da quattro colonne che rappresentano le
26 CAPITOLO 2. TECNOLOGIE, STRUMENTI E PATTERN UTILIZZATI
diverse fasi di sviluppo (To Do, Doing, Testing, Done). Ciascuna di esse conterr`a
degli elementi chiamati kanban cards che rappresentano le varie azioni di sviluppo,
considerate complete solo quando si trovano nella colonna Done.
Tra le altre caratteristiche di questa metodologia, troviamo la voluta mancanza
di ruoli definiti all’interno del team associata al fatto che i cambiamenti possono
avvenire in ogni momento. Tutto questo da vita ad un’ottica di rilascio continuo
(Continous delivery) che conferisce la dinamicit`a di questa metodologia.
Capitolo 3
Il contesto applicativo
In questo capitolo verr`a mostrato lo sviluppo dell’applicazione introducendo la strut-
tura generale e gli scopi per cui `e stata creata, descrivendo successivamente le due
soluzioni sviluppate, ovvero quella monolitica, in cui viene utilizzato un solo tipo di
storage, e quella poliglotta, la quale estende la precedente con l’utilizzo di database
NoSQL.
3.1 Descrizione e scopi dell’applicazione
L’applicazione realizzata durante il lavoro di tesi `e la riproduzione di una piattaforma
di e-commerce di tipo B2B(Business to Business) sviluppata all’interno dell’azienda
in cui `e stato svolto il tirocinio. Essa viene erogata sotto forma di servizio senza la
necessit`a di installarla all’interno delle macchine dei clienti utilizzatori. Le opera-
zioni eseguite variano in base al tipo di soluzione presa in esame, ma nel complesso
`e comunque possibile:
• registrare un’azienda mediante l’inserimento di una serie di informazioni
anagrafiche, tra cui l’opzione di caratterizzarla come Reseller (rivenditore) o
come Buyer (acquirente) . Per semplicit`a `e stato scelto di non dare possibilit`a
ad un’azienda Reseller di poter acquistare prodotti e ad un’azienda Buyer di
poterne vendere.
• modificare i dati di un’azienda in caso di aggiornamento delle sue infor-
mazioni. Non sar`a possibile modificare la sua tipologia (buyer o reseller, vedi
sopra).
• inserire un prodotto da parte di un’azienda reseller, specificando sia le
informazioni di vendita che un’eventuale immagine rappresentativa.
• aggiornare le informazioni di un prodotto senza restrizioni sui campi
modificabili a differenza di quanto visto con le aziende.
• visualizzare il pannello di controllo di ciascun utente che, in base alla
sua tipologia, varier`a nelle operazioni disponibili offrendo in entrambi i casi
uno storico degli ordini precedenti con la possibilit`a di visualizzarne le fatture.
• ricercare uno o pi`u prodotti in base alla descrizione da parte di un’a-
zienda Buyer, visualizzando una lista contenente il risultato dell’operazone da
cui `e possibile aggiungere i prodotti desiderati al carrello.
27
28 CAPITOLO 3. IL CONTESTO APPLICATIVO
• salvare i prodotti da acquistare inserendoli all’interno di un carrello
virtuale in base alle quantit`a selezionate.
• visualizzare il carrello virtuale in modo tale da rimuovere i prodotti inde-
siderati o per finalizzare l’operazione di acquisto.
• completare l’acquisto in base agli elementi presenti nel carrello virtuale,
generando e salvando un file PDF che rappresenta la sua fattura.
• ricevere consigli sui prodotti futuri per mezzo di una mail in base a quanto
appena acquistato da parte di un utente.
3.2 Struttura dell’applicazione
Veniamo ora alla descrizione generale dell’applicazione indipendentemente dal tipo
di soluzione sviluppata. Essa si divide in una parte client, che si interfaccia diret-
tamente con l’utente, ed in una server in cui sono presenti i diversi database. Dal
momento che i database NoSQL sono schemaless e appartenenti ad una delle due
soluzioni, verr`a introdotto saolamente il database relazionale gestito dal DBMS SQL
Server presente in entrambe. Per descriverlo, partiamo dal suo schema ER:
Product
Uses
1..1
Refers
1..1
Owns
0..1
Contains
0..N
1..1
Buys
0..N
Currency
1..N
Category
0..N
ProductPhoto
1..1
SalesOrderDetail
1..1
Customer
1..N1..1
Lives
1..1
Creates
0..N
1..1
UnitMeasure
0..N
Province
0..N
ClientPolicy
0..N
SalesOrderHeader
1..1
Is
1..1
Has
0..N
Has
1..1
OrderStatus
0..N
3.2. STRUTTURA DELL’APPLICAZIONE 29
Questo schema rappresenta le seguenti entit`a con la loro descrizione:
• Customer: rappresenta l’azienda che vuole acquistare o vendere dei prodotti.
• CustomerPolicy: rappresenta la tipologia di azienda con cui `e possibile regi-
strarsi.
• Province: rappresenta la provincia in cui l’azienda risiede.
• Product: rappresenta il prodotto acquistato o venduto da un’azienda.
• UnitMeasure: rappresenta l’unit`a di misura utilizzata nella descrizione del
peso e della lunghezza di un prodotto.
• Currency: rappresenta la valuta utilizzata per rappresentare il prezzo di un
prodotto.
• Category: rappresenta la categoria a cui appartiene un prodotto.
• ProductPhoto: rappresenta la foto associata ad un prodotto.
• SalesOrderHeader: rappresenta le informazioni di intestazione di un ordine.
• SalesOrderDetail: rappresenta le informazioni dell’acquisto di un prodotto
all’interno di un ordine.
• OrderStatus: rappresenta lo stato di un ordine.
Dal lato client, l’applicazione `e stata sviluppata con un’architettura di tipo three-tier
che presenta diverse analogie con il pattern MVC. Essa infatti `e composta da tre
elementi:
• l’interfaccia utente realizzata mediante la creazione di pagine web.
• la logica di business realizzata dalle classi appartenenti alla categoria dei Con-
troller e dei View Model che manipoleranno i dati in entrata e in uscita
dall’applicazione.
• il data layer costituito dal DBMS su cui verranno salvati i dati.
Il funzionamento generale `e il seguente: l’utente, in base all’operazione che vuole
eseguire, selezioner`a una voce apposita di un menu presente nelle diverse pagine,
inviando una richiesta URL della forma /ControllerScelto/AzioneDesiderata. Essa
richiamer`a uno specifico metodo di un controller, incaricato a visualizzare la pagina
desiderata e consumando nella maggior parte dei casi un oggetto appartenente alla
categoria dei view model. Il compito di quest’ultimo oggetto `e quello di prelevare
dal database i dati necessari ad essere visualizzati. Tale ragionamento si applica
anche alla pressione dei tasti di conferma presenti nei vari form dal momento che
si tratta comunque del meccanismo di routing di ASP.NET MVC unito al pattern
Model View View-Model e all’architettura Three-Tier visti in precedenza.
Dal punto di vista architetturale, `e possibile categorizzare le classi in base al loro
ruolo. Possiamo quindi identificare:
30 CAPITOLO 3. IL CONTESTO APPLICATIVO
• il modello da cui si attingeranno i dati utilizzati nell’applicazione: `e
composto da una serie di classi scritte in C create mediante l’utilizzo di Entity
Framework. Come gi`a descritto nel capitolo precedente, le tabelle presenti nel
database relazionale sono mappate all’interno dell’applicazione con una rispet-
tiva classe il cui nome e campi sono generati in automatico. Prendendo come
esempio l’entit`a Customer relativa ad un’azienda, il framework ha generato
un file chiamato Customer.cs il cui contenuto `e il seguente:
1 public partial class Customer
2 {
3 public Customer ()
4 {
5 this. SalesOrderHeaders = new
HashSet <SalesOrderHeader >();
6 this.Products = new HashSet <Product >();
7 }
8
9 public int CustomerID { get; set; }
10 public string Name { get; set; }
11 public string Email { get; set; }
12 public string Psw { get; set; }
13 public string Address { get; set; }
14 public string PhoneNumber { get; set; }
15 public string IBAN { get; set; }
16 public string PartitaIVA { get; set; }
17 public byte PolicyID { get; set; }
18 public byte ProvinceID { get; set; }
19
20 // Entita ’ per cui si ha una relazione all ’interno del
database.
21
22 // In relazione uno a molti.
23 public virtual CustomerPolicy CustomerPolicies { get;
set; }
24 public virtual Province Provinces { get; set; }
25
26 // In relazione molti a uno.
27 public virtual ICollection <SalesOrderHeader >
SalesOrderHeaders { get; set; }
28 public virtual ICollection <Product > Products { get;
set; }
29 }
`E interessante notare alcune caratteristiche comuni a tutte le classi mappate
con questo meccanismo. Come prima cosa, esse utilizzano nella loro definizione
la parola chiave partial, la quale specifica che la definizione della classe pu`o
avvenire anche in altre parti all’interno del namespace, purch´e utilizzino a loro
volta questa parola chiave. In un tale scenario, in cui le classi possono essere
aggiornate dal framework, l’utilizzo della keyword partial permette di definire
in un file slegato tutti gli attributi ed i metodi che non dovranno essere coinvolti
nelle modifiche. Per questa ragione, la definizione delle classi relative alle
3.2. STRUTTURA DELL’APPLICAZIONE 31
entit`a Product, ProductPhoto e Customer sono state ampliate tramite classi
partial su file esterni. In merito alla seconda caratteristica dell’applicazione,
notiamo che all’interno della classe precedentemente riportata sono presenti
degli attributi riferiti a delle entit`a con cui `e stata definita una relazione.
Notiamo infatti che nel caso di relazioni uno a uno (1:1) o uno a molti (1:N)
in cui la classe si trova dalla parte dell’entit`a con cardinalit`a unario, l’entit`a
mappata sar`a un solo oggetto mentre nel caso contrario avremo una collezione
di oggetti di tipo ICollection<T>, tipizzata in base alla classe dell’entit`a
corrispondente.
• i controller adibiti alla visualizzazione delle pagine web: sono classi
scritte in C che, ereditando la classe Controller presente nel framework .NET,
sono in grado di rispondere alle richieste HTTP inviate ad un’applicazione
ASP.NET MVC. Tale caratteristica permette anche di richiamare queste classi
all’interno dei pattern di routing senza dover esplicitare completamente il nome
omettendo la parola Controller al suo interno.
Venendo alle classi presenti nella categoria, troviamo:
– CustomerController: gestisce le pagine relative alle operazioni di acces-
so, disconnessione, registrazione di un nuovo utente e alla sua modi-
fica. Esse sono accessibili mediante il pattern di routing della forma
/Customer/NomeMetodoDesignato.
– ProductController: si occupa della registrazione, modifica e cancellazio-
ne di un prodotto e della loro rappresentazione all’interno della pagina
contenente i risultati della ricerca. Il pattern di routing per accedervi `e
/Product/NomeMetodoDesignato.
– OrderController: si occupa di tutte le operazioni che riguardano i prodotti
scelti e il carrello virtuale come l’inserimento, la rimozione e la visualizza-
zione dei prodotti al suo interno, insieme alle operazioni di prelevamento
di una fattura relativa ad un ordine e alla finalizzazione dell’ordine stesso.
• le classi adibite all’interfacciamento con i differenti database: sono
classi create appositamente per poter gestire le connessioni e le operazioni con i
diversi DBMS. Esse, indipendentemente dal tipo di soluzione, sono le seguenti:
– IRelationalDatabaseManager: `e l’interfaccia implementata da tutte le
classi che vorranno interagire con l’RDBMS dell’applicazione. Esso `e
costituito da un solo metodo, GetDBManager, che ritorna un oggetto
di tipo DatabaseEntity creato durante l’importazione del database me-
diante l’utilizzo di Entity Framework. Al suo interno sono contenute sia
stored procedure importate sempre da Entity framework, utilizzandole
sotto forma di metodi, che le entit`a mappate visibili nel seguente estratto
di codice :
1
2 // DatabaseEntity .cs
3
4 public virtual DbSet <Category > Categories{get;set;}
32 CAPITOLO 3. IL CONTESTO APPLICATIVO
5 public virtual DbSet <ClientPolicy >
ClientPolicies {get;set;}
6 public virtual DbSet <Currency > Currencies{get;set;}
7 public virtual DbSet <Customer > Customers{get;set;}
8 public virtual DbSet <OrderStatus >
OrderStatus{get;set;}
9 public virtual DbSet <Province > Provinces{get;set;}
10 public virtual DbSet <SalesOrderHeader >
SalesOrderHeaders {get;set;}
11 public virtual DbSet <UnitMeasure >
UnitMeasures{get;set;}
12 public virtual DbSet <SalesOrderDetail >
SalesOrderDetails {get;set;}
13 public virtual DbSet <Product > Products{get;set;}
Quanto appena mostrato evidenzia come tale framework, partendo dalle
tabelle presenti in un database, crei una loro mappatura dando vita al
Model dell’applicazione. Al suo interno notiamo come gli oggetti siano
tutti di tipo DbSet<T>, tipizzati con le classi del modello, sfruttando
il fatto che in essa sono dichiarati una serie di metodi per le tipiche
operazioni di inserimento, modifica, lettura e rimozione di un record.
Anche in questo caso mostriamo un breve estratto della sua definizione
con i metodi utilizzati nello sviluppo:
1 // DbSet.cs
2
3 /* Inserisce o aggiorna nel database un record
identificando tabella e campi a partire
4 * dalla classe TEntity che verra ’ tipizzata al
momento della creazione dell ’oggetto
5 * DbSet <TEntity >
6 */
7 public virtual TEntity Add(TEntity entity);
8
9 /* Cerca un record all ’interno della tabella mappata
dalla classe che tipizza l’oggetto
10 * in base al valore della chiave primaria
11 */
12 public virtual TEntity Find(params object []
keyValues);
13
14 /* Rimuove dall database un record in base alla
chiave primaria , identificando tabella e chiave *
primaria dalla classe TEntity che verra ’
tipizzata al momento della creazione dell ’oggetto
15 * DbSet <TEntity >
16 */
17 public virtual TEntity Remove(TEntity entity);
La descrizione di questa interfaccia dovrebbe dare quindi un’idea di come
avviene la comunicazione con il database relazionale: non sar`a neces-
sario scrivere SQL dinamico da codice per eseguire query o richiamare
3.2. STRUTTURA DELL’APPLICAZIONE 33
stored procedure ma baster`a utilizzare i metodi forniti indicando sola-
mente i parametri, che possono essere oggetti appartenenti al modello
dell’applicazione o definiti dall’utente.
– RelationalDatabaseManager: `e la classe che implementa l’interfaccia IRe-
lationalDatabaseManager permettendo quindi la comunicazione tra l’ap-
plicazione e il database relazionale secondo le modalit`a descritte nel punto
precedente.
– RelationalDatabaseManager: `e la classe che implementa la comunicazione
con il database relazionale dell’applicazione e che implementa l’interfaccia
IRelationalDatabaseManager, con tutte le meccaniche dovute all’utilizzo
di Entity Framework viste precedentemente.
– INoSQLDatabaseManager: `e l’interfaccia implementata da tutte le classi
a seguire contenente al suo interno.
– DocumentalDatabaseManager: `e la classe che concretizza la comunicazio-
ne con il database documentale inserendo i diversi documenti e prelevan-
doli in merito al loro identificativo con cui sono stati salvati.
– GraphDatabaseManager: all’interno di questa classe verr`a gestita la co-
municazione con il database a grafo, inserendo un nodo che identifica
un prodotto o un’azienda al loro inserimento nel sistema e creando una
relazione che li coinvolge al momento di un acquisto.
– KeyValueDatabaseManager: `e la classe che gestisce la comunicazione con
il database di tipo key - value, implementando al suo interno le operazioni
di inserimento, modifica e rimozione del carrello associato ad un utente.
– StorageDatabaseManager: `e l’ultima classe per la comunicazione con i
database, riferendosi in questo caso ad un file system su cui salvare e
prelevare sia le foto dei prodotti che i PDF dei diversi ordini effettuati.
• le classi appartenenti alla categoria ViewModel: concretizzano le fun-
zionalit`a fornite dall’applicazione dal momento che, come spiegato nella sezio-
ne precedente, contengono tutte le logiche di business. Forniamo quindi una
descrizione generale delle classi appartenenti a questa categoria, entrando nel
dettaglio durante la descrizione delle singole operazioni:
– CustomerViewModel: gestisce tutte le operazioni inerenti ad un’azienda
come la registrazione, l’aggiornamento dei dati, il prelevamento di tutte
le fatture ad esso associate insieme all’accesso e alla disconnessione dal
sistema.
– ProductViewModel: gestisce tutte le operazioni che coinvolgono i prodotti
all’interno dell’applicazione, occupandosi dell’inserimento, della modifica
e della cancellazione.
– SearchViewModel: gestisce la ricerca dei prodotti e la loro visualizzazione
all’interno dell’applicazione.
– ShoppingItemViewModel: viene utilizzata dagli altri ViewModel per la
visualizzazione dei prodotti insieme alle informazioni ad essi legate, come
ad esempio l’azienda che li ha messi in vendita. Al suo interno infatti si
34 CAPITOLO 3. IL CONTESTO APPLICATIVO
possono trovare attributi utilizzati per scopi di visualizzazione e relazioni
di tipo HAS A con alcune classi appartenenti alla categoria Model.
– ShoppingItemListViewModel: `e una classe che contiene al suo interno
una lista di oggetti di tipo ShoppingItemViewModel utilizzata dagli altri
componenti dell’applicazione nel salvataggio delel informazioni relative ai
prodotti.
3.3 La soluzione monolitica
Ora che abbiamo introdotto la struttura dell’applicazione, andiamo a descrivere
ognuna delle due soluzioni sviluppate in base al loro comportamento rispetto alle
funzionalit`a eseguite.
3.3.1 Registrazione di una nuova azienda
`E possibile registrare una nuova azienda mediante il pattern di routing
/Customer/Registration. Esso richiamer`a il metodo Registration del controller Cu-
stomerController visualizzando la pagina Registration.cshtml cos`ı strutturata:
Figura 3.1: Pagina di registrazione di una nuova azienda.
3.3. LA SOLUZIONE MONOLITICA 35
I campi visualizzati nella pagina sono prelevati dalla classe CustomerViewModel
che a sua volt`a si rifar`a a quelli presenti nella classe Customer, con la differenza che
essi utilizzano un meccanismo di rappresentazione degli attributi appartenente alla
tecnologia ASP.NET MVC chiamato data annotation. Esso permette di utilizzare
determinati attributi, appartenenti al namespace System.ComponentModel.DataAn
notations, che al momento della compilazione genereranno del codice HTML all’in-
terno della rispettiva view rispettando il tipo di validazione assegnata. Per rendere
meglio l’idea, mostreremo un estratto della classe CustomerViewModel in cui ven-
gono utilizzati gli attributi di data annotation:
1 [Required]
2 [EmailAddress]
3 [StringLength(maximumLength: 50, ErrorMessage = "Email
length must be less than 50 characters")]
4 public string Email { get; set; }
5
6 [Required]
7 [Display(Name = "Password")]
8 [StringLength(minimumLength: 8, maximumLength: 50,
ErrorMessage = "Password length must be between 8 and 50
characters" )]
9 [DataType(DataType.Password)]
10 public string Psw { get; set; }
11
12 [Required]
13 [Display(Name = "Confirm Password")]
14 [DataType(DataType.Password)]
15 [Compare("Psw", ErrorMessage = "Passwords must match")]
16 [StringLength(minimumLength: 8, maximumLength: 50,
ErrorMessage = "Password length must be between 8 and 50
characters" )]
17 public string ConfirmPsw { get; set; }
In questa porzione di codice `e possibile notare diverse caratteristiche. Per cominciare
si pu`o vedere come i campi in questione siano tutti necessari al fine della registrazione
grazie alla presenza dell’attributo Required. In merito agli attributi Psw e ConfirmP-
sw che andranno invece a rappresentare i campi in cui inserire la password, notiamo
come entrambi sono preceduti dall’attributo DataType(DataType.Password), per in-
dicare che essi andranno a contenere un dato sensibile, e da Display(Name) per fare
in modo che la pagina in cui verranno visualizzati non utilizzi il nome del cam-
po ma uno definito ad hoc. Come ultima caratteristica, si pu`o notare come sia
possibile definire una lunghezza minima e massima del campo, grazie all’attributo
StringLength(minimumLength, maximumLength, ErrorMessage), sia il fatto che esso
dovr`a essere uguale al contenuto di un altro campo, se presente, mediante l’attributo
Compare(NomeCampoConCuiConfrontarsi). Il loro utilizzo, nella pagina Registra-
tion.cshtml, generer`a il rispettivo codice:
1 <div class="form -group">
2 <label class="col -md -2" for="Email">Email </label >
3 <div class="col -md -10">
36 CAPITOLO 3. IL CONTESTO APPLICATIVO
4 <!-- [EmailAddress] -->
5 <input class="form -control" id="Email" name="Email"
type="text" value="" />
6 <!-- Validazione in javascript che include la lunghezza
massima e la forma
7 corretta per essere un indirizzo email. -->
8 <span class="field -validation -valid text -danger"
id=" Email_validationMessage " ></span >
9 </div >
10 </div >
11
12 <div class="form -group">
13 <!-- [Display(Name = "Password")] -->
14 <label class="col -md -2" for="Psw">Password </label >
15 <div class="col -md -10">
16 <!-- [DataType(DataType.Password)] -->
17 <input class="form -control" id="Psw" name="Psw"
type="password" />
18 <!-- Validazione in javascript che include la lunghezza
minima e massima -->
19 <span class="field -validation -valid text -danger"
id=" Psw_validationMessage " ></span >
20 </div >
21 </div >
22
23 <div class="form -group">
24 <!-- [Display(Name = "Confirm Password")] -->
25 <label class="col -md -2" for="ConfirmPsw">Confirm
Password </label >
26 <div class="col -md -10">
27 <input class="form -control" id="ConfirmPsw"
name="ConfirmPsw" type="password" />
28 <!-- Validazione in javascript che include la lunghezza
minima e massima insieme al test di ugaglianza
rispetto al campo Psw -->
29 <span class="field -validation -valid text -danger"
id=" ConfirmPsw_validationMessage " ></span >
30 </div >
31 </div >
L’utilizzo di questo meccanismo ha come vantaggio quello di poter fornire gi`a a
lato client il corretto dimensionamento dei campi rispetto agli attributi presenti nelle
tabelle su database relazionale, sollevando l’RDBMS dalle operazioni di controllo.
Ritornando alla descrizione dei ruoli delle classi coinvolte, notiamo come la clas-
se CustomerViewModel sia utilizzata per comunicare con la classe Provinces, per
poter visualizzare le province, e ClientPolicies, per poter visualizzare le tipologie
di azienda con cui `e possibile registrarsi. A seguire, mediante la pressione del ta-
sto Registrati, l’applicazione richiamer`a il metodo CheckRegistration, appartenente
sempre al controller CustomerController, passandogli come attributo l’oggetto di ti-
po CustomerViewModel contenente gli attributi valorizzati nei campi presenti nella
pagina. Al suo interno, verr`a successivamente richiamato il metodo InsertCusto-
3.3. LA SOLUZIONE MONOLITICA 37
mer, che istanzier`a un nuovo oggetto di tipo Customer, per rappresentare un record
del modello di cui fa parte, e un oggetto di tipo DatabaseEntity generato da Enti-
ty Framework con cui interfacciarsi al database relazionale. Ottenuto quest’ultimo
oggetto, l’inserimento avverr`a utilizzando il metodo Add() della classe Customer
passando come attributo un oggetto di tipo customer Customer. Esso inserir`a un
nuovo record all’interno dell’omonima tabella occupandosi della mappatura degli
attributi con i valori inseriti.
La funzione appena descritta `e la seguente:
1
2 public bool InsertCustomer ()
3 {
4 /* Istanziazione l’oggetto c di classe Customer dandogli
come parametro il CustomerViewModel chiamante dal
momento che esso , secondo il pattern MVVM , contiene i
suoi stessi parametri.
5 */
6 c = new Customer(this);
7
8 try
9 {
10 /*Il metodo getDBManager () ritorna un oggetto di tipo
DatabaseEntity relativo al database relazionale per
inserire l’oggetto di tipo Customer contenente i valori
di una nuova riga.
11 */
12 dbManager.GetDBManager ().Customers.Add(c);
13 dbManager.GetDBManager ().SaveChanges ();
14 }catch(Exception e){
15 Console.WriteLine(e.StackTrace);
16 return false;
17 }
18
19 return true;
20 }
Ad operazione correttamente eseguita, la nuova azienda verr`a inserita all’interno del
database ritornando al chiamante CheckRegistration il suo esito: in caso positivo,
l’utente verr`a indirizzato al pannello di controllo dell’utente, mentre in caso contrario
l’utente verr`a indirizzato ad una pagina d’errore che lo informer`a dell’esito negativo
dell’operazione.
3.3.2 Modifica dei dati di un’azienda
La modifica dei dati di un’azienda gi`a presente nel sistema ha molti tratti in comune
con l’inserimento appena visto. La differenza sostanziale risiede nel fatto che al
momento della visualizzazione della pagina la classe CustomerViewModel si occuper`a
di prelevare i dati dell’azienda partendo dal suo codice identificativo salvato nella
sessione. Tale operazione `e implementata nel seguente frammento di codice:
1 public ActionResult EditCustomerAccount ()
38 CAPITOLO 3. IL CONTESTO APPLICATIVO
2 {
3 /* Viene istanziato un oggetto CustomerViewModel contenente
i dati dell ’utente che verra ’ passato alla view come
parametro. */
4 CustomerViewModel cvm = new CustomerViewModel ();
5 // Viene prelevato l’id dell ’utente dalla sessione
6 cvm.CustomerID = (int)Session["CustomerID"];
7 /* Viene chiamata la funzione GetCustomerByID che
prelevera ’ i parametri da visualizzare nella pagina di
modifica in base all ’ identificativo dell ’utente. */
8 cvm. GetCustomerById ((int)Session["CustomerID"]);
9
10 return View(cvm);
11 }
La funzione GetCustomerById far`a uso di una stored procedure chiamata con lo
stesso nome il cui result set conterr`a le informazioni da visualizzare nella pagina di
modifica. Poich`e si tratta di una sola operazione di SELECT, non verr`a mostrato il
codice SQL relativo.
A modifiche eseguite, cliccando sul tasto Aggiorna verr`a richiamato il metodo
UpdateCustomer, appartenente alla classe CustomerController, passandogli come
parametro l’oggetto di tipo CustomerViewModel che conterr`a al suo interno i valo-
ri dell’utente modificati. Questo metodo utilizzer`a una stored procedure chiamata
UpdateCustomerById la cui natura `e duale rispetto a quella vista nell’operazione
precedente: se la prima restituiva un result set con certi dati relativi all’azienda,
essa utilizzer`a tali attributi come parametri al cui interno saranno presenti i valori
dell’utente aggiornati. Anche in questo caso, dal momento che la stored procedure
`e composta da una serie di operazioni SET su un record identificato dall’attributo
CustomerID, non verr`a riportato il codice.
3.3.3 Visualizzazione del pannello di controllo di un utente
Dopo aver effettuato l’accesso al sistema o dopo aver registrato un utente, l’applica-
zione visualizzer`a il pannello di controllo in cui sono possibili diverse operazioni in
base alla tipologia di utente definita dall’attributo Policy. Se l’utente infatti `e stato
registrato come Seller, esso potr`a:
• inserire un prodotto.
• modificare un prodotto.
• visualizzare lo storico degli ordini con la possibilit`a di prelevare il docu-
mento PDF contenente la relativa bolla.
• disconnettersi dal sistema.
Se l’utente invece `e stato invece registrato come Seller, oltre alla visualizzazione
dello storico degli ordini sar`a possibile:
• ricercare un prodotto in base alla sua descrizione.
• visualizzare i dettagli di un prodotto.
3.3. LA SOLUZIONE MONOLITICA 39
• visualizzare il carrello con i prodotti.
• completare l’acquisto dei prodotti presenti nel carrello.
Definite le operazioni possibili da ciascun utente, vediamo la pagina Dashboard.cshtml
incaricata a visualizzare il pannello di controllo:
3.3.4 Inserimento di un prodotto
La pagina di inserimento di un prodotto `e accessibile mediante il pattern di rou-
ting /Product/AddProduct, facendo riferimento al controller ProductController. Al
suo interno `e presente il metodo AddProduct la cui logica `e molto simile a quella
dell’inserimento di un’azienda. Essa far`a riferimento infatti ad un oggetto di tipo
ProductViewModel il quale al suo interno ha gli stessi attributi della classe Product,
con l’aggiunta delle data annotations per gli scopi di inserimento e visualizzazio-
ne. Questo oggetto verr`a assegnato dal controller alla view incaricata a visualizzare
il prodotto, corrispondente al file AddProduct.cshtml che si presenta nel seguente
modo:
40 CAPITOLO 3. IL CONTESTO APPLICATIVO
Figura 3.2: Pagina di inserimento di un prodotto.
In questo caso il sistema di data annotation, oltre che per gli usi tradizionali
di visualizzazione e di controllo di integrit`a dei campi, viene usato anche per far s`ı
che i campi Peso e Lunghezza, se valorizzati, abbiano anche una rispettiva unit`a di
misura.
Alla pressione del tasto Inserisci Prodotto, il controller ProductController richia-
mer`a il metodo InsertProduct passandogli come parametro l’oggetto di tipo Custo-
merViewModel i cui campi sono stati appena valorizzati. Tale oggetto richiamer`a
a sua volta un suo metodo, chiamato sempre InsertProduct il cui comportamento `e
analogo al metodo InsertCustomer visto nella registrazione di una nuova azienda.
Al suo interno viene infatti instanziato un oggetto inerente al modello su cui lavora,
in questo caso di tipo Product, il cui costruttore `e stato ridefinito per poter ricevere
come parametro un oggetto di tipo ProductViewModel instanzianziando successiva-
mente un oggetto di tipo DatabaseEntity per poter inserire un nuovo record nella
tabella Product presente nel database relazionale. L’inserimento `e sempre garantito
mediante l’utilizzo del metodo Add che questa volta prender`a in input un oggetto
di tipo Product.
La descrizione appena mostrata fa riferimento al seguente codice:
1 public bool InsertProduct ()
2 {
3 /* Viene instanziato un oggetto di tipo Product i cui
attributi assumeranno il valore dei loro corrispondenti
3.3. LA SOLUZIONE MONOLITICA 41
presenti nella classe ProductViewModel */
4 Product product = new Product(this);
5 try
6 {
7 /* Viene inserito nella tabella Product un record i cui
campi sono mappati dall ’oggetto appena definito.*/
8 dbManager.GetDBManager ().Products.Add(product);
9 dbManager.GetDBManager ().SaveChanges ();
10 }catch(Exception e){
11 Debug.WriteLine(e.StackTrace);
12 return false;
13 }
14 return true;
15 }
Anche per l’inserimento di un prodotto, l’esito del metodo decider`a la pagina a
cui reindirizzer`a il controller ProductController: in caso di inserimento avvenuto
verr`a visualizzato il pannello di controllo principale dell’atrimenti, altrimenti verr`a
visualizzata una pagina contenente un messaggio di errore.
3.3.5 Aggiornamento delle informazioni di un prodotto
La pagina per aggiornare le informazioni corrispondenti ad un prodotto `e accessibile
mediante il pattern di routing /Product/EditProduct, gestito dal controller Product-
Controller. Questa funzionalit`a `e predisposta solamente per gli utenti Seller e il suo
funzionamento `e leggermente diverso dalla modifica di un’azienda. Dal momento in-
fatti che esse possono vendere pi`u prodotti, l’applicazione reindirizzer`a l’utente verso
la pagina EditProductList.cshtml che visualizzer`a la lista dei suoi prodotti venduti.
Premendo il tasto Modifica di uno degli elementi si verr`a reindirizzati alla pagina di
modifica vera e propria, chiamata EditProduct.cshtml, la cui struttura `e la stessa di
quella dell’inserimento di un prodotto se non per il fatto che i suoi campi saranno
gi`a valorizzati con i dati prelevati. A modifiche avvenute, l’applicazione richiamer`a
sempre il controller ProductController passando come parametro del suo metodo,
chiamato UpdateProduct, il chiamante di tipo ProductViewController. Al suo inter-
no, l’oggetto parametro richiamer`a il metodo UpdateProductById per aggiornare il
prodotto, mediante una stored procedure, in base al suo codice identificativo. A
funzione terminata, il controler reindirizzer`a l’utente alla pagina del suo pannello di
controllo in caso di esito positivo, altrimenti visualizzer`a ad una pagina contenente
un messaggio di errore.
3.3.6 Ricerca dei prodotti in base alla descrizione e aggiunta
al carrello.
La ricerca di un prodotto `e utilizzabile solamente da un’azienda Buyer in quanto
nel suo pannello di controllo `e presente un’apposita casella di ricerca. Alla pressio-
ne del tasto Cerca verr`a richiamato il metodo ProductList presente all’interno del
controller ProductController che ricever`a come parametro la stringa di ricerca. Al
suo interno verr`a istanziato un oggetto di tipo SearchViewModel con un costrutto-
re definito appositamente il cui parametro `e la stringa di ricerca da assegnare ad
42 CAPITOLO 3. IL CONTESTO APPLICATIVO
un attributo apposito presente al suo interno. L’oggetto appena instanziato verr`a
utilizzato richiamando il metodo SearchProductsAndCustomers dove, al suo inter-
no, un oggetto di tipo DatabaseEntity utilizzer`a la stored procedure SearchProducts
sotto forma di metodo, passandogli come parametro la chiave di ricerca costituita
da soli caratteri in minuscolo in cui sono stati eliminati gli eventuali spazi. Que-
sta procedura al suo completamento ritorner`a le informazioni relative alla tabella
dei prodotti (Products) e a tutte le tabelle ad essa associate che contengono infor-
mazioni utili alla loro visualizzazione (Customers, UnitMeasures, Currencies). Per
ogni record nel result set ottenuto verr`a istanziato un oggetto di tipo ShoppingItem
contenente tutti i campi prelevati: ciascuno di essi a sua volta verr`a aggiunto al-
l’oggetto di tipo List<ShoppingItem> chiamato ShoppingItems, presente nella classe
ShoppingItemManager.
Una volta completata la ricerca, il metodo ritorner`a il controllo al metodo Pro-
ductList, appartenente alla classe ProductController, che visualizzer`a la lista dei
prodotti ottenuti all’interno dell’oggetto di tipo SearchViewModel precedentemente
istanziato. Per completare l’operazione di ricerca, questo controller visualizzer`a la
pagina ProductList.cshtml incaricata a visualizzare il risultato, il cui il risultato `e il
seguente:
Figura 3.3: Risultato di una ricerca secondo la chiave ”vite”.
Come si pu`o notare, la pagina offre la possibilit`a di selezionare la quantit`a dei
prodotti in modo tale da aggiungerli al carrello, completando l’operazione mediante
la pressione del tasto Aggiungi prodotti al carrello.
3.3.7 Visualizzazione dei prodotti all’interno del carrello
Gli utenti Buyer hanno la possibilit`a di visualizzare i prodotti in fase di acquisto
presenti nel carrello virtuale. Tale funzionalit`a `e raggiungibile mediante il pattern
di routing /Order/ShoppingCartDetail, in cui il metodo ShoppingCartDetail, appar-
tenente al controller OrderController, instanzier`a al suo interno un oggetto di tipo
3.3. LA SOLUZIONE MONOLITICA 43
ShoppingItemManager a cui verr`a assegnata una lista di elementi di tipo Shoppin-
gItem prelevata dalla sessione. Questo oggetto sar`a poi utilizzato come parametro
alla View incaricata a rappresentare la pagina, completando la descrizione di questo
metodo che a livello di codice avr`a il seguente contenuto:
1 public ActionResult ShoppingCartDetail ()
2 {
3 ShoppingItemManager cartManager = new ShoppingItemManager ();
4 // Prelevo la lista dei prodotti aggiunti al carrello
precedentemente salvati in sessione.
5 cartManager = (List <ShoppingItem >) Session["Products"];
6 // La lista con i prodotti , se presenti , sara ’ il modello
su cui la view attingera ’ i dati.
7 return View(cartManager);
8 }
Analogamente all’operazione di ricerca, il meccanismo con cui verranno visualizzati i
prodotti presenti nel carrello utilizzer`a due view: la prima, chiamata ShoppingCart-
Detail.cshtml, sar`a la pagina visualizzata all’utente che per ogni prodotto presente
nel carrello far`a riferimento alla seconda pagina, ShoppingCartItem.cshmtl, in cui `e
presente la struttura delle diverse righe che andranno a rappresentare i dati della
tabella. A tal proposito mostriamo le due porzioni di codice coinvolte e la pagina
ottenuta:
1 <!-- ShoppingCartDetail -->
2
3 <div class="ser">
4 <div class="col -sm -8">
5 @foreach (var item in Model)
6 {
7 <table class="table">
8 @**@
9 @Html.EditorFor(m => item , " ShoppingCartItem ")
10 </table >
11 }
12 </div >
1 <!-- ShoppingCartItem -->
2
3 <tr >
4 <td colspan="2">@Html.DisplayFor(m => m.P.Nome) </td >
5 <td > @Html.DisplayFor(m => m.P.Prezzo) </td >
6 <td > @Html.DisplayFor(m => m. QuantitaSelezionata ) </td >
7 </tr >
44 CAPITOLO 3. IL CONTESTO APPLICATIVO
Figura 3.4: Un esempio di carrello contenente due prodotti.
Oltre alla visualizzazione, l’applicazione offre anche al possibilit`a di rimuovere i
prodotti mediante la pressione del tasto Rimuovi presente per ogni elemento. Ta-
le operazione `e implementata passando al controller OrderController l’oggetto di
tipo ShoppingItem rappresentante il singolo prodotto da eliminare. L’operazione
di rimozione eseguita dal metodo RemoveShoppingCartitem, implementato sempre
all’interno del controller in questione, ricercher`a tutti gli elementi il cui codice iden-
tificativo `e uguale a quello del prodotto passato come parametro per poi rimuoverli.
Fatto questo, l’applicazione sostituir`a alla variabile di sessione Products rappresen-
tante i prodotti nel carrello una nuova lista senza l’elemento appena rimosso. Il
codice relativo a questa operazione `e il seguente:
1
2 public ActionResult RemoveCartItem (ShoppingItem itemToRemove)
3 {
4 /* Prelevo la lista attuale dei prodotti nel carrello.*/
5 List <ShoppingItem > items = (List <ShoppingItem >)
Session["Products"];
6 /* Rimuovo i prodotti il cui identificativo coincide con
quello del prodotto da eliminare */
7 items.RemoveAll(item => item.P.ProductID ==
itemToRemove.P.ProductID);
8 /* Rimuovo la variabile di sessione Products */
9 Session.Remove("Products");
10 /* Associo alla variabile di sessione Products la lista
aggiornata */
11 Session["Products"] = items;
12
13 /* Visualizzo nuovamente la pagina relativa al carrello dei
prodotti */
14 return RedirectToAction (" ShoppingCartDetail ", "Order");
15 }
Per prelevare tutti i prodotti con un determinato codice identificativo, si `e uti-
lizzato un componente del framework .NET chiamato LINQ(Language Integrated
Query). Esso estende il linguaggio C aggiungendo la maggior parte degli operatori
3.3. LA SOLUZIONE MONOLITICA 45
SQL con la possibilit`a di essere utilizzati sia per operare su collezioni di oggetti che
su database. Nel caso del codice mostrato si `e utilizzata la prima possibilit`a d’uso,
eseguendo all’interno della lista items una query traducidibile come:
1 DELETE
2 FROM items
3 WHERE P.IDProdotto = itemToRemove.P.IDProdotto
3.3.8 Finalizzazione dell’acquisto
Partendo dalla visualizzazione del carrello del prodotto, l’utente potr`a cliccare sul
tasto Procedi all’acquisto che finalizzer`a appunto l’operazione gestita dal metodo
Checkout appartenente al controller OrderController. La struttura di questa opera-
zione `e composta da diverse fasi: innazitutto, l’applicazione dovr`a accertarsi che i
prodotti siano ancora disponibili, e per farlo richiamer`a la stored procedure Check-
ProductAvailabilityProcedure passandogli come input una User Defined Table for-
mata da due attributi che indicano i codici identificativi dei prodotti da acquistare
con la loro quantit`a. Tale procedura effettuer`a poi un’operazione di JOIN avendo
come condizione l’uguaglianza dei codici dei prodotti, verificando successivamente
che la loro quantit`a sia maggiore di quella richiesta dall’utente. Nello specifico, la
procedura descritta `e la seguente:
1
2 -- Creazione della User Data Table (udt) che conterra ’ i
codici dei prodotti forniti in input con la loro
quantita ’.
3 CREATE type dbo.Product AS TABLE
4 (
5 ProductID INT ,
6 Quantity INT
7 )
8 GO
9
10 -- Creazione della procedura ha come parametro di input la
UDT appena descritta e come
11 -- parametro di output l’esito dell ’operazione
12 CREATE PROCEDURE dbo. proc_CheckProductAvailability
13 @Products AS dbo.Product READONLY ,
14 @ProductsAreAvailable BIT = 0 OUT
15 AS
16 BEGIN
17
18 -- Se il numero di righe della UDT e’
19 -- uguale a quelle della tabella su cui e’ stata fatta
l’operazione di join , allora
20 -- verra ’ assegnato 1 al parametro di output , altrimenti 0
poiche ’ alcuni dei prodotti acquistati
21 -- non sono disponibili.
22
23 -- COUNT (1) ha lo stesso valore semantico di COUNT (*).
46 CAPITOLO 3. IL CONTESTO APPLICATIVO
24 SELECT @ProductsAreAvailable = CASE WHEN COUNT (1) =
COUNT(p.ProductID) THEN 1
25 ELSE 0 END
26 FROM @Products p
27 JOIN dbo.Product p1
28 ON p.ProductID = p1.ProductID
29 WHERE p1.Quantity < p.Quantity;
30
31 END
32
33 GO
All’interno della procedura appena descritta si pu`o notare, oltre all’utilizzo della
UDT, la presenza di un parametro di output chiamato ProductsAreAvailable, con-
traddistinto dal fatto che sia seguito dalla parola chiave OUT. Per quanto riguarda la
comunicazione tra la procedura e l’applicazione, Entity Framework offre la possibi-
lit`a di creare delle classi che rappresentano le stored procedure in locale precedendole
con una data annotation chiamata StoredProcedure. Vediamo a tal proposito le classi
create per eseguire la procedura esaminata precedentemente:
1
2 /* Definizione della classe rappresentante la stored
procedure */
3 [ StoredProcedure (" proc_CheckProductAvailability ")]
4 public class CheckProductAvailabilityProcedure
5 {
6 /*
7 Dichiarazione dei parametri della procedura in cui ,
mediante data annotation , viene specificato
8 il tipo e il nome che deve essere identico a quanto
definito nel database.
9 */
10 [ StoredProcedureParameter (SqlDbType.Udt , ParameterName =
"Products")]
11 public List <UdtProduct > Products { get; set; }
12
13 [ StoredProcedureParameter (SqlDbType.Bit , Direction =
ParameterDirection .Output)]
14 public bool ProductsAreAvailable { get; set; }
15 }
16
17 /*
18 Definizione di un oggetto rappresentante lo schema della UDT
19 */
20 [ UserDefinedTableType ("Products")]
21 public class UdtProduct
22 {
23 /*
24 Dichiarazione degli attributi della UDT con il rispettivo
numero di colonna.
25 */
26 [ UserDefinedTableTypeColumn (1)]
3.3. LA SOLUZIONE MONOLITICA 47
27 public int ProductID { get; set; }
28
29 [ UserDefinedTableTypeColumn (2)]
30 public int Quantity { get; set; }
31 }
Queste classi verranno successivamente utilizzate all’interno del metodo Checkout
per richiamare la stored procedure in questione passandogli come parametro la UDT
mappata nel seguente modo:
1
2 /* Partendo gia ’ dalla lista degli elementi del carrello
presente
3 all ’interno di listaProdottiPrelevati , viene istanziato un
nuovo oggetto
4 assegnando all ’attributo rappresentante la UDT la lista dei
prodotti. */
5
6 var proc = new CheckProductAvaiabilityProcedure ()
7 {
8 Prodotti = retrievedProductList
9 };
10
11 /* Utilizzo di Entity Framework per eseguire la stored
procedure prelevando
12 tutte le sue informazioni dall ’oggetto proc appena
istanziato */
13 dbManager.GetDBManager ().Database. ExecuteStoredProcedure (proc);
14
15 /* Prelevo il valore del parametro di output presente
all ’interno della stored
16 procedure facendo sempre riferimento all ’oggetto che la
rappresenta da codice */
17 bool areProductsAvailable = proc. ProductsAreAvailable ;
In caso di disponibilit`a dei prodotti, l’operazione passer`a alla seconda fase in cui
verr`a effettuato l’acquisto vero e proprio, riducendo la quantit`a dei prodotti selezio-
nati dal database. Questa operazione `e effettuata sulla linea di quella precedente
utilizzando una stored procedure che, ricevendo come parametro una UDT, eseguir`a
un’operazione di join con i prodotti presenti su database in base al codice del pro-
dotto, riducendone la loro quantit`a. Per tale motivo, mostreremo solo la stored
procedure adibita a finalizzare l’acquisto, chiamata procCreateOrder:
1 ALTER PROCEDURE proc_CreateOrder
2 @OrderData AS dbo.OrderData READONLY ,
3 @Success BIT = 0 OUT ,
4 @Products AS dbo.Products READONLY ,
5 @OrderID INT = 0 OUT
6 AS
7 BEGIN
8 DECLARE @OrderTemp TABLE (ID INT)
9 DECLARE @TotalAmount DECIMAL (8,2)
48 CAPITOLO 3. IL CONTESTO APPLICATIVO
10 -- Creazione dell ’ordine generale in cui verranno inserite
le generalita ’ di spedizione
11 INSERT INTO dbo. SalesOrderHeader (BuyerID , OrderDate ,
DeliveryDate , Status , TotalAmount)
12 OUTPUT inserted.OrderID INTO @OrderTemp
13 SELECT BuyerID , GETDATE (), GETDATE (), 1, SubAmount
14 FROM @OrderData
15
16 SET @Success = 1;
17 SELECT @OrderID = ID FROM @OrderTemp;
18
19 -- Creazione del dettaglio dell ’ordine in cui verranno
inseriti i prodotti , con le loro quantita ’ e prezzi ,
20 -- relativi all ’ordine vero e proprio.
21 INSERT INTO dbo. SalesOrderDetail (OrderID , Quantity ,
Quantity , Price)
22 SELECT t.ID , p.ProductID , p.Quantity , p.Price
23 FROM @Products AS p, @OrderTemp t
24
25 -- Aggiornamento delle quantita ’ dei prodotti in base a
quelli acquistati.
26 UPDATE dbo.Product
27 SET Quantita = Quantity - q.Quantity
28 FROM (SELECT Quantity FROM [@Products ]) AS q
29 WHERE ProductID = (SELECT ProductID FROM @Products)
30 END
In caso di esito positivo della procedura si passer`a alla terza e ultima fase del
processo di acquisto in cui viene generato il PDF che sar`a una sorta di fac-simile
di una fattura in cui saranno presenti tutte le informazioni relative ai prodotti ac-
quistati e alla compravendita in se. La sua creazione `e gestita da un componente
View Model chiamato PdfViewModel, composto dal solo metodo createOrderSeal.
Esso, prendendo come parametri di input la lista dei prodotti nel carrello e le infor-
mazioni ottenute dalla stored procedure precedente, utilizzer`a le classi appartenenti
alla libreria iTextSharp[6] per creare il PDF che a fine operazione verr`a salvato nel-
la tabella SealOrderHeader attraverso un’operazione di UPDATE racchiusa in una
stored procedure dedicata.
Conclusa l’operazione, l’applicazione canceller`a dalla sessione i prodotti acqui-
stati e reindirizzer`a l’utente alla pagina contenente il suo pannello di controllo.
3.3.9 Accesso al sistema
La funzionalit`a di accesso al sistema `e raggiungibile mediante il pattern di routing
/Customer/Login. Al suo interno, la pagina visualizzata `e la seguente:
3.3. LA SOLUZIONE MONOLITICA 49
Figura 3.5: Pagina di login dell’applicazione
Come si pu`o vedere, la pagina si compone di due soli campi utilizzati per inserire
rispettivamente l’indirizzo email e la sua password. Alla pressione del tasto Accedi,
l’applicazione richiamer`a il metodo CheckLoggingCustomer del controller Customer-
Controller, il quale a sua volta richiamer`a la stored procedure Login, passandogli
come parametri di input l’email e la password inserite. La procedura in questione
che verr`a eseguita su database `e la seguente:
1 CREATE PROCEDURE Login
2 @Email VARCHAR (50) ,
3 @Password VARCHAR (50) ,
4 @Success BIT = 0 OUTPUT ,
5 @SessionToken UNIQUEIDENTIFIER = 0 OUTPUT ,
6 @PolicyID TINYINT = 0 OUTPUT ,
7 @CustomerID INT = 0 OUTPUT
8
9 AS
10 BEGIN
11 -- Se email e password coincidono , viene impostata la
variabile Success ad 1
12 -- come avvenuta operazione.
13 SELECT @Success = 1, @CustomerID = IDCliente , @PolicyID =
PolicyID
14 FROM dbo.Customer
15 WHERE Email = @Email AND Psw = @Password
16
17 -- Se l’utente e’ presente , viene generato il token di
sessione ed assegnato al parametro
18 -- di output.
19
20 IF @Success = 1
21 UPDATE dbo.Customer
22 SET SessionToken = NEWID (),
23 @SessionToken = SessionToken
24 WHERE CustomerID = @CustomerID
25 ELSE
26
27 END
In caso di accesso riuscito, il metodo salver`a nella sessione dell’utente due varia-
bili chiamate CustomerID e SessionToken, indicanti rispettivamente l’identificativo
TesiEtta
TesiEtta
TesiEtta
TesiEtta
TesiEtta
TesiEtta
TesiEtta
TesiEtta
TesiEtta
TesiEtta
TesiEtta
TesiEtta
TesiEtta
TesiEtta
TesiEtta
TesiEtta
TesiEtta
TesiEtta
TesiEtta
TesiEtta
TesiEtta
TesiEtta
TesiEtta
TesiEtta
TesiEtta
TesiEtta
TesiEtta
TesiEtta

More Related Content

Similar to TesiEtta

Analisi e sviluppo di un sistema collaborativo simultaneo per la modifica di ...
Analisi e sviluppo di un sistema collaborativo simultaneo per la modifica di ...Analisi e sviluppo di un sistema collaborativo simultaneo per la modifica di ...
Analisi e sviluppo di un sistema collaborativo simultaneo per la modifica di ...Filippo Muscolino
 
Progettazione e sviluppo di un'applicazione web per la gestione di dati di at...
Progettazione e sviluppo di un'applicazione web per la gestione di dati di at...Progettazione e sviluppo di un'applicazione web per la gestione di dati di at...
Progettazione e sviluppo di un'applicazione web per la gestione di dati di at...daniel_zotti
 
Publish/Subscribe EDI with Content-Based Routing
Publish/Subscribe EDI with Content-Based RoutingPublish/Subscribe EDI with Content-Based Routing
Publish/Subscribe EDI with Content-Based RoutingNicola Mezzetti
 
Profilazione utente in ambienti virtualizzati
Profilazione utente in ambienti virtualizzatiProfilazione utente in ambienti virtualizzati
Profilazione utente in ambienti virtualizzatiPietro Corona
 
Progetto e sviluppo di un'applicazionemobile multipiattaforma per il supporto...
Progetto e sviluppo di un'applicazionemobile multipiattaforma per il supporto...Progetto e sviluppo di un'applicazionemobile multipiattaforma per il supporto...
Progetto e sviluppo di un'applicazionemobile multipiattaforma per il supporto...maik_o
 
Tesi Specialistica - L'ottimizzazione delle risorse della Grid di EGEE median...
Tesi Specialistica - L'ottimizzazione delle risorse della Grid di EGEE median...Tesi Specialistica - L'ottimizzazione delle risorse della Grid di EGEE median...
Tesi Specialistica - L'ottimizzazione delle risorse della Grid di EGEE median...Davide Ciambelli
 
Prototipazione di una piattaforma di controllo degli accessi fisici cross ven...
Prototipazione di una piattaforma di controllo degli accessi fisici cross ven...Prototipazione di una piattaforma di controllo degli accessi fisici cross ven...
Prototipazione di una piattaforma di controllo degli accessi fisici cross ven...MassimoPalmisano
 
Art Everywhere: progetto per workshop Google. Sviluppo di sistemi di pattern ...
Art Everywhere: progetto per workshop Google. Sviluppo di sistemi di pattern ...Art Everywhere: progetto per workshop Google. Sviluppo di sistemi di pattern ...
Art Everywhere: progetto per workshop Google. Sviluppo di sistemi di pattern ...Francesco Cucari
 
Implementazione in Java di plugin Maven per algoritmi di addestramento per re...
Implementazione in Java di plugin Maven per algoritmi di addestramento per re...Implementazione in Java di plugin Maven per algoritmi di addestramento per re...
Implementazione in Java di plugin Maven per algoritmi di addestramento per re...Francesco Komauli
 
Un sistema di persistenza per motori di workflow business-oriented BPMN
Un sistema di persistenza per motori di workflow business-oriented BPMNUn sistema di persistenza per motori di workflow business-oriented BPMN
Un sistema di persistenza per motori di workflow business-oriented BPMNAlessandro Segatto
 
Tesina di fine seminario sas ed sql
Tesina di fine seminario sas ed sqlTesina di fine seminario sas ed sql
Tesina di fine seminario sas ed sqlMarco D'Alessandro
 
Progetto SOD Davide Sito
Progetto SOD Davide SitoProgetto SOD Davide Sito
Progetto SOD Davide SitoDavide Sito
 
Studio e realizzazione di un sw per la gestione dei profili e delle versioni ...
Studio e realizzazione di un sw per la gestione dei profili e delle versioni ...Studio e realizzazione di un sw per la gestione dei profili e delle versioni ...
Studio e realizzazione di un sw per la gestione dei profili e delle versioni ...artemedea
 
Openfisca Managing Tool: a tool to manage fiscal sistems
Openfisca Managing Tool: a tool to manage fiscal sistemsOpenfisca Managing Tool: a tool to manage fiscal sistems
Openfisca Managing Tool: a tool to manage fiscal sistemsLorenzo Stacchio
 
Generazione automatica diagrammi di rete con template pptx
Generazione automatica diagrammi di rete con template pptxGenerazione automatica diagrammi di rete con template pptx
Generazione automatica diagrammi di rete con template pptxGiacomoZorzin
 
Sviluppo e realizzazione di un sistema per la manipolazione di superfici trid...
Sviluppo e realizzazione di un sistema per la manipolazione di superfici trid...Sviluppo e realizzazione di un sistema per la manipolazione di superfici trid...
Sviluppo e realizzazione di un sistema per la manipolazione di superfici trid...Raffaele Bernardi
 
Estrazione automatica di informazioni da documenti cartacei: progetto e reali...
Estrazione automatica di informazioni da documenti cartacei: progetto e reali...Estrazione automatica di informazioni da documenti cartacei: progetto e reali...
Estrazione automatica di informazioni da documenti cartacei: progetto e reali...Luca Bressan
 

Similar to TesiEtta (20)

Analisi e sviluppo di un sistema collaborativo simultaneo per la modifica di ...
Analisi e sviluppo di un sistema collaborativo simultaneo per la modifica di ...Analisi e sviluppo di un sistema collaborativo simultaneo per la modifica di ...
Analisi e sviluppo di un sistema collaborativo simultaneo per la modifica di ...
 
Progettazione e sviluppo di un'applicazione web per la gestione di dati di at...
Progettazione e sviluppo di un'applicazione web per la gestione di dati di at...Progettazione e sviluppo di un'applicazione web per la gestione di dati di at...
Progettazione e sviluppo di un'applicazione web per la gestione di dati di at...
 
Publish/Subscribe EDI with Content-Based Routing
Publish/Subscribe EDI with Content-Based RoutingPublish/Subscribe EDI with Content-Based Routing
Publish/Subscribe EDI with Content-Based Routing
 
Profilazione utente in ambienti virtualizzati
Profilazione utente in ambienti virtualizzatiProfilazione utente in ambienti virtualizzati
Profilazione utente in ambienti virtualizzati
 
Compas Project
Compas ProjectCompas Project
Compas Project
 
Progetto e sviluppo di un'applicazionemobile multipiattaforma per il supporto...
Progetto e sviluppo di un'applicazionemobile multipiattaforma per il supporto...Progetto e sviluppo di un'applicazionemobile multipiattaforma per il supporto...
Progetto e sviluppo di un'applicazionemobile multipiattaforma per il supporto...
 
Tesi Specialistica - L'ottimizzazione delle risorse della Grid di EGEE median...
Tesi Specialistica - L'ottimizzazione delle risorse della Grid di EGEE median...Tesi Specialistica - L'ottimizzazione delle risorse della Grid di EGEE median...
Tesi Specialistica - L'ottimizzazione delle risorse della Grid di EGEE median...
 
Prototipazione di una piattaforma di controllo degli accessi fisici cross ven...
Prototipazione di una piattaforma di controllo degli accessi fisici cross ven...Prototipazione di una piattaforma di controllo degli accessi fisici cross ven...
Prototipazione di una piattaforma di controllo degli accessi fisici cross ven...
 
Art Everywhere: progetto per workshop Google. Sviluppo di sistemi di pattern ...
Art Everywhere: progetto per workshop Google. Sviluppo di sistemi di pattern ...Art Everywhere: progetto per workshop Google. Sviluppo di sistemi di pattern ...
Art Everywhere: progetto per workshop Google. Sviluppo di sistemi di pattern ...
 
Tesi Tamiazzo09
Tesi Tamiazzo09Tesi Tamiazzo09
Tesi Tamiazzo09
 
Implementazione in Java di plugin Maven per algoritmi di addestramento per re...
Implementazione in Java di plugin Maven per algoritmi di addestramento per re...Implementazione in Java di plugin Maven per algoritmi di addestramento per re...
Implementazione in Java di plugin Maven per algoritmi di addestramento per re...
 
Un sistema di persistenza per motori di workflow business-oriented BPMN
Un sistema di persistenza per motori di workflow business-oriented BPMNUn sistema di persistenza per motori di workflow business-oriented BPMN
Un sistema di persistenza per motori di workflow business-oriented BPMN
 
Tesina di fine seminario sas ed sql
Tesina di fine seminario sas ed sqlTesina di fine seminario sas ed sql
Tesina di fine seminario sas ed sql
 
Dynamic Scheduling
Dynamic SchedulingDynamic Scheduling
Dynamic Scheduling
 
Progetto SOD Davide Sito
Progetto SOD Davide SitoProgetto SOD Davide Sito
Progetto SOD Davide Sito
 
Studio e realizzazione di un sw per la gestione dei profili e delle versioni ...
Studio e realizzazione di un sw per la gestione dei profili e delle versioni ...Studio e realizzazione di un sw per la gestione dei profili e delle versioni ...
Studio e realizzazione di un sw per la gestione dei profili e delle versioni ...
 
Openfisca Managing Tool: a tool to manage fiscal sistems
Openfisca Managing Tool: a tool to manage fiscal sistemsOpenfisca Managing Tool: a tool to manage fiscal sistems
Openfisca Managing Tool: a tool to manage fiscal sistems
 
Generazione automatica diagrammi di rete con template pptx
Generazione automatica diagrammi di rete con template pptxGenerazione automatica diagrammi di rete con template pptx
Generazione automatica diagrammi di rete con template pptx
 
Sviluppo e realizzazione di un sistema per la manipolazione di superfici trid...
Sviluppo e realizzazione di un sistema per la manipolazione di superfici trid...Sviluppo e realizzazione di un sistema per la manipolazione di superfici trid...
Sviluppo e realizzazione di un sistema per la manipolazione di superfici trid...
 
Estrazione automatica di informazioni da documenti cartacei: progetto e reali...
Estrazione automatica di informazioni da documenti cartacei: progetto e reali...Estrazione automatica di informazioni da documenti cartacei: progetto e reali...
Estrazione automatica di informazioni da documenti cartacei: progetto e reali...
 

TesiEtta

  • 1. Universit`a degli Studi di Parma Dipartimento di Matematica e Informatica La persistenza poliglotta: analisi di un’applicazione in un contesto aziendale Candidato: Gabriele Etta Relatore: Prof. Enea Zaffanella Correlatore: Alessandro Alpi Anno Accademico 2015 - 2016 22 Dicembre 2016
  • 2. 2 Ad Alessandro, Daniela, Giordano e Martina.
  • 3. Indice 1 I database NoSQL e la persistenza poliglotta 7 1.1 Caratteristiche strutturali dei database NoSQL . . . . . . . . . . . . 7 1.1.1 Flessibilit`a nella manipolazione dei diversi tipi di dato . . . . 7 1.1.2 Performance elevate . . . . . . . . . . . . . . . . . . . . . . . . 8 1.2 Caratteristiche architetturali dei database NoSQL . . . . . . . . . . . 8 1.2.1 Il teorema CAP (Consistency, Availability, Partition Tolerance) 10 1.3 Categorie di database NoSQL . . . . . . . . . . . . . . . . . . . . . . 12 1.3.1 Database di tipo Key - Value . . . . . . . . . . . . . . . . . . 12 1.3.2 Database documentali . . . . . . . . . . . . . . . . . . . . . . 14 1.3.3 Database a grafo . . . . . . . . . . . . . . . . . . . . . . . . . 17 1.4 La persistenza poliglotta . . . . . . . . . . . . . . . . . . . . . . . . . 18 2 Tecnologie, strumenti e pattern utilizzati 21 2.1 Tecnologie utilizzate . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 2.1.1 Framework .NET . . . . . . . . . . . . . . . . . . . . . . . . . 21 2.1.2 ASP.NET MVC . . . . . . . . . . . . . . . . . . . . . . . . . . 22 2.2 Strumenti utilizzati . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 2.2.1 Visual Studio . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 2.2.2 Microsoft Azure . . . . . . . . . . . . . . . . . . . . . . . . . . 23 2.2.3 SQL Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 2.2.4 SQL Server Management Studio . . . . . . . . . . . . . . . . . 23 2.2.5 DBMS NoSQL utilizzati . . . . . . . . . . . . . . . . . . . . . 23 2.2.6 Git . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 2.2.7 RedGate SQL Source Control . . . . . . . . . . . . . . . . . . 24 2.2.8 Entity Framework . . . . . . . . . . . . . . . . . . . . . . . . . 24 2.3 Pattern utilizzati . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 2.3.1 Model View View-Model (MVVM) . . . . . . . . . . . . . . . 25 2.3.2 Kanban . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 3 Il contesto applicativo 27 3.1 Descrizione e scopi dell’applicazione . . . . . . . . . . . . . . . . . . . 27 3.2 Struttura dell’applicazione . . . . . . . . . . . . . . . . . . . . . . . . 28 3.3 La soluzione monolitica . . . . . . . . . . . . . . . . . . . . . . . . . . 34 3.3.1 Registrazione di una nuova azienda . . . . . . . . . . . . . . . 34 3.3.2 Modifica dei dati di un’azienda . . . . . . . . . . . . . . . . . 37 3.3.3 Visualizzazione del pannello di controllo di un utente . . . . . 38 3.3.4 Inserimento di un prodotto . . . . . . . . . . . . . . . . . . . . 39 3.3.5 Aggiornamento delle informazioni di un prodotto . . . . . . . 41 3
  • 4. 4 INDICE 3.3.6 Ricerca dei prodotti in base alla descrizione e aggiunta al carrello. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 3.3.7 Visualizzazione dei prodotti all’interno del carrello . . . . . . . 42 3.3.8 Finalizzazione dell’acquisto . . . . . . . . . . . . . . . . . . . . 45 3.3.9 Accesso al sistema . . . . . . . . . . . . . . . . . . . . . . . . 48 3.3.10 Disconnessione dal sistema . . . . . . . . . . . . . . . . . . . . 50 3.4 La soluzione poliglotta . . . . . . . . . . . . . . . . . . . . . . . . . . 50 3.4.1 Architettura della soluzione . . . . . . . . . . . . . . . . . . . 50 3.4.2 Accesso al sistema . . . . . . . . . . . . . . . . . . . . . . . . 52 3.4.3 Inserimento e modifica dei dati di un’azienda . . . . . . . . . . 52 3.4.4 Inserimento e modifica delle informazioni relative ad un prodotto 52 3.4.5 Ricerca dei prodotti in base alla sua descrizione . . . . . . . . 53 3.4.6 Inserimento di prodotti all’interno del carrello . . . . . . . . . 53 3.4.7 Visualizzazione dei prodotti presenti nel carrello . . . . . . . . 53 3.4.8 Finalizzazione di un acquisto . . . . . . . . . . . . . . . . . . . 53 3.4.9 Analisi e consiglio sui prodotti potenzialmente interessanti all’utente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 4 Confronti e analisi 57 4.1 Ricerca di prodotti . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 4.2 Analisi predittiva per il consiglio di prodotti . . . . . . . . . . . . . . 66 5 Conclusioni 69 5.1 Conclusioni e sviluppi futuri . . . . . . . . . . . . . . . . . . . . . . . 69 Appendici 71 A Glossario 73
  • 5. Introduzione Nel seguente lavoro di tesi verr`a presentato un prototipo di una piattaforma di e-commerce, sviluppata all’interno dell’azienda in cui `e stato svolto il tirocinio for- mativo, che utilizza due architetture diverse per assicurare la persistenza dei dati al suo interno. Nella prima soluzione, indicata nelle pagine a seguire con il termi- ne monolitica, verr`a utilizzato un solo database relazionale per salvare ogni tipo di informazione necessaria, mentre nella seconda soluzione, indicata con il termine po- liglotta, verr`a estesa quella precedente facendo affidamento ai database appartenenti alla categoria NoSQL (Not Only SQL) e al concetto di persistenza poliglotta da cui prende il nome. Lo scopo della tesi sar`a quello di mostrare che, in caso di applica- zioni aziendali che utilizzano un’elevata mole di dati diversi tra loro, l’utilizzo di un database relazionale pu`o portare ad inefficienze dal punto di vista delle operazioni svolte al suo interno, preferendo soluzioni in cui la presenza di pi`u tipologie di da- tabase offre la possibilit`a di suddividere il dominio della base di dati assegnando a ciascuno di essi uno specifico sottodominio che coincider`a con quello per cui sono stati ottimizzati, incrementando le perfomance complessive. Le pagine che seguiranno sono state organizzate su quattro capitoli introducendo al lettore i fondamenti teorici del mondo dei database NoSQL in modo tale da poter parlare delle tecnologie e dello sviluppo vero e proprio delle due soluzioni senza ambiguit`a. Avremo quindi: • il primo capitolo dedicato alla descrizione dei database NoSQL, mostrando le tipologie pi`u utilizzate con le loro caratteristiche, e al concetto di persistenza poliglotta di cui sono attori. • il secondo capitolo sar`a dedicato alla descrizione delle tecnologie, dei pat- tern e degli strumenti di sviluppo utilizzati nella creazione dell’applicazione gettandone le basi dal punto di vista teorico. • il terzo capitolo racchiuder`a lo sviluppo vero e proprio dell’applicazione a partire dalla sua struttura generale, per poi passare a descrivere lo sviluppo delle funzionalit`a fornite nelle due soluzioni. • il quarto capitolo mostrer`a i confronti eseguiti tra le due soluzioni rispetto ad alcune funzionalit`a principali, mettendo in evidenza vantaggi e svantaggi in esse presenti. • nella conclusione verr`a riassunto il lavoro svolto con un verdetto sull’efficacia dei due approcci, introducendo gli sviluppi futuri dell’applicazione. 5
  • 7. Capitolo 1 I database NoSQL e la persistenza poliglotta In questo capitolo introdurremo la categoria dei database denominata NoSQL, de- scrivendone le caratteristiche principali e fornendo una loro tassonomia, introducen- do successivamente il concetto di persistenza poliglotta su cui verter`a il lavoro di tesi. 1.1 Caratteristiche strutturali dei database No- SQL NoSQL `e un termine utilizzato per descrivere quella categoria di database in cui i dati sono organizzati seguendo un modello diverso dai tradizionali database relazionali. Per comprenderne al meglio le differenze e le motivazioni all’uso verr`a fornita una descrizione delle sue caratteristiche principali. 1.1.1 Flessibilit`a nella manipolazione dei diversi tipi di dato La molteplicit`a dei tipi di dato, dovuta alle variazioni del mercato su cui operano le applicazioni e al repentino cambiamento della natura del software, `e ormai un argomento di importanza centrale nell’implementazione e nella gestione delle ap- plicazioni il cui approccio tradizionale si rivolge spesso ad un solo tipo di storage, generalmente costituito da database relazionali. I DBMS a cui fanno riferimento infatti non sono abbastanza flessibili per gestire una elevata mole di dati di tipo diverso tra loro e, per questa ragione, gran parte delle aziende hanno seriamente considerato di valutare soluzioni di storage differenti al fine di dare una risposta efficace. Questa “nuova” categoria di database permette di gestire le diversit`a intro- dotte senza dover imporre restrizioni sullo schema di rappresentazione del dato al punto da ottenere dalla comunit`a informatica l’etichetta di schema-less. Tale carat- terizzazione, tuttavia, `e corretta solo in parte, poich`e nel mondo NoSQL lo schema di un database `e definito intrinsecamente dall’applicazione. Spetter`a infatti ad essa il compito di codificare e decodificare il flusso di dati ricevuti dal DBMS al momento dell’invio o della lettura. Questa caratteristica mette altres`ı in evidenza il fatto gli che eventuali errori dovuti alla discordanza tra lo schema definito a livello di appli- cazione e i dati prelevati dal database siano una responsabilit`a dello sviluppatore. 7
  • 8. 8 CAPITOLO 1. I DATABASE NOSQL E LA PERSISTENZA POLIGLOTTA Al contrario, nel contesto dei DBMS relazionali (o RDBMS), la presenza di uno schema modellato a priori assicura ed impone una maggiore rigorosit`a sull’insieme di dati e delle strutture da gestire. 1.1.2 Performance elevate Il modello relazionale memorizza le informazioni organizzandole secondo il concetto di tupla che, in certi casi, risulta essere una struttura dati limitata, non potendo ad esempio inserirne una all’interno di un’altra al fine di ottenere annidamenti. I database NoSQL a tal proposito mostrano un approccio differente: essi partono dal- l’idea che i dati abbiano una struttura pi`u complessa di una semplice tupla e, per tale ragione, identificano il concetto di aggregato, ovvero una collezione di “oggetti” legati tra loro su cui vengono eseguite operazioni. Ognuno di essi `e visto dal moto- re dei database NoSQL come una singola unit`a, atomica, indipendentemente dalla loro struttura interna. Questa caratteristica, unita al fatto che gran parte di questi DBMS non supporta transazioni di tipo ACID, permette di avere performance po- tenzialmente elevate sia in lettura che in scrittura, senza togliere all’applicazione la possibilit`a di annidare pi`u sorgenti di dati secondo un proprio schema. 1.2 Caratteristiche architetturali dei database No- SQL In questa sezione forniremo un confronto tra il mondo relazionale e quello No- SQL, ponendo particolare attenzione alle caratteristiche architetturali di quest’ul- tima realt`a. Prima di cominciare `e tuttavia necessario introdurre il concetto di scalabilit`a a cui faranno riferimento le successive considerazioni. Esso, in ambito database, indica la caratteristica con cui vengono gestite le richieste di lettura e scrittura all’aumentare sia della dimensione della base di dati che del numero di operazioni stesse. Pi`u generalmente, si pu`o affermare che la scalabilit`a `e il fattore di crescita o diminuzione di un sistema al variare delle necessit`a e delle disponibilit`a. Essa pu`o essere di due tipi: verticale, per la quale cambiano le caratteristiche del sistema atto a contenere il database (in termini di risorse CPU, RAM, e cosi via), oppure orizzontale, che si ottiene aggiungendo ulteriori nodi all’infrastruttura, visti come istanze del DBMS gestore, macchine virtuali o server. Entrambi gli approcci hanno vantaggi e svantaggi sia in termini economici che di complessit`a. Tuttavia, la scalabilit`a orizzontale non risente dei limiti strutturali della prima, andando per`o ad incidere sulla consistenza del dato: a titolo di esempio, replicare un dato su pi`u nodi pu`o far s`ı che durante le operazioni di scrittura si possa incappare in letture di informazioni non ancora aggiornate. Questo rovescio della medaglia comporta la necessit`a di scegliere preventivamente la natura dei dati da utilizzare poich`e, in caso di inconsistenza, il danno causato sia il minore possibile (letture sporche, fantasma, non aggiornate). In generale, la scalabilit`a, sia essa orizzontale o verticale, pu`o essere implementata tramite: • partizionamento: di tipo orizzontale nel caso in cui si suddividano gli og- getti, che rimangono strutturalmente identici, all’interno dello stesso database in base alla qualit`a (valore) del dato. Il suo accesso `e definito da logiche di
  • 9. 1.2. CARATTERISTICHE ARCHITETTURALI DEI DATABASE NOSQL 9 business che canalizzano il flusso dei chiamanti verso la sorgente pi`u oppor- tuna. Nel caso di partizionamento verticale si opta invece per suddividere le propriet`a in pi`u oggetti: si pensi ad un entit`a da modellare molto grande per il quale `e possibile effettuare la suddivisione in pi`u oggetti diversi. In tal caso si opera identificando le diverse aree funzionali presenti al suo interno isolandole al fine di ottenere pi`u sottoinsiemi di granularit`a minore. • sharding (frammentazione): in questo caso la scalabilit`a orizzontale si realizza dividendo il contenuto dei diversi database tra i nodi atti a gestirli. Vengono quindi ”installate” pi`u istanze del DBMS potenzialmente su altret- tante macchine (economiche, anche virtuali) facendo in modo che esse possano condividere dati tra loro. Questa suddivisione `e resa possibile da una chiave detta di “segmentazione”. Il problema principale di questa soluzione sta nel fatto che uno di questi nodi pu`o essere momentaneamente non disponibile. Per evitare ci`o, assicurando al tempo stesso un maggiore livello di business con- tinuity, viene generalmente utilizzata la replica per la quale un dataset viene copiato su pi`u nodi. Questa tecnica pu`o essere realizzata mediante l’impiego di diverse architetture, anche se fra tutte `e possibile identificarne due principali: – master - slave: questa architettura di replica vede la presenza di un nodo principale, detto master, in relazione ai restanti nodi detti slave. Al suo interno, le modifiche effettuate su un nodo di tipo master vengono propagate a tutti gli altri nodi slave, migliorando la scalabilit`a di lettura dal momento che queste richieste possono essere smistate su pi`u fronti. Questo meccanismo ha come svantaggio quello di dare origine ad un unico punto di fallimento: in caso di malfunzionamento di un nodo, le letture continueranno ad essere servite correttamente ma gli aggiornamenti dei data set non saranno disponibili. Per tali ragioni, un’architettura di tipo aster - slave `e utile nei casi in cui i data set hanno un alto traffico in lettura ma non in scrittura. Figura 1.1: Rappresentazione dell’architettura master-slave.
  • 10. 10 CAPITOLO 1. I DATABASE NOSQL E LA PERSISTENZA POLIGLOTTA – peer to peer: questa architettura risolve il problema descritto al punto precedente. Al suo interno, tutti i nodi hanno la medesima importanza e sono in grado di gestire sia le richieste di lettura che di scrittura. In caso di fallimento di un nodo non viene intaccata la business continuity dell’infrastruttura, ed anzi, si ha la possibilit`a di aggiungere dei nuovi nodi senza dover incorrere a tempi di inattivit`a del sistema. Figura 1.2: Rappresentazione dell’architettura peer to peer. 1.2.1 Il teorema CAP (Consistency, Availability, Partition Tolerance) Ora che sono state introdotte le caratteristiche comuni a tutti i sistemi distribuiti di tipo NoSQL, definiamo un teorema che ne caratterizza la struttura conosciuto come Teorema CAP (CAP Theorem). Formulato da Eric Brewer nel 2000, esso afferma che `e possibile ottimizzare contemporaneamente solamente due caratteristiche tra consistenza (consistency), disponibilit`a (availability) e tolleranza al partizionamento (partition tolerance). Le prime due caratteristiche sono gi`a state precedentemente discusse, mentre l’ultima indica la capacit`a di un cluster nel sopravvivere ai vari malfunzionamenti che impediscono alle sue partizioni di comunicare tra loro.
  • 11. 1.2. CARATTERISTICHE ARCHITETTURALI DEI DATABASE NOSQL 11 Figura 1.3: Rappresentazione dei risultati del teorema CAP Il teorema dimostra che per i database distribituiti di tipo NoSQL possono esi- stere tre diversi scenari in base alla coppia di caratteristiche su cui si `e deciso di investire: • CP (Consistency - Partition tollerance): in sistemi di questo tipo i dati letti sono sempre aggiornati all’ultima scrittura e le partizioni di un cluster hanno rarissimi problemi di comunicazione. Per contro, le richieste in lettura e scrittura provenienti dall’esterno su un singolo nodo potrebbero non fornire una risposta o, nel caso lo facessero, impiegherebbero tempi non ragionevoli mettendo in pericolo la disponibilit`a dell’intera infrastruttura. • AP (Availability - Partition tollerance:) in sistemi di questo tipo la risposta alle richieste di lettura e scrittura `e sempre garantita insieme alla comunicazione interna tra le partizioni del cluster. Per contro, la mancanza di consistenza pu`o creare problemi di aggiornamento dei dati tra i diversi nodi di un cluster, dando luogo a fenomeni di letture sporche (dirty read) per cui i dati prelevati non appartengono al dataset pi`u aggiornato. • CA (Consistency - Availability): sono i classici DBMS relazionali in cui i database sono salvati in un’unica partizione. Nel caso di decidesse di incre- mentare le partizioni si ricadrebbe in un sistema di tipo CP a causa del fatto che la garanzia delle transizioni ACID andrebbe a compromettere la continua disponibilit`a del dato. Facendo un confronto tra questo teorema e le propriet`a ACID si pu`o notare una notevole differenza, a cominciare dal punto di vista semantico. La lettera ”C” e la lettera ”A” del teorema appena visto rappresentano concetti diversi da quelli presenti in ACID: in ambito NoSQL, la consistenza indica che un insieme di dati `e copiato e disponibile su tutti i nodi in cui `e replicato, a differenza dell’ambito relazionale in cui si fa riferimento allo stato di un database prima e dopo una transazione. Tale diversit`a `e presente anche nella lettera ”A” dei due acronimi: in ambito NoSQL si
  • 12. 12 CAPITOLO 1. I DATABASE NOSQL E LA PERSISTENZA POLIGLOTTA intende la disponibilit`a del dato, replicato su pi`u nodi, mentre in ambito relazionale si intende l’atomicit`a di una transazione. Tutte queste differenze hanno portato, nel corso degli anni, a definire un acro- nimo per i sistemi NoSQL distribuiti che `e complementare alle propriet`a ACID dei database relazionali. Esso prende il nome di BASE ed `e formato dai seguenti termini: • BAsically available (Disponibilit`a di base): indica che il sistema offre una disponibilit`a di base, secondo quanto definito nel teorema CAP. • Soft state (Stato mutabile:) indica che il dataset pu`o cambiare nel corso del tempo anche in assenza di scritture. • Eventual consistency (Consistenza futura): poich´e l’aggiornamento su tutti i nodi di un cluster non `e sempre garantito, questo termine indica che il sistema risulter`a consistente solo quando smetter`a di ricevere dati in input. Durante la sua esecuzione non verr`a per`o fatto alcun controllo sulla consistenza rispetto ad altre transazioni eseguite in contemporanea. 1.3 Categorie di database NoSQL In questa sezione verranno presentati i principali tipi di database NoSQL dispo- nibili, caratterizzandoli in merito alla gestione della consistenza, delle transazioni, alle caratteristiche delle query che utilizzano, alla scalabilit`a e alle strutture dati utilizzate. 1.3.1 Database di tipo Key - Value E’ la categoria di database NoSQL pi`u semplice dal punto di vista strutturale. Es- si non sono altro che una tabella hash formata da due colonne: una chiave, che contiene per ogni record inserito un valore univoco su cui vengono effettuate le ope- razioni di hashing, e un valore, generalmente rappresentato da un BLOB (Binary Large OBject) che contiene un insieme di dati al quale l’applicazione dovr`a dare un significato sempre secondo l’ottica schemaless caratteristica dei NoSQL. Figura 1.4: Un esempio di database di tipo key- value.
  • 13. 1.3. CATEGORIE DI DATABASE NOSQL 13 Oltre a questo, tali database offrono generalmente la possibilit`a di salvare dati per un determinato periodo di tempo predisponendoli a contenere informazioni la cui natura `e volatile o sensibile ai fini dell’applicazione in cui verranno utilizzati. Da un punto di vista pi`u pratico invece, abbiamo tre tipologie di operazioni esegui- bili: • get(chiave): preleva il valore associato alla chiave. • put(chiave, valore): inserisce o aggiorna il valore associato alla chiave for- nita. • delete(chiave): rimuove il valore associato alla chiave. La struttura e la tipologia di operazioni eseguibili permette di fare diverse con- siderazioni sulle caratteristiche elencate ad inizio sezione, parlando quindi di: • consistenza La consistenza `e applicabile solo alle operazioni su chiave singola ed `e garantita nelle implementazioni distribuite di questi sistemi. Dal momento che il dato viene replicato su pi`u nodi, esistono due modi principali per risolvere i conflitti durante un aggiornamento: dando precedenza all’operazione di scrittura pi`u recente o ritornando all’utente entrambi i risultati dell’operazione lasciando ad esso la decisione su quale mantenere. • transazioni Generalmente questi tipi di database danno la possibilit`a di implementare le transazioni in modo differente purch´e si basino sul concetto di quorum, facen- do s`ı che non ci siano garanzie sulla scrittura. Questo termine, tipico degli scenari NoSQL, indica che all’aumentare dei nodi coinvolti in una richiesta diminuisce anche la possibilit`a di avere inconsistenza tra loro. Esso definisce inoltre il numero di nodi necessari al fine di garantire una consistenza forte (strong consistency), basandosi sul fatto che in un contesto di dati replicati su pi`u nodi non `e necessario che le operazioni di scrittura vadano a buon fine sulla loro totalit`a ma solo sulla loro maggioranza. Questa propriet`a prende il nome di Quorum per la scrittura (write quorum) e indica che, in un’operazio- ne di scrittura, il numero di nodi che partecipano all’operazione di scrittura (indicati con W ) deve essere maggiore della met`a dei nodi su cui viene fatta la replica dei dati (N ), ovvero W>N/2. Analogamente, esiste anche il concetto di quorum di lettura (read quorum) che definisce il numero di nodi necessari per avere maggiore sicurezza di avere accesso ad una determinata porzione di dati aggiornati alla loro ultima versione. Essa non `e sempre definibile me- diante una disuguaglianza come sopra descritto, poich´e dipende dal numero di nodi che devono confermare l’avvenuta scrittura. Nonostante ci`o, `e possibile affermare che il totale tra il numero dei nodi interrogati in ciascuna lettura (indicati con la lettera R) e scrittura (indicati sempre con la lettera W ) deve essere maggiore del numero dei nodi coinvolti nella replica dei dati (N ), ovve- ro W+R>N. La suddetta implementazione nei database di tipo Key - Value si concretizza nella capacit`a di poter operare anche con un numero di nodi disponibili minore del totale (N ) purch´e si rispetti il quorum dell’operazione eseguita. Ad esempio, in caso di cluster con un fattore di replica pari a 5 (N ),
  • 14. 14 CAPITOLO 1. I DATABASE NOSQL E LA PERSISTENZA POLIGLOTTA con 3 nodi adibiti alla scrittura (W ), `e ammissibile il malfunzionamento di al pi`u 2 di essi pur garantendo consistenza sulla scrittura. • caratteristiche delle query Tutti i database di tipo key-value offrono la possibilit`a di eseguire query at- traverso il valore della chiave, avendo come svantaggio quello di non poter ricavare un determinato record cercando in base al contenuto e, nella maggior parte dei casi, di non poter nemmeno prelevare la lista delle chiavi presenti al suo interno. Nonostante alcuni DBMS offrano la possibilit`a di effettuare una ricerca in base al contenuto, risulta evidente che la scelta del tipo di dati da inserire debba essere fatta prestando attenzione alla gestione della chiavi, sia del metodo con cui vengono generate (mediante algoritmi, campi univoci come gli identificativi, email e cos`ı via) che di quello con cui vengono salvate. Per questo motivo, tali database vengono generalmente utilizzati per salvare sessioni di navigazione di un utente, carte di credito e in generale per dati sensibili o temporanei la cui persistenza pu`o essere programmata. • struttura dei dati In questo tipo di database non viene fatto nessun controllo di integrit`a rispet- to al contenuto presente nell’attributo valore in ogni coppia <Chiave,Valore>. Esso pu`o essere quindi un BLOB, una stringa, un JSON o qualsiasi altro forma- to, che per buona pratica deve essere esplicitato dall’applicazione al momento della scrittura al fine di ottimizzarne la memorizzazione. • scalabilit`a La maggior parte di questi database scala in modo orizzontale mediante la tecnica della frammentazione (sharding) vista precedentemente. Con essa, il valore di una chiave determiner`a il nodo da cui prelevare il dato, mettendo in evidenza il problema che si avrebbe nel caso in cui il nodo contenente una determinata coppia non fosse pi`u disponibile. Esso `e comunque risolvibile, o quanto meno minimizzabile, grazie ai risultati del Teorema CAP e al concetto di quorum. 1.3.2 Database documentali I database documentali nascono con lo scopo di inserire e prelevare documenti, che possono essere di tipo JSON, XML o formati di questo genere il cui contenuto `e auto descrittivo, rappresentato internamente con una struttura gerarchica ad albero che pu`o includere valori scalari, liste o collezioni di dati in generale. I database che appartengono a tale tipologia conservano anch’essi la propriet`a schemaless, e quindi sono in grado di salvare al loro interno documenti strutturalmente diversi. A diffe- renza dei DBMS relazionali inoltre, la rappresentazione degli attributi si comporta in modo diverso in presenza di valori nulli: nei documenti non esistono attributi sco- nosciuti e, nel caso non ne venisse trovato uno, si assume che esso non sia rilevante ai fini del documento preso in esame. L’introduzione di un nuovo attributo inoltre non deve rispettare alcun vincolo rispetto a quelli gi`a presenti negli altri documenti, eccetto il fatto che il suo nome sia univoco. Facendo un paragone con quanto visto in precedenza, possiamo dire quindi che i database documentali sono una forma di
  • 15. 1.3. CATEGORIE DI DATABASE NOSQL 15 database di tipo key-value per cui il contenuto `e esaminabile e non appartenente ad un preciso schema. Figura 1.5: Un esempio di database documentale in cui gli stessi documenti possono appartenere a diverse collezioni. Andiamo ora ad introdurre le caratteristiche principali di questi database come fatto nella sezione precedente. Parleremo sempre di: • consistenza La consistenza `e garantita dal fatto che essi implementano l’architettura master- slave. Grazie ad essa `e possibile indicare, durante le operazioni di scrittura, il numero di slave su cui il nodo master dovr`a apportare le modifiche, con- siderando l’operazione conclusa solo dopo l’aggiornamento dell’ultimo nodo coinvolto nell’operazione. Il tutto pu`o essere rafforzato con una replica del dato su un numero di nodi slave che soddisfi il quorum di scrittura. Questo ha per`o come svantaggio il tempo di esecuzione delle operazioni di aggiorna- mento. Esse vengono serializzate infatti su ciascun nodo coinvolto andando ad incidere negativamente sulle performance nel caso di scritture frequenti di dati che allo stesso tempo verranno letti da altri nodi. In ultima analisi, `e possibile riscontrare problemi di disponibilit`a del dato sia nel contenuto che nei tempi di attesa. • transazioni Nel mondo dei database documentali, le transazioni che coinvolgono un sin- golo documento sono considerate atomiche e in generale non `e possibile coin- volgerne pi`u di uno per volta. Le operazioni ammissibili sono le tradizionali appartenenti all’acronimo CRUD (Create, Read, Update, Delete) per cui `e possibile: – Creare un documento il cui contenuto appartiene ad uno tra i tipi visti in precedenza. – Modificare un documento. – Prelevare il contenuto di uno o pi`u documenti, dando luogo ad una micro- transazione per ogni documento letto.
  • 16. 16 CAPITOLO 1. I DATABASE NOSQL E LA PERSISTENZA POLIGLOTTA – Cancellare un documento. • disponibilit`a I database documentali di base cercano di aumentare la disponibilit`a del dato replicandoli secondo l’architettura master-slave con l’utilizzo degli Insiemi di replica (replica sets). Tali insiemi, introdotti dal DBMS documentale Mon- goDB [5], prevedono che due o pi`u nodi partecipino alla replica dei dati in modo asincrono, scegliendo tra loro il nodo master secondo diverse propriet`a come la quantit`a di RAM, la priorit`a assegnata e cos`ı via. Tutte le richieste saranno indirizate al nodo master replicando i dati aggiornati ai nodi slave con una differenza: nel caso in cui il nodo principale venisse a mancare, il sistema provveder`a ad eleggere un nuovo nodo master a cui gli altri faranno riferi- mento. Nel caso in cui il nodo precedentemente assegnato a master tornasse operativo, esso diventer`a un nodo slave allineandosi con i contenuti aggiornati dal nuovo nodo principale. Tale caratteristica di autogestione si riflette anche nel comportamento attuato dall’applicazione. A connessione stabilita infatti, l’applicazione avr`a bisogno di un solo nodo all’interno dell’insieme di replica, master o meno, per com- piere le proprie operazioni, scoprendo i restanti automaticamente. Essa non dovr`a neanche prendersi l’onere di gestire il fallimento della comunicazione con il database o l’elezione di un nuovo nodo master. Risulta evidente pertanto l’alta disponibilit`a dell’infrastruttura che risponde in modo solido a tutte le necessit`a relative alla ridondanza del dato, alla consistenza in lettura e al- le problematiche di tipo catastrofico (disaster recovery, manutenzione senza tempi di inattivit`a, ecc..). • caratteristiche delle query I database documentali forniscono diverse caratteristiche nelle loro query. No- nostante non appartengano alla categoria dei database relazionali, essi possono far riferimento alle ciste materializzate, create e salvate su disco, su cui possono eseguire funzioni di aggregazione. Inoltre, come detto all’inizio, tali database possono effettuare ricerche nel contenuto dei documenti, senza doverli prima prelevare completamente, come accade normalmente nei database key-value. • scalabilit`a Basandosi sul modello master - slave, tutte le considerazioni riguardanti la scalabilit`a devono essere fatte in relazione ai due possibili scopi per cui si utilizza questa architettura, ovvero: – al fine di avere un’elevata disponibilit`a in lettura: aggiungendo pi`u nodi di tipo slave in modo tale che le letture possano essere dirette ad essi. All’aggiunta di un nuovo nodo, esso si sincronizzer`a con gli altri esistenti e cominceranno ad essere disponibili per le letture senza nessun tempo di inattivit`a dovuto all’operazione. – Al fine di avere un’elevata disponibilit`a in scrittura: applicando il concet- to di frammentazione visto in precedenza con la differenza che, in questo tipo di database, il dato pu`o essere suddiviso in base al campo tra i vari
  • 17. 1.3. CATEGORIE DI DATABASE NOSQL 17 nodi disponibili ed il DBMS si prender`a carico del loro corretto bilancia- mento. I diversi frammenti ottenuti dai nodi possono dar vita a singoli data set appartenenti ad un unico cluster frammentato. 1.3.3 Database a grafo Questa categoria di database, basata sulla teoria dei grafi, permette di rappresenta- re le entit`a sotto forma di vertici che possono essere legati tra loro mediante archi. Il vantaggio del loro utilizzo rispetto ai database relazionali risiede nella capacit`a di scalare pi`u facilmente al crescere del dataset dal momento che essi non utiliz- zano operazioni di join. Una query eseguita da questi DBMS infatti rappresenta l’attraversamento di un grafo secondo diverse relazioni: ciascun nodo pu`o averne in numero teoricamente illimitato e con diversa navigabilit`a. Il fatto di appartenere alla categoria dei NoSQL inoltre rende questi database adatti a gestire i casi in cui `e necessario modificare ed evolvere frequentemente il loro schema. Figura 1.6: Un esempio di database a grafo. Come fatto per le precedenti categorie, descriviamo le caratteristiche pi`u impor- tanti di un database a grafo: • consistenza Dal momento che i database a grafo lavorano su istanze di entit`a connesse tra loro, la loro distribuzione non `e supportata dalla maggior parte dei DBMS. Nel caso di un unico nodo, le propriet`a ACID delle transazioni sono garantite, evitando quelle situazioni in cui uno o entrambi i vertici di una relazione vengano a mancare (dangling relationships). La cancellazione di un vertice `e quindi possibile solo se non `e coinvolto in nessuna relazione. • transazioni Come descritto in precedenza, questi database rispettano le propriet`a ACID delle transazioni. Prima della modifica di un vertice o dell’inserimento di una relazione tra due esistenti `e necessario iniziare una transazione, ad eccezione delle operazioni di lettura che non ne richiedono una creazione. • disponibilit`a Questo tipo di database utilizza tipicamente l’architettura master-slave al fine di garantire un buon livello di disponibilit`a, con la differenza che anche i nodi
  • 18. 18 CAPITOLO 1. I DATABASE NOSQL E LA PERSISTENZA POLIGLOTTA di tipo slave possono gestire le scritture. Nel caso in cui venissero coinvolti in queste operazioni infatti, essi dovranno sincronizzare la scrittura con l’at- tuale nodo master effettuando prima un commit delle modifiche verso di lui e poi con se stessi. Esistono per`o casi di database a grafo con un modello di memorizzazione dei nodi distribuito: in questi casi le considerazioni fatte in precedenza non valgono pi`u, trattandosi di un database NoSQL a tutti gli effetti. • caratteristiche delle query A causa della loro natura, questi database supportano un proprio linguaggio con cui scrivere le query. Nei capitoli successivi della tesi verr`a mostrato l’utilizzo del linguaggio Cypher, appartenente al database Neo4J, mettendo in evidenza le diverse modalit`a e usi degli attraversamenti dei nodi al fine di rilevare statistiche e comportamenti dei nodi. • scalabilit`a I database a grafo non supportano la tecnica della frammentazione dal momen- to che non esiste il concetto di aggregato ma di relazione. A questo proposito `e possibile definire tre diverse modalit`a con cui scalare un database a grafo: 1. aggiungendo pi`u RAM alla macchina che contiene il database, ricoprendo tutti quei casi elementari in cui il dataset cresce con un tasso per il quale si ritiene che non superer`a mai i limiti fisici attuali dell’elaboratore che lo contiene. 2. aggiungendo pi`u nodi di tipo slave al fine di aumentare la scalabilit`a nelle letture, facendo comunque confluire tutte le scritture al nodo master. Questa tecnica `e ottima nel caso in cui il dataset sia di una dimensione tale da non poter essere interamente salvata nella memoria RAM di una macchina ma al tempo stesso abbastanza piccola da essere replicata su pi`u macchine. 3. optando comunque per la frammentazione nel caso in cui la replica del dataset renda l’applicazione inutilizzabile, suddividendo i dati secondo un criterio che dipende dal loro dominio. 1.4 La persistenza poliglotta Nel 2006 Neal Ford, CEO dell’azienda ThoughtWorks, ha coniato per la prima volta il termine di persistenza poliglotta (polyglot persistence). Con esso, Ford voleva esprimere l’idea tramite cui le applicazioni dovrebbero essere scritte un insieme di linguaggi in modo tale da utilizzare, in base alla tipologia del problema da risolvere, quello pi`u adatto allo scopo. Questo concetto col tempo `e stato introdotto anche al mondo dei database, nel quale le applicazioni dovrebbero sfruttare diverse tipologie di database al fine di poter far affidamento su molteplici tecnologie di storage capaci di far fronte alle necessit`a presenti. L’introduzione di questo termine ha portato negli anni a seguire un cambiamento dal punto di vista dell’approccio alle applicazioni di tipo enterprise: la scelta classica di un solo storage non `e pi`u l’unica ad essere valutata. Al contrario, si dovrebbero valutare nuove soluzioni per cui, a fronte delle diverse esigenze funzionali del progetto
  • 19. 1.4. LA PERSISTENZA POLIGLOTTA 19 si prova a far corrispondere il tipo di database pi`u adatto, avvicinandosi ad una metodologia sempre pi`u incline a quella dei Software As A Service (SAAS) che in quegli anni ha visto un’ascesa marcata nel mondo informatico.
  • 20. 20 CAPITOLO 1. I DATABASE NOSQL E LA PERSISTENZA POLIGLOTTA
  • 21. Capitolo 2 Tecnologie, strumenti e pattern utilizzati In questo capitolo verranno introdotte le tecnologie e gli strumenti utilizzati durante lo sviluppo del progetto, descrivendo e motivando le loro scelte al fine di offrire una panoramica il pi`u possibile completa riguardo all’infrastruttura dell’applicazione. 2.1 Tecnologie utilizzate 2.1.1 Framework .NET .NET `e un tipo di framework per lo sviluppo di applicazioni software prodotto da Microsoft, composto principalmente da due componenti: • Common Language Runtime (CLR) `E la macchina virtuale alla base del framework il cui compito principale `e quel- lo di gestire il codice in esecuzione fornendo una serie di servizi appartenenti al linguaggio utilizzato, tra cui la gestione della memoria, la gestione della sicurezza dell’applicazione, il caricamento di librerie e la compilazione. Essa `e caratterizzata da una fase iniziale in cui si ottiene un codice managed rac- chiuso all’interno di un assembly, rappresentato da un file eseguibile (.exe) o da una libreria (.dll), insieme a dei metadati contenenti informazioni sui tipi e sull’applicazione stessa. Questo codice managed non `e altro che un linguaggio intermedio (IL) che, nel momento in cui il CLR carica l’assembly, viene con- vertito nel codice nativo della macchina grazie ad un compilatore Just In Time presente al suo interno. Nonostante le varie operazioni, l’assembly contenente la maggior parte del codice originale viene mantenuto rendendone pi`u facile l’ispezione e la generazione dinamica del codice. • libreria delle classi `E una libreria di tipo object oriented compatibile con l’insieme dei linguaggi della famiglia .NET. Essa permette di creare diverse tipologie di applicazioni, che vanno dai servizi di Windows alle applicazioni web vere e proprie, con la possibilit`a di farle comunicare tra loro anche all’interno di uno stesso progetto. 21
  • 22. 22 CAPITOLO 2. TECNOLOGIE, STRUMENTI E PATTERN UTILIZZATI 2.1.2 ASP.NET MVC ASP.NET [4] `e un framework open source per lo sviluppo Web a lato server prodotto da Microsoft come evoluzione del motore di scripting ASP (Active Server Pages) in cui `e stata introdotta la possibilit`a di programmare in un qualsiasi linguaggio della famiglia .NET grazie al supporto dato dal CLR visto in precedenza. Nel contesto di sviluppo del progetto, `e stato scelto di utilizzare una sotto categoria chiamata ASP.NET MVC con lo scopo di separare le diverse logiche dell’applicazione dalle pagine di visualizzazione vere e proprie. Tale tecnologia infatti si basa sul pattern architetturale Model View Controller (MVC), in cui le applicazioni vengono suddi- vise in tre tipi di componenti le cui responsabilit`a all’interno di questo framework differiscono in alcuni casi da quanto si `e abituati a vedere. Parliamo quindi di: • Model: rappresentano i diversi modelli dell’applicazione gestendo tutte le operazioni relative alla manipolazione dei loro dati. • View: sono responsabili della visualizzazione delle interfacce utente. Tipica- mente riflettono la struttura dei diversi modelli dell’applicazione e per questo motivo sono legate ad essi dal punto di vista della comunicazione. • Controller: gestiscono le richieste dell’utente ogniqualvolta essi desiderano visualizzare una pagina. Tipicamente, un utente interagisce con una View che al suo interno genera una richiesta ad uno specifico URL, richiamando indirettamente un controller il cui compito `e quello di visualizzare la pagina desiderata. Un’ulteriore caratteristica introdotta in ASP.NET MVC `e il Routing. La mo- tivazione `e data dal fatto che grazie ad esso non vi `e pi`u la necessit`a di associare ad ogni URL un file fisico specifico, definendo cos`ı una regola di routing che andr`a ad interrogare un determinato controller. Per esempio, nel caso in cui si decides- se di registrare un nuovo cliente all’interno dell’applicazione, in ASP.NET classico sarebbe stato necessario riferirsi ad una precisa pagina che rispondeva all’indiriz- zo http:/sito/Customer/Register/Registration.aspx, mentre adesso baster`a indicare il controller e l’azione che si vuole eseguire, ottenendo un URL della forma /Cu- stomer/Register. La mappatura di queste regole deve essere fatta all’interno di un file presente nei progetti ASP.NET MVC chiamato RouteConfig.cs in cui `e possi- bile specificare quali controller e quali dei loro metodi sono incaricati a rispondere rispetto ad una determinata chiamata HTTP. Oltre al routing, concludiamo la descrizione generale di questo framework intro- ducendo un ultimo elemento: Razor. Esso non `e altro che una sintassi utilizzata per creare pagine web dinamiche mediante l’impiego dei linguaggi C e Visual Basic .NET le cui porzioni di codice verranno eseguite a lato server. La pagine web che vorranno implementare questa tecnologia avranno l’estensione .cshtml, inserendo porzioni di codice precedute dal carattere ”@”. 2.2 Strumenti utilizzati Prima di procedere alla descrizione dello sviluppo e delle funzionalit`a dell’applica- zione, descriviamo tutti gli strumenti che ne hanno reso possibile la creazione.
  • 23. 2.2. STRUMENTI UTILIZZATI 23 2.2.1 Visual Studio Per poter sviluppare un’applicazione con le tecnologie descritte nella precedente se- zione, `e stato necessario l’utilizzo dell’IDE Visual Studio [15]. Questo prodotto, oltre alle funzionalit`a di base necessarie per poter testare ed eseguire il codice prodotto, offre al suo interno il NuGet Package Manager, un gestore di pacchetti fondamentale per includere nel progetto le diverse librerie e moduli utilizzati nella comunicazione con i diversi servizi esterni all’applicazione. 2.2.2 Microsoft Azure Microsoft Azure [16] `e la piattaforma cloud sviluppata da Microsoft che offre una variet`a di strumenti resi disponibili come servizi ai diversi utilizzatori. Nell’ambito del progetto `e stato utilizzato come piattaforma su cui utilizzare i diversi DBMS NoSQL secondo un’ottica di Software As A Service (SaaS). Tale scelta `e motivata dalle seguenti caratteristiche: • scalabilit`a interna dei servizi eseguiti: Azure offre come caratteristica quella di gestire automaticamente la scalabilit`a verticale dei servizi offerti, senza la ne- cessit`a di dover impiegare ulteriori risorse per rendere efficienti le infrastrutture che li eseguono. • Georeplica dei servizi in esecuzione: ogni servizio eseguito su Azure `e replicato globalmente e in modo autonomo all’interno dei diversi datacenter, garantendo un’elevata affidabilit`a rispetto ai guasti. 2.2.3 SQL Server SQL Server [7], nella versione relativa all’anno 2012, `e un RDBMS sviluppato da Microsoft e utilizzato per poter gestire la base di dati relazionale all’interno del progetto. Esso `e stato utilizzato sotto forma di servizio all’interno della piattaforma Azure. 2.2.4 SQL Server Management Studio SQL Server Management Studio `e un’applicazione sviluppata da Microsoft per poter interagire con il DBMS SQL Server, offrendo strumenti per l’analisi e la creazione di query. 2.2.5 DBMS NoSQL utilizzati Andremo ora ad indicare i DBMS utilizzati appartenenti alla categoria NoSQL. Per comprendere il loro comportamento e le interazioni con l’applicazione, si rimanda al capitolo successivo. Si `e utilizzato: • Redis Cache: DBMS di tipo key-value in esecuzione come servizio su Azure, utilizzato per contenere il carrello degli acquisti dell’utente. [8]
  • 24. 24 CAPITOLO 2. TECNOLOGIE, STRUMENTI E PATTERN UTILIZZATI • Azure Blob Storage: `e un servizio di tipo file system per il salvataggio di BLOB, oggetti non strutturati di dimensioni generalmente non piccole. La sua struttura interna `e basata su contenitori, raggruppamenti di un numero di BLOB teoricamente infinito secondo una logica imposta dall’utente . Esso `e utilizzato all’interno dell’applicazione per il salvataggio delle foto relative ai prodotti venduti e per i PDF delle fatture. • Neo4J: `e un DBMS a grafo distribuito, installato come servizio in locale alla macchina in cui viene eseguita l’applicazione. Esso `e utilizzato per esegui- re operazioni di previsione sui possibili prodotti a cui un utente pu`o essere interessato in base a ci`o che ha recentemente acquistato o visualizzato. [9] • ElasticSearch: `e un DBMS documentale distributo utilizzato per il salvataggio di testi su cui vengono effettuate ricerche in base alla loro struttura. Anch’esso, insieme al DBMS Neo4j, `e eseguito in locale alla macchina. [10] 2.2.6 Git Git `e un software di controllo di versione utilizzato per tenere traccia dei cambia- menti nel corso dello sviluppo dell’applicazione. Esso `e stato usato per organizzare il codice sorgente secondo due branch (letteralmente ”rami”): nel primo, chiamato monolitic, `e stata sviluppata e versionata l’applicazione che utilizzava un solo data- base relazionale per tutte le tipologie di operazioni, mentre nel secondo, chiamato polyglot, era presente il sorgente dell’applicazione che si interfacciava con le diverse tipologie di database NoSQL precedentemente descritte. [14] 2.2.7 RedGate SQL Source Control `E uno strumento per il versionamento degli RDBMS sviluppato da RedGate [12] ed integrabile in SQL Server Management Studio. Il versionamento `e realizzato sempre attraverso Git, aggiungendo funzionalit`a importanti nell’ambito dei database relazionali tra cui: • la possibilit`a di versionare specifiche colonne di una tabella lasciando fuori quelle che contengono dati modificati di frequente. • l’inserimento di dati nelle tabelle prelevandoli da file esterni, utilizzato per attingere dati da file Excel in formato CSV. • il mantenimento dei record presenti nelle diverse tabelle sotto forma di comandi INSERT INTO, potendo gestirli e modificarli senza dover eseguire dei comandi di ALTER TABLE. 2.2.8 Entity Framework `E un framework open source utilizzato per interfacciare le entit`a di un database rela- zionale a delle classi presenti all’interno di applicazioni basate sul framework .NET. Esso permette due tipologie di approcci: nel primo, chiamato Code First, le entit`a vengono scritte inizialmente da codice sotto forma di classi per poi essere riportate
  • 25. 2.3. PATTERN UTILIZZATI 25 su database relazionali mantenendo nomi, tipi e vincoli, mentre nel secondo, chia- mato Database First, si parte da un modello relazionale gi`a presente su database da cui si genera una serie di classi all’interno dell’applicazione che lo rispecchiano. Nel contesto dell’applicazione `e stato utilizzato il secondo approccio. [13] 2.3 Pattern utilizzati Descriviamo la terza e ultima sezione di questo capitolo inerente ai pattern utilizzati nello sviluppo dell’applicazione, sia dal punto di vista architetturale che da quello metodologico. 2.3.1 Model View View-Model (MVVM) L’utilizzo di Entity Framework e la struttura delle applicazioni basate su ASP.NET MVC introducono la necessit`a di dover isolare l’interfaccia grafica dal resto del- l’applicazione dal momento che non si ha pi`u un controllo totale sul suo modello. Per questa ragione, `e stato deciso di utilizzare il pattern Model View View-Model (MVVM) che `e composto dai seguenti componenti: • Model: `e uguale al Model del pattern MVC presentato in precedenza, che in questo contesto si concretizza con le classi generate da Entity Framework. • View: anch’esso composto dalle classi e dalle pagine relative alla visualizza- zione delle interfacce utente. • View-Model: si pone tra il Model e la View. Ogni View nel prelevare i dati si rifar`a ora al View-Model, spostando in esso tutte le logiche di business, interagendo con il Model solo per prelevare i dati iniziali non ancora lavorati. Figura 2.1: Rappresentazione del pattern MVVM nell’ambito di un’applicazione ASP.NET MVC. 2.3.2 Kanban Il lavoro che ha portato allo sviluppo del progetto `e stato organizzato con un me- todologia evolutiva chiamata Kanban ispirata alla filosofia della programmazione snella (Lean Production). La caratteristica principale risiede nell’utilizzo di una ta- bella chiamata Kanban Board, composta da quattro colonne che rappresentano le
  • 26. 26 CAPITOLO 2. TECNOLOGIE, STRUMENTI E PATTERN UTILIZZATI diverse fasi di sviluppo (To Do, Doing, Testing, Done). Ciascuna di esse conterr`a degli elementi chiamati kanban cards che rappresentano le varie azioni di sviluppo, considerate complete solo quando si trovano nella colonna Done. Tra le altre caratteristiche di questa metodologia, troviamo la voluta mancanza di ruoli definiti all’interno del team associata al fatto che i cambiamenti possono avvenire in ogni momento. Tutto questo da vita ad un’ottica di rilascio continuo (Continous delivery) che conferisce la dinamicit`a di questa metodologia.
  • 27. Capitolo 3 Il contesto applicativo In questo capitolo verr`a mostrato lo sviluppo dell’applicazione introducendo la strut- tura generale e gli scopi per cui `e stata creata, descrivendo successivamente le due soluzioni sviluppate, ovvero quella monolitica, in cui viene utilizzato un solo tipo di storage, e quella poliglotta, la quale estende la precedente con l’utilizzo di database NoSQL. 3.1 Descrizione e scopi dell’applicazione L’applicazione realizzata durante il lavoro di tesi `e la riproduzione di una piattaforma di e-commerce di tipo B2B(Business to Business) sviluppata all’interno dell’azienda in cui `e stato svolto il tirocinio. Essa viene erogata sotto forma di servizio senza la necessit`a di installarla all’interno delle macchine dei clienti utilizzatori. Le opera- zioni eseguite variano in base al tipo di soluzione presa in esame, ma nel complesso `e comunque possibile: • registrare un’azienda mediante l’inserimento di una serie di informazioni anagrafiche, tra cui l’opzione di caratterizzarla come Reseller (rivenditore) o come Buyer (acquirente) . Per semplicit`a `e stato scelto di non dare possibilit`a ad un’azienda Reseller di poter acquistare prodotti e ad un’azienda Buyer di poterne vendere. • modificare i dati di un’azienda in caso di aggiornamento delle sue infor- mazioni. Non sar`a possibile modificare la sua tipologia (buyer o reseller, vedi sopra). • inserire un prodotto da parte di un’azienda reseller, specificando sia le informazioni di vendita che un’eventuale immagine rappresentativa. • aggiornare le informazioni di un prodotto senza restrizioni sui campi modificabili a differenza di quanto visto con le aziende. • visualizzare il pannello di controllo di ciascun utente che, in base alla sua tipologia, varier`a nelle operazioni disponibili offrendo in entrambi i casi uno storico degli ordini precedenti con la possibilit`a di visualizzarne le fatture. • ricercare uno o pi`u prodotti in base alla descrizione da parte di un’a- zienda Buyer, visualizzando una lista contenente il risultato dell’operazone da cui `e possibile aggiungere i prodotti desiderati al carrello. 27
  • 28. 28 CAPITOLO 3. IL CONTESTO APPLICATIVO • salvare i prodotti da acquistare inserendoli all’interno di un carrello virtuale in base alle quantit`a selezionate. • visualizzare il carrello virtuale in modo tale da rimuovere i prodotti inde- siderati o per finalizzare l’operazione di acquisto. • completare l’acquisto in base agli elementi presenti nel carrello virtuale, generando e salvando un file PDF che rappresenta la sua fattura. • ricevere consigli sui prodotti futuri per mezzo di una mail in base a quanto appena acquistato da parte di un utente. 3.2 Struttura dell’applicazione Veniamo ora alla descrizione generale dell’applicazione indipendentemente dal tipo di soluzione sviluppata. Essa si divide in una parte client, che si interfaccia diret- tamente con l’utente, ed in una server in cui sono presenti i diversi database. Dal momento che i database NoSQL sono schemaless e appartenenti ad una delle due soluzioni, verr`a introdotto saolamente il database relazionale gestito dal DBMS SQL Server presente in entrambe. Per descriverlo, partiamo dal suo schema ER: Product Uses 1..1 Refers 1..1 Owns 0..1 Contains 0..N 1..1 Buys 0..N Currency 1..N Category 0..N ProductPhoto 1..1 SalesOrderDetail 1..1 Customer 1..N1..1 Lives 1..1 Creates 0..N 1..1 UnitMeasure 0..N Province 0..N ClientPolicy 0..N SalesOrderHeader 1..1 Is 1..1 Has 0..N Has 1..1 OrderStatus 0..N
  • 29. 3.2. STRUTTURA DELL’APPLICAZIONE 29 Questo schema rappresenta le seguenti entit`a con la loro descrizione: • Customer: rappresenta l’azienda che vuole acquistare o vendere dei prodotti. • CustomerPolicy: rappresenta la tipologia di azienda con cui `e possibile regi- strarsi. • Province: rappresenta la provincia in cui l’azienda risiede. • Product: rappresenta il prodotto acquistato o venduto da un’azienda. • UnitMeasure: rappresenta l’unit`a di misura utilizzata nella descrizione del peso e della lunghezza di un prodotto. • Currency: rappresenta la valuta utilizzata per rappresentare il prezzo di un prodotto. • Category: rappresenta la categoria a cui appartiene un prodotto. • ProductPhoto: rappresenta la foto associata ad un prodotto. • SalesOrderHeader: rappresenta le informazioni di intestazione di un ordine. • SalesOrderDetail: rappresenta le informazioni dell’acquisto di un prodotto all’interno di un ordine. • OrderStatus: rappresenta lo stato di un ordine. Dal lato client, l’applicazione `e stata sviluppata con un’architettura di tipo three-tier che presenta diverse analogie con il pattern MVC. Essa infatti `e composta da tre elementi: • l’interfaccia utente realizzata mediante la creazione di pagine web. • la logica di business realizzata dalle classi appartenenti alla categoria dei Con- troller e dei View Model che manipoleranno i dati in entrata e in uscita dall’applicazione. • il data layer costituito dal DBMS su cui verranno salvati i dati. Il funzionamento generale `e il seguente: l’utente, in base all’operazione che vuole eseguire, selezioner`a una voce apposita di un menu presente nelle diverse pagine, inviando una richiesta URL della forma /ControllerScelto/AzioneDesiderata. Essa richiamer`a uno specifico metodo di un controller, incaricato a visualizzare la pagina desiderata e consumando nella maggior parte dei casi un oggetto appartenente alla categoria dei view model. Il compito di quest’ultimo oggetto `e quello di prelevare dal database i dati necessari ad essere visualizzati. Tale ragionamento si applica anche alla pressione dei tasti di conferma presenti nei vari form dal momento che si tratta comunque del meccanismo di routing di ASP.NET MVC unito al pattern Model View View-Model e all’architettura Three-Tier visti in precedenza. Dal punto di vista architetturale, `e possibile categorizzare le classi in base al loro ruolo. Possiamo quindi identificare:
  • 30. 30 CAPITOLO 3. IL CONTESTO APPLICATIVO • il modello da cui si attingeranno i dati utilizzati nell’applicazione: `e composto da una serie di classi scritte in C create mediante l’utilizzo di Entity Framework. Come gi`a descritto nel capitolo precedente, le tabelle presenti nel database relazionale sono mappate all’interno dell’applicazione con una rispet- tiva classe il cui nome e campi sono generati in automatico. Prendendo come esempio l’entit`a Customer relativa ad un’azienda, il framework ha generato un file chiamato Customer.cs il cui contenuto `e il seguente: 1 public partial class Customer 2 { 3 public Customer () 4 { 5 this. SalesOrderHeaders = new HashSet <SalesOrderHeader >(); 6 this.Products = new HashSet <Product >(); 7 } 8 9 public int CustomerID { get; set; } 10 public string Name { get; set; } 11 public string Email { get; set; } 12 public string Psw { get; set; } 13 public string Address { get; set; } 14 public string PhoneNumber { get; set; } 15 public string IBAN { get; set; } 16 public string PartitaIVA { get; set; } 17 public byte PolicyID { get; set; } 18 public byte ProvinceID { get; set; } 19 20 // Entita ’ per cui si ha una relazione all ’interno del database. 21 22 // In relazione uno a molti. 23 public virtual CustomerPolicy CustomerPolicies { get; set; } 24 public virtual Province Provinces { get; set; } 25 26 // In relazione molti a uno. 27 public virtual ICollection <SalesOrderHeader > SalesOrderHeaders { get; set; } 28 public virtual ICollection <Product > Products { get; set; } 29 } `E interessante notare alcune caratteristiche comuni a tutte le classi mappate con questo meccanismo. Come prima cosa, esse utilizzano nella loro definizione la parola chiave partial, la quale specifica che la definizione della classe pu`o avvenire anche in altre parti all’interno del namespace, purch´e utilizzino a loro volta questa parola chiave. In un tale scenario, in cui le classi possono essere aggiornate dal framework, l’utilizzo della keyword partial permette di definire in un file slegato tutti gli attributi ed i metodi che non dovranno essere coinvolti nelle modifiche. Per questa ragione, la definizione delle classi relative alle
  • 31. 3.2. STRUTTURA DELL’APPLICAZIONE 31 entit`a Product, ProductPhoto e Customer sono state ampliate tramite classi partial su file esterni. In merito alla seconda caratteristica dell’applicazione, notiamo che all’interno della classe precedentemente riportata sono presenti degli attributi riferiti a delle entit`a con cui `e stata definita una relazione. Notiamo infatti che nel caso di relazioni uno a uno (1:1) o uno a molti (1:N) in cui la classe si trova dalla parte dell’entit`a con cardinalit`a unario, l’entit`a mappata sar`a un solo oggetto mentre nel caso contrario avremo una collezione di oggetti di tipo ICollection<T>, tipizzata in base alla classe dell’entit`a corrispondente. • i controller adibiti alla visualizzazione delle pagine web: sono classi scritte in C che, ereditando la classe Controller presente nel framework .NET, sono in grado di rispondere alle richieste HTTP inviate ad un’applicazione ASP.NET MVC. Tale caratteristica permette anche di richiamare queste classi all’interno dei pattern di routing senza dover esplicitare completamente il nome omettendo la parola Controller al suo interno. Venendo alle classi presenti nella categoria, troviamo: – CustomerController: gestisce le pagine relative alle operazioni di acces- so, disconnessione, registrazione di un nuovo utente e alla sua modi- fica. Esse sono accessibili mediante il pattern di routing della forma /Customer/NomeMetodoDesignato. – ProductController: si occupa della registrazione, modifica e cancellazio- ne di un prodotto e della loro rappresentazione all’interno della pagina contenente i risultati della ricerca. Il pattern di routing per accedervi `e /Product/NomeMetodoDesignato. – OrderController: si occupa di tutte le operazioni che riguardano i prodotti scelti e il carrello virtuale come l’inserimento, la rimozione e la visualizza- zione dei prodotti al suo interno, insieme alle operazioni di prelevamento di una fattura relativa ad un ordine e alla finalizzazione dell’ordine stesso. • le classi adibite all’interfacciamento con i differenti database: sono classi create appositamente per poter gestire le connessioni e le operazioni con i diversi DBMS. Esse, indipendentemente dal tipo di soluzione, sono le seguenti: – IRelationalDatabaseManager: `e l’interfaccia implementata da tutte le classi che vorranno interagire con l’RDBMS dell’applicazione. Esso `e costituito da un solo metodo, GetDBManager, che ritorna un oggetto di tipo DatabaseEntity creato durante l’importazione del database me- diante l’utilizzo di Entity Framework. Al suo interno sono contenute sia stored procedure importate sempre da Entity framework, utilizzandole sotto forma di metodi, che le entit`a mappate visibili nel seguente estratto di codice : 1 2 // DatabaseEntity .cs 3 4 public virtual DbSet <Category > Categories{get;set;}
  • 32. 32 CAPITOLO 3. IL CONTESTO APPLICATIVO 5 public virtual DbSet <ClientPolicy > ClientPolicies {get;set;} 6 public virtual DbSet <Currency > Currencies{get;set;} 7 public virtual DbSet <Customer > Customers{get;set;} 8 public virtual DbSet <OrderStatus > OrderStatus{get;set;} 9 public virtual DbSet <Province > Provinces{get;set;} 10 public virtual DbSet <SalesOrderHeader > SalesOrderHeaders {get;set;} 11 public virtual DbSet <UnitMeasure > UnitMeasures{get;set;} 12 public virtual DbSet <SalesOrderDetail > SalesOrderDetails {get;set;} 13 public virtual DbSet <Product > Products{get;set;} Quanto appena mostrato evidenzia come tale framework, partendo dalle tabelle presenti in un database, crei una loro mappatura dando vita al Model dell’applicazione. Al suo interno notiamo come gli oggetti siano tutti di tipo DbSet<T>, tipizzati con le classi del modello, sfruttando il fatto che in essa sono dichiarati una serie di metodi per le tipiche operazioni di inserimento, modifica, lettura e rimozione di un record. Anche in questo caso mostriamo un breve estratto della sua definizione con i metodi utilizzati nello sviluppo: 1 // DbSet.cs 2 3 /* Inserisce o aggiorna nel database un record identificando tabella e campi a partire 4 * dalla classe TEntity che verra ’ tipizzata al momento della creazione dell ’oggetto 5 * DbSet <TEntity > 6 */ 7 public virtual TEntity Add(TEntity entity); 8 9 /* Cerca un record all ’interno della tabella mappata dalla classe che tipizza l’oggetto 10 * in base al valore della chiave primaria 11 */ 12 public virtual TEntity Find(params object [] keyValues); 13 14 /* Rimuove dall database un record in base alla chiave primaria , identificando tabella e chiave * primaria dalla classe TEntity che verra ’ tipizzata al momento della creazione dell ’oggetto 15 * DbSet <TEntity > 16 */ 17 public virtual TEntity Remove(TEntity entity); La descrizione di questa interfaccia dovrebbe dare quindi un’idea di come avviene la comunicazione con il database relazionale: non sar`a neces- sario scrivere SQL dinamico da codice per eseguire query o richiamare
  • 33. 3.2. STRUTTURA DELL’APPLICAZIONE 33 stored procedure ma baster`a utilizzare i metodi forniti indicando sola- mente i parametri, che possono essere oggetti appartenenti al modello dell’applicazione o definiti dall’utente. – RelationalDatabaseManager: `e la classe che implementa l’interfaccia IRe- lationalDatabaseManager permettendo quindi la comunicazione tra l’ap- plicazione e il database relazionale secondo le modalit`a descritte nel punto precedente. – RelationalDatabaseManager: `e la classe che implementa la comunicazione con il database relazionale dell’applicazione e che implementa l’interfaccia IRelationalDatabaseManager, con tutte le meccaniche dovute all’utilizzo di Entity Framework viste precedentemente. – INoSQLDatabaseManager: `e l’interfaccia implementata da tutte le classi a seguire contenente al suo interno. – DocumentalDatabaseManager: `e la classe che concretizza la comunicazio- ne con il database documentale inserendo i diversi documenti e prelevan- doli in merito al loro identificativo con cui sono stati salvati. – GraphDatabaseManager: all’interno di questa classe verr`a gestita la co- municazione con il database a grafo, inserendo un nodo che identifica un prodotto o un’azienda al loro inserimento nel sistema e creando una relazione che li coinvolge al momento di un acquisto. – KeyValueDatabaseManager: `e la classe che gestisce la comunicazione con il database di tipo key - value, implementando al suo interno le operazioni di inserimento, modifica e rimozione del carrello associato ad un utente. – StorageDatabaseManager: `e l’ultima classe per la comunicazione con i database, riferendosi in questo caso ad un file system su cui salvare e prelevare sia le foto dei prodotti che i PDF dei diversi ordini effettuati. • le classi appartenenti alla categoria ViewModel: concretizzano le fun- zionalit`a fornite dall’applicazione dal momento che, come spiegato nella sezio- ne precedente, contengono tutte le logiche di business. Forniamo quindi una descrizione generale delle classi appartenenti a questa categoria, entrando nel dettaglio durante la descrizione delle singole operazioni: – CustomerViewModel: gestisce tutte le operazioni inerenti ad un’azienda come la registrazione, l’aggiornamento dei dati, il prelevamento di tutte le fatture ad esso associate insieme all’accesso e alla disconnessione dal sistema. – ProductViewModel: gestisce tutte le operazioni che coinvolgono i prodotti all’interno dell’applicazione, occupandosi dell’inserimento, della modifica e della cancellazione. – SearchViewModel: gestisce la ricerca dei prodotti e la loro visualizzazione all’interno dell’applicazione. – ShoppingItemViewModel: viene utilizzata dagli altri ViewModel per la visualizzazione dei prodotti insieme alle informazioni ad essi legate, come ad esempio l’azienda che li ha messi in vendita. Al suo interno infatti si
  • 34. 34 CAPITOLO 3. IL CONTESTO APPLICATIVO possono trovare attributi utilizzati per scopi di visualizzazione e relazioni di tipo HAS A con alcune classi appartenenti alla categoria Model. – ShoppingItemListViewModel: `e una classe che contiene al suo interno una lista di oggetti di tipo ShoppingItemViewModel utilizzata dagli altri componenti dell’applicazione nel salvataggio delel informazioni relative ai prodotti. 3.3 La soluzione monolitica Ora che abbiamo introdotto la struttura dell’applicazione, andiamo a descrivere ognuna delle due soluzioni sviluppate in base al loro comportamento rispetto alle funzionalit`a eseguite. 3.3.1 Registrazione di una nuova azienda `E possibile registrare una nuova azienda mediante il pattern di routing /Customer/Registration. Esso richiamer`a il metodo Registration del controller Cu- stomerController visualizzando la pagina Registration.cshtml cos`ı strutturata: Figura 3.1: Pagina di registrazione di una nuova azienda.
  • 35. 3.3. LA SOLUZIONE MONOLITICA 35 I campi visualizzati nella pagina sono prelevati dalla classe CustomerViewModel che a sua volt`a si rifar`a a quelli presenti nella classe Customer, con la differenza che essi utilizzano un meccanismo di rappresentazione degli attributi appartenente alla tecnologia ASP.NET MVC chiamato data annotation. Esso permette di utilizzare determinati attributi, appartenenti al namespace System.ComponentModel.DataAn notations, che al momento della compilazione genereranno del codice HTML all’in- terno della rispettiva view rispettando il tipo di validazione assegnata. Per rendere meglio l’idea, mostreremo un estratto della classe CustomerViewModel in cui ven- gono utilizzati gli attributi di data annotation: 1 [Required] 2 [EmailAddress] 3 [StringLength(maximumLength: 50, ErrorMessage = "Email length must be less than 50 characters")] 4 public string Email { get; set; } 5 6 [Required] 7 [Display(Name = "Password")] 8 [StringLength(minimumLength: 8, maximumLength: 50, ErrorMessage = "Password length must be between 8 and 50 characters" )] 9 [DataType(DataType.Password)] 10 public string Psw { get; set; } 11 12 [Required] 13 [Display(Name = "Confirm Password")] 14 [DataType(DataType.Password)] 15 [Compare("Psw", ErrorMessage = "Passwords must match")] 16 [StringLength(minimumLength: 8, maximumLength: 50, ErrorMessage = "Password length must be between 8 and 50 characters" )] 17 public string ConfirmPsw { get; set; } In questa porzione di codice `e possibile notare diverse caratteristiche. Per cominciare si pu`o vedere come i campi in questione siano tutti necessari al fine della registrazione grazie alla presenza dell’attributo Required. In merito agli attributi Psw e ConfirmP- sw che andranno invece a rappresentare i campi in cui inserire la password, notiamo come entrambi sono preceduti dall’attributo DataType(DataType.Password), per in- dicare che essi andranno a contenere un dato sensibile, e da Display(Name) per fare in modo che la pagina in cui verranno visualizzati non utilizzi il nome del cam- po ma uno definito ad hoc. Come ultima caratteristica, si pu`o notare come sia possibile definire una lunghezza minima e massima del campo, grazie all’attributo StringLength(minimumLength, maximumLength, ErrorMessage), sia il fatto che esso dovr`a essere uguale al contenuto di un altro campo, se presente, mediante l’attributo Compare(NomeCampoConCuiConfrontarsi). Il loro utilizzo, nella pagina Registra- tion.cshtml, generer`a il rispettivo codice: 1 <div class="form -group"> 2 <label class="col -md -2" for="Email">Email </label > 3 <div class="col -md -10">
  • 36. 36 CAPITOLO 3. IL CONTESTO APPLICATIVO 4 <!-- [EmailAddress] --> 5 <input class="form -control" id="Email" name="Email" type="text" value="" /> 6 <!-- Validazione in javascript che include la lunghezza massima e la forma 7 corretta per essere un indirizzo email. --> 8 <span class="field -validation -valid text -danger" id=" Email_validationMessage " ></span > 9 </div > 10 </div > 11 12 <div class="form -group"> 13 <!-- [Display(Name = "Password")] --> 14 <label class="col -md -2" for="Psw">Password </label > 15 <div class="col -md -10"> 16 <!-- [DataType(DataType.Password)] --> 17 <input class="form -control" id="Psw" name="Psw" type="password" /> 18 <!-- Validazione in javascript che include la lunghezza minima e massima --> 19 <span class="field -validation -valid text -danger" id=" Psw_validationMessage " ></span > 20 </div > 21 </div > 22 23 <div class="form -group"> 24 <!-- [Display(Name = "Confirm Password")] --> 25 <label class="col -md -2" for="ConfirmPsw">Confirm Password </label > 26 <div class="col -md -10"> 27 <input class="form -control" id="ConfirmPsw" name="ConfirmPsw" type="password" /> 28 <!-- Validazione in javascript che include la lunghezza minima e massima insieme al test di ugaglianza rispetto al campo Psw --> 29 <span class="field -validation -valid text -danger" id=" ConfirmPsw_validationMessage " ></span > 30 </div > 31 </div > L’utilizzo di questo meccanismo ha come vantaggio quello di poter fornire gi`a a lato client il corretto dimensionamento dei campi rispetto agli attributi presenti nelle tabelle su database relazionale, sollevando l’RDBMS dalle operazioni di controllo. Ritornando alla descrizione dei ruoli delle classi coinvolte, notiamo come la clas- se CustomerViewModel sia utilizzata per comunicare con la classe Provinces, per poter visualizzare le province, e ClientPolicies, per poter visualizzare le tipologie di azienda con cui `e possibile registrarsi. A seguire, mediante la pressione del ta- sto Registrati, l’applicazione richiamer`a il metodo CheckRegistration, appartenente sempre al controller CustomerController, passandogli come attributo l’oggetto di ti- po CustomerViewModel contenente gli attributi valorizzati nei campi presenti nella pagina. Al suo interno, verr`a successivamente richiamato il metodo InsertCusto-
  • 37. 3.3. LA SOLUZIONE MONOLITICA 37 mer, che istanzier`a un nuovo oggetto di tipo Customer, per rappresentare un record del modello di cui fa parte, e un oggetto di tipo DatabaseEntity generato da Enti- ty Framework con cui interfacciarsi al database relazionale. Ottenuto quest’ultimo oggetto, l’inserimento avverr`a utilizzando il metodo Add() della classe Customer passando come attributo un oggetto di tipo customer Customer. Esso inserir`a un nuovo record all’interno dell’omonima tabella occupandosi della mappatura degli attributi con i valori inseriti. La funzione appena descritta `e la seguente: 1 2 public bool InsertCustomer () 3 { 4 /* Istanziazione l’oggetto c di classe Customer dandogli come parametro il CustomerViewModel chiamante dal momento che esso , secondo il pattern MVVM , contiene i suoi stessi parametri. 5 */ 6 c = new Customer(this); 7 8 try 9 { 10 /*Il metodo getDBManager () ritorna un oggetto di tipo DatabaseEntity relativo al database relazionale per inserire l’oggetto di tipo Customer contenente i valori di una nuova riga. 11 */ 12 dbManager.GetDBManager ().Customers.Add(c); 13 dbManager.GetDBManager ().SaveChanges (); 14 }catch(Exception e){ 15 Console.WriteLine(e.StackTrace); 16 return false; 17 } 18 19 return true; 20 } Ad operazione correttamente eseguita, la nuova azienda verr`a inserita all’interno del database ritornando al chiamante CheckRegistration il suo esito: in caso positivo, l’utente verr`a indirizzato al pannello di controllo dell’utente, mentre in caso contrario l’utente verr`a indirizzato ad una pagina d’errore che lo informer`a dell’esito negativo dell’operazione. 3.3.2 Modifica dei dati di un’azienda La modifica dei dati di un’azienda gi`a presente nel sistema ha molti tratti in comune con l’inserimento appena visto. La differenza sostanziale risiede nel fatto che al momento della visualizzazione della pagina la classe CustomerViewModel si occuper`a di prelevare i dati dell’azienda partendo dal suo codice identificativo salvato nella sessione. Tale operazione `e implementata nel seguente frammento di codice: 1 public ActionResult EditCustomerAccount ()
  • 38. 38 CAPITOLO 3. IL CONTESTO APPLICATIVO 2 { 3 /* Viene istanziato un oggetto CustomerViewModel contenente i dati dell ’utente che verra ’ passato alla view come parametro. */ 4 CustomerViewModel cvm = new CustomerViewModel (); 5 // Viene prelevato l’id dell ’utente dalla sessione 6 cvm.CustomerID = (int)Session["CustomerID"]; 7 /* Viene chiamata la funzione GetCustomerByID che prelevera ’ i parametri da visualizzare nella pagina di modifica in base all ’ identificativo dell ’utente. */ 8 cvm. GetCustomerById ((int)Session["CustomerID"]); 9 10 return View(cvm); 11 } La funzione GetCustomerById far`a uso di una stored procedure chiamata con lo stesso nome il cui result set conterr`a le informazioni da visualizzare nella pagina di modifica. Poich`e si tratta di una sola operazione di SELECT, non verr`a mostrato il codice SQL relativo. A modifiche eseguite, cliccando sul tasto Aggiorna verr`a richiamato il metodo UpdateCustomer, appartenente alla classe CustomerController, passandogli come parametro l’oggetto di tipo CustomerViewModel che conterr`a al suo interno i valo- ri dell’utente modificati. Questo metodo utilizzer`a una stored procedure chiamata UpdateCustomerById la cui natura `e duale rispetto a quella vista nell’operazione precedente: se la prima restituiva un result set con certi dati relativi all’azienda, essa utilizzer`a tali attributi come parametri al cui interno saranno presenti i valori dell’utente aggiornati. Anche in questo caso, dal momento che la stored procedure `e composta da una serie di operazioni SET su un record identificato dall’attributo CustomerID, non verr`a riportato il codice. 3.3.3 Visualizzazione del pannello di controllo di un utente Dopo aver effettuato l’accesso al sistema o dopo aver registrato un utente, l’applica- zione visualizzer`a il pannello di controllo in cui sono possibili diverse operazioni in base alla tipologia di utente definita dall’attributo Policy. Se l’utente infatti `e stato registrato come Seller, esso potr`a: • inserire un prodotto. • modificare un prodotto. • visualizzare lo storico degli ordini con la possibilit`a di prelevare il docu- mento PDF contenente la relativa bolla. • disconnettersi dal sistema. Se l’utente invece `e stato invece registrato come Seller, oltre alla visualizzazione dello storico degli ordini sar`a possibile: • ricercare un prodotto in base alla sua descrizione. • visualizzare i dettagli di un prodotto.
  • 39. 3.3. LA SOLUZIONE MONOLITICA 39 • visualizzare il carrello con i prodotti. • completare l’acquisto dei prodotti presenti nel carrello. Definite le operazioni possibili da ciascun utente, vediamo la pagina Dashboard.cshtml incaricata a visualizzare il pannello di controllo: 3.3.4 Inserimento di un prodotto La pagina di inserimento di un prodotto `e accessibile mediante il pattern di rou- ting /Product/AddProduct, facendo riferimento al controller ProductController. Al suo interno `e presente il metodo AddProduct la cui logica `e molto simile a quella dell’inserimento di un’azienda. Essa far`a riferimento infatti ad un oggetto di tipo ProductViewModel il quale al suo interno ha gli stessi attributi della classe Product, con l’aggiunta delle data annotations per gli scopi di inserimento e visualizzazio- ne. Questo oggetto verr`a assegnato dal controller alla view incaricata a visualizzare il prodotto, corrispondente al file AddProduct.cshtml che si presenta nel seguente modo:
  • 40. 40 CAPITOLO 3. IL CONTESTO APPLICATIVO Figura 3.2: Pagina di inserimento di un prodotto. In questo caso il sistema di data annotation, oltre che per gli usi tradizionali di visualizzazione e di controllo di integrit`a dei campi, viene usato anche per far s`ı che i campi Peso e Lunghezza, se valorizzati, abbiano anche una rispettiva unit`a di misura. Alla pressione del tasto Inserisci Prodotto, il controller ProductController richia- mer`a il metodo InsertProduct passandogli come parametro l’oggetto di tipo Custo- merViewModel i cui campi sono stati appena valorizzati. Tale oggetto richiamer`a a sua volta un suo metodo, chiamato sempre InsertProduct il cui comportamento `e analogo al metodo InsertCustomer visto nella registrazione di una nuova azienda. Al suo interno viene infatti instanziato un oggetto inerente al modello su cui lavora, in questo caso di tipo Product, il cui costruttore `e stato ridefinito per poter ricevere come parametro un oggetto di tipo ProductViewModel instanzianziando successiva- mente un oggetto di tipo DatabaseEntity per poter inserire un nuovo record nella tabella Product presente nel database relazionale. L’inserimento `e sempre garantito mediante l’utilizzo del metodo Add che questa volta prender`a in input un oggetto di tipo Product. La descrizione appena mostrata fa riferimento al seguente codice: 1 public bool InsertProduct () 2 { 3 /* Viene instanziato un oggetto di tipo Product i cui attributi assumeranno il valore dei loro corrispondenti
  • 41. 3.3. LA SOLUZIONE MONOLITICA 41 presenti nella classe ProductViewModel */ 4 Product product = new Product(this); 5 try 6 { 7 /* Viene inserito nella tabella Product un record i cui campi sono mappati dall ’oggetto appena definito.*/ 8 dbManager.GetDBManager ().Products.Add(product); 9 dbManager.GetDBManager ().SaveChanges (); 10 }catch(Exception e){ 11 Debug.WriteLine(e.StackTrace); 12 return false; 13 } 14 return true; 15 } Anche per l’inserimento di un prodotto, l’esito del metodo decider`a la pagina a cui reindirizzer`a il controller ProductController: in caso di inserimento avvenuto verr`a visualizzato il pannello di controllo principale dell’atrimenti, altrimenti verr`a visualizzata una pagina contenente un messaggio di errore. 3.3.5 Aggiornamento delle informazioni di un prodotto La pagina per aggiornare le informazioni corrispondenti ad un prodotto `e accessibile mediante il pattern di routing /Product/EditProduct, gestito dal controller Product- Controller. Questa funzionalit`a `e predisposta solamente per gli utenti Seller e il suo funzionamento `e leggermente diverso dalla modifica di un’azienda. Dal momento in- fatti che esse possono vendere pi`u prodotti, l’applicazione reindirizzer`a l’utente verso la pagina EditProductList.cshtml che visualizzer`a la lista dei suoi prodotti venduti. Premendo il tasto Modifica di uno degli elementi si verr`a reindirizzati alla pagina di modifica vera e propria, chiamata EditProduct.cshtml, la cui struttura `e la stessa di quella dell’inserimento di un prodotto se non per il fatto che i suoi campi saranno gi`a valorizzati con i dati prelevati. A modifiche avvenute, l’applicazione richiamer`a sempre il controller ProductController passando come parametro del suo metodo, chiamato UpdateProduct, il chiamante di tipo ProductViewController. Al suo inter- no, l’oggetto parametro richiamer`a il metodo UpdateProductById per aggiornare il prodotto, mediante una stored procedure, in base al suo codice identificativo. A funzione terminata, il controler reindirizzer`a l’utente alla pagina del suo pannello di controllo in caso di esito positivo, altrimenti visualizzer`a ad una pagina contenente un messaggio di errore. 3.3.6 Ricerca dei prodotti in base alla descrizione e aggiunta al carrello. La ricerca di un prodotto `e utilizzabile solamente da un’azienda Buyer in quanto nel suo pannello di controllo `e presente un’apposita casella di ricerca. Alla pressio- ne del tasto Cerca verr`a richiamato il metodo ProductList presente all’interno del controller ProductController che ricever`a come parametro la stringa di ricerca. Al suo interno verr`a istanziato un oggetto di tipo SearchViewModel con un costrutto- re definito appositamente il cui parametro `e la stringa di ricerca da assegnare ad
  • 42. 42 CAPITOLO 3. IL CONTESTO APPLICATIVO un attributo apposito presente al suo interno. L’oggetto appena instanziato verr`a utilizzato richiamando il metodo SearchProductsAndCustomers dove, al suo inter- no, un oggetto di tipo DatabaseEntity utilizzer`a la stored procedure SearchProducts sotto forma di metodo, passandogli come parametro la chiave di ricerca costituita da soli caratteri in minuscolo in cui sono stati eliminati gli eventuali spazi. Que- sta procedura al suo completamento ritorner`a le informazioni relative alla tabella dei prodotti (Products) e a tutte le tabelle ad essa associate che contengono infor- mazioni utili alla loro visualizzazione (Customers, UnitMeasures, Currencies). Per ogni record nel result set ottenuto verr`a istanziato un oggetto di tipo ShoppingItem contenente tutti i campi prelevati: ciascuno di essi a sua volta verr`a aggiunto al- l’oggetto di tipo List<ShoppingItem> chiamato ShoppingItems, presente nella classe ShoppingItemManager. Una volta completata la ricerca, il metodo ritorner`a il controllo al metodo Pro- ductList, appartenente alla classe ProductController, che visualizzer`a la lista dei prodotti ottenuti all’interno dell’oggetto di tipo SearchViewModel precedentemente istanziato. Per completare l’operazione di ricerca, questo controller visualizzer`a la pagina ProductList.cshtml incaricata a visualizzare il risultato, il cui il risultato `e il seguente: Figura 3.3: Risultato di una ricerca secondo la chiave ”vite”. Come si pu`o notare, la pagina offre la possibilit`a di selezionare la quantit`a dei prodotti in modo tale da aggiungerli al carrello, completando l’operazione mediante la pressione del tasto Aggiungi prodotti al carrello. 3.3.7 Visualizzazione dei prodotti all’interno del carrello Gli utenti Buyer hanno la possibilit`a di visualizzare i prodotti in fase di acquisto presenti nel carrello virtuale. Tale funzionalit`a `e raggiungibile mediante il pattern di routing /Order/ShoppingCartDetail, in cui il metodo ShoppingCartDetail, appar- tenente al controller OrderController, instanzier`a al suo interno un oggetto di tipo
  • 43. 3.3. LA SOLUZIONE MONOLITICA 43 ShoppingItemManager a cui verr`a assegnata una lista di elementi di tipo Shoppin- gItem prelevata dalla sessione. Questo oggetto sar`a poi utilizzato come parametro alla View incaricata a rappresentare la pagina, completando la descrizione di questo metodo che a livello di codice avr`a il seguente contenuto: 1 public ActionResult ShoppingCartDetail () 2 { 3 ShoppingItemManager cartManager = new ShoppingItemManager (); 4 // Prelevo la lista dei prodotti aggiunti al carrello precedentemente salvati in sessione. 5 cartManager = (List <ShoppingItem >) Session["Products"]; 6 // La lista con i prodotti , se presenti , sara ’ il modello su cui la view attingera ’ i dati. 7 return View(cartManager); 8 } Analogamente all’operazione di ricerca, il meccanismo con cui verranno visualizzati i prodotti presenti nel carrello utilizzer`a due view: la prima, chiamata ShoppingCart- Detail.cshtml, sar`a la pagina visualizzata all’utente che per ogni prodotto presente nel carrello far`a riferimento alla seconda pagina, ShoppingCartItem.cshmtl, in cui `e presente la struttura delle diverse righe che andranno a rappresentare i dati della tabella. A tal proposito mostriamo le due porzioni di codice coinvolte e la pagina ottenuta: 1 <!-- ShoppingCartDetail --> 2 3 <div class="ser"> 4 <div class="col -sm -8"> 5 @foreach (var item in Model) 6 { 7 <table class="table"> 8 @**@ 9 @Html.EditorFor(m => item , " ShoppingCartItem ") 10 </table > 11 } 12 </div > 1 <!-- ShoppingCartItem --> 2 3 <tr > 4 <td colspan="2">@Html.DisplayFor(m => m.P.Nome) </td > 5 <td > @Html.DisplayFor(m => m.P.Prezzo) </td > 6 <td > @Html.DisplayFor(m => m. QuantitaSelezionata ) </td > 7 </tr >
  • 44. 44 CAPITOLO 3. IL CONTESTO APPLICATIVO Figura 3.4: Un esempio di carrello contenente due prodotti. Oltre alla visualizzazione, l’applicazione offre anche al possibilit`a di rimuovere i prodotti mediante la pressione del tasto Rimuovi presente per ogni elemento. Ta- le operazione `e implementata passando al controller OrderController l’oggetto di tipo ShoppingItem rappresentante il singolo prodotto da eliminare. L’operazione di rimozione eseguita dal metodo RemoveShoppingCartitem, implementato sempre all’interno del controller in questione, ricercher`a tutti gli elementi il cui codice iden- tificativo `e uguale a quello del prodotto passato come parametro per poi rimuoverli. Fatto questo, l’applicazione sostituir`a alla variabile di sessione Products rappresen- tante i prodotti nel carrello una nuova lista senza l’elemento appena rimosso. Il codice relativo a questa operazione `e il seguente: 1 2 public ActionResult RemoveCartItem (ShoppingItem itemToRemove) 3 { 4 /* Prelevo la lista attuale dei prodotti nel carrello.*/ 5 List <ShoppingItem > items = (List <ShoppingItem >) Session["Products"]; 6 /* Rimuovo i prodotti il cui identificativo coincide con quello del prodotto da eliminare */ 7 items.RemoveAll(item => item.P.ProductID == itemToRemove.P.ProductID); 8 /* Rimuovo la variabile di sessione Products */ 9 Session.Remove("Products"); 10 /* Associo alla variabile di sessione Products la lista aggiornata */ 11 Session["Products"] = items; 12 13 /* Visualizzo nuovamente la pagina relativa al carrello dei prodotti */ 14 return RedirectToAction (" ShoppingCartDetail ", "Order"); 15 } Per prelevare tutti i prodotti con un determinato codice identificativo, si `e uti- lizzato un componente del framework .NET chiamato LINQ(Language Integrated Query). Esso estende il linguaggio C aggiungendo la maggior parte degli operatori
  • 45. 3.3. LA SOLUZIONE MONOLITICA 45 SQL con la possibilit`a di essere utilizzati sia per operare su collezioni di oggetti che su database. Nel caso del codice mostrato si `e utilizzata la prima possibilit`a d’uso, eseguendo all’interno della lista items una query traducidibile come: 1 DELETE 2 FROM items 3 WHERE P.IDProdotto = itemToRemove.P.IDProdotto 3.3.8 Finalizzazione dell’acquisto Partendo dalla visualizzazione del carrello del prodotto, l’utente potr`a cliccare sul tasto Procedi all’acquisto che finalizzer`a appunto l’operazione gestita dal metodo Checkout appartenente al controller OrderController. La struttura di questa opera- zione `e composta da diverse fasi: innazitutto, l’applicazione dovr`a accertarsi che i prodotti siano ancora disponibili, e per farlo richiamer`a la stored procedure Check- ProductAvailabilityProcedure passandogli come input una User Defined Table for- mata da due attributi che indicano i codici identificativi dei prodotti da acquistare con la loro quantit`a. Tale procedura effettuer`a poi un’operazione di JOIN avendo come condizione l’uguaglianza dei codici dei prodotti, verificando successivamente che la loro quantit`a sia maggiore di quella richiesta dall’utente. Nello specifico, la procedura descritta `e la seguente: 1 2 -- Creazione della User Data Table (udt) che conterra ’ i codici dei prodotti forniti in input con la loro quantita ’. 3 CREATE type dbo.Product AS TABLE 4 ( 5 ProductID INT , 6 Quantity INT 7 ) 8 GO 9 10 -- Creazione della procedura ha come parametro di input la UDT appena descritta e come 11 -- parametro di output l’esito dell ’operazione 12 CREATE PROCEDURE dbo. proc_CheckProductAvailability 13 @Products AS dbo.Product READONLY , 14 @ProductsAreAvailable BIT = 0 OUT 15 AS 16 BEGIN 17 18 -- Se il numero di righe della UDT e’ 19 -- uguale a quelle della tabella su cui e’ stata fatta l’operazione di join , allora 20 -- verra ’ assegnato 1 al parametro di output , altrimenti 0 poiche ’ alcuni dei prodotti acquistati 21 -- non sono disponibili. 22 23 -- COUNT (1) ha lo stesso valore semantico di COUNT (*).
  • 46. 46 CAPITOLO 3. IL CONTESTO APPLICATIVO 24 SELECT @ProductsAreAvailable = CASE WHEN COUNT (1) = COUNT(p.ProductID) THEN 1 25 ELSE 0 END 26 FROM @Products p 27 JOIN dbo.Product p1 28 ON p.ProductID = p1.ProductID 29 WHERE p1.Quantity < p.Quantity; 30 31 END 32 33 GO All’interno della procedura appena descritta si pu`o notare, oltre all’utilizzo della UDT, la presenza di un parametro di output chiamato ProductsAreAvailable, con- traddistinto dal fatto che sia seguito dalla parola chiave OUT. Per quanto riguarda la comunicazione tra la procedura e l’applicazione, Entity Framework offre la possibi- lit`a di creare delle classi che rappresentano le stored procedure in locale precedendole con una data annotation chiamata StoredProcedure. Vediamo a tal proposito le classi create per eseguire la procedura esaminata precedentemente: 1 2 /* Definizione della classe rappresentante la stored procedure */ 3 [ StoredProcedure (" proc_CheckProductAvailability ")] 4 public class CheckProductAvailabilityProcedure 5 { 6 /* 7 Dichiarazione dei parametri della procedura in cui , mediante data annotation , viene specificato 8 il tipo e il nome che deve essere identico a quanto definito nel database. 9 */ 10 [ StoredProcedureParameter (SqlDbType.Udt , ParameterName = "Products")] 11 public List <UdtProduct > Products { get; set; } 12 13 [ StoredProcedureParameter (SqlDbType.Bit , Direction = ParameterDirection .Output)] 14 public bool ProductsAreAvailable { get; set; } 15 } 16 17 /* 18 Definizione di un oggetto rappresentante lo schema della UDT 19 */ 20 [ UserDefinedTableType ("Products")] 21 public class UdtProduct 22 { 23 /* 24 Dichiarazione degli attributi della UDT con il rispettivo numero di colonna. 25 */ 26 [ UserDefinedTableTypeColumn (1)]
  • 47. 3.3. LA SOLUZIONE MONOLITICA 47 27 public int ProductID { get; set; } 28 29 [ UserDefinedTableTypeColumn (2)] 30 public int Quantity { get; set; } 31 } Queste classi verranno successivamente utilizzate all’interno del metodo Checkout per richiamare la stored procedure in questione passandogli come parametro la UDT mappata nel seguente modo: 1 2 /* Partendo gia ’ dalla lista degli elementi del carrello presente 3 all ’interno di listaProdottiPrelevati , viene istanziato un nuovo oggetto 4 assegnando all ’attributo rappresentante la UDT la lista dei prodotti. */ 5 6 var proc = new CheckProductAvaiabilityProcedure () 7 { 8 Prodotti = retrievedProductList 9 }; 10 11 /* Utilizzo di Entity Framework per eseguire la stored procedure prelevando 12 tutte le sue informazioni dall ’oggetto proc appena istanziato */ 13 dbManager.GetDBManager ().Database. ExecuteStoredProcedure (proc); 14 15 /* Prelevo il valore del parametro di output presente all ’interno della stored 16 procedure facendo sempre riferimento all ’oggetto che la rappresenta da codice */ 17 bool areProductsAvailable = proc. ProductsAreAvailable ; In caso di disponibilit`a dei prodotti, l’operazione passer`a alla seconda fase in cui verr`a effettuato l’acquisto vero e proprio, riducendo la quantit`a dei prodotti selezio- nati dal database. Questa operazione `e effettuata sulla linea di quella precedente utilizzando una stored procedure che, ricevendo come parametro una UDT, eseguir`a un’operazione di join con i prodotti presenti su database in base al codice del pro- dotto, riducendone la loro quantit`a. Per tale motivo, mostreremo solo la stored procedure adibita a finalizzare l’acquisto, chiamata procCreateOrder: 1 ALTER PROCEDURE proc_CreateOrder 2 @OrderData AS dbo.OrderData READONLY , 3 @Success BIT = 0 OUT , 4 @Products AS dbo.Products READONLY , 5 @OrderID INT = 0 OUT 6 AS 7 BEGIN 8 DECLARE @OrderTemp TABLE (ID INT) 9 DECLARE @TotalAmount DECIMAL (8,2)
  • 48. 48 CAPITOLO 3. IL CONTESTO APPLICATIVO 10 -- Creazione dell ’ordine generale in cui verranno inserite le generalita ’ di spedizione 11 INSERT INTO dbo. SalesOrderHeader (BuyerID , OrderDate , DeliveryDate , Status , TotalAmount) 12 OUTPUT inserted.OrderID INTO @OrderTemp 13 SELECT BuyerID , GETDATE (), GETDATE (), 1, SubAmount 14 FROM @OrderData 15 16 SET @Success = 1; 17 SELECT @OrderID = ID FROM @OrderTemp; 18 19 -- Creazione del dettaglio dell ’ordine in cui verranno inseriti i prodotti , con le loro quantita ’ e prezzi , 20 -- relativi all ’ordine vero e proprio. 21 INSERT INTO dbo. SalesOrderDetail (OrderID , Quantity , Quantity , Price) 22 SELECT t.ID , p.ProductID , p.Quantity , p.Price 23 FROM @Products AS p, @OrderTemp t 24 25 -- Aggiornamento delle quantita ’ dei prodotti in base a quelli acquistati. 26 UPDATE dbo.Product 27 SET Quantita = Quantity - q.Quantity 28 FROM (SELECT Quantity FROM [@Products ]) AS q 29 WHERE ProductID = (SELECT ProductID FROM @Products) 30 END In caso di esito positivo della procedura si passer`a alla terza e ultima fase del processo di acquisto in cui viene generato il PDF che sar`a una sorta di fac-simile di una fattura in cui saranno presenti tutte le informazioni relative ai prodotti ac- quistati e alla compravendita in se. La sua creazione `e gestita da un componente View Model chiamato PdfViewModel, composto dal solo metodo createOrderSeal. Esso, prendendo come parametri di input la lista dei prodotti nel carrello e le infor- mazioni ottenute dalla stored procedure precedente, utilizzer`a le classi appartenenti alla libreria iTextSharp[6] per creare il PDF che a fine operazione verr`a salvato nel- la tabella SealOrderHeader attraverso un’operazione di UPDATE racchiusa in una stored procedure dedicata. Conclusa l’operazione, l’applicazione canceller`a dalla sessione i prodotti acqui- stati e reindirizzer`a l’utente alla pagina contenente il suo pannello di controllo. 3.3.9 Accesso al sistema La funzionalit`a di accesso al sistema `e raggiungibile mediante il pattern di routing /Customer/Login. Al suo interno, la pagina visualizzata `e la seguente:
  • 49. 3.3. LA SOLUZIONE MONOLITICA 49 Figura 3.5: Pagina di login dell’applicazione Come si pu`o vedere, la pagina si compone di due soli campi utilizzati per inserire rispettivamente l’indirizzo email e la sua password. Alla pressione del tasto Accedi, l’applicazione richiamer`a il metodo CheckLoggingCustomer del controller Customer- Controller, il quale a sua volta richiamer`a la stored procedure Login, passandogli come parametri di input l’email e la password inserite. La procedura in questione che verr`a eseguita su database `e la seguente: 1 CREATE PROCEDURE Login 2 @Email VARCHAR (50) , 3 @Password VARCHAR (50) , 4 @Success BIT = 0 OUTPUT , 5 @SessionToken UNIQUEIDENTIFIER = 0 OUTPUT , 6 @PolicyID TINYINT = 0 OUTPUT , 7 @CustomerID INT = 0 OUTPUT 8 9 AS 10 BEGIN 11 -- Se email e password coincidono , viene impostata la variabile Success ad 1 12 -- come avvenuta operazione. 13 SELECT @Success = 1, @CustomerID = IDCliente , @PolicyID = PolicyID 14 FROM dbo.Customer 15 WHERE Email = @Email AND Psw = @Password 16 17 -- Se l’utente e’ presente , viene generato il token di sessione ed assegnato al parametro 18 -- di output. 19 20 IF @Success = 1 21 UPDATE dbo.Customer 22 SET SessionToken = NEWID (), 23 @SessionToken = SessionToken 24 WHERE CustomerID = @CustomerID 25 ELSE 26 27 END In caso di accesso riuscito, il metodo salver`a nella sessione dell’utente due varia- bili chiamate CustomerID e SessionToken, indicanti rispettivamente l’identificativo