Sistemi di database relazionali -Introduzione ............................................................................................................................................ Evoluzione dei sistemi di database ....................................................................................................... Il modello relazionale ............................................................................................................................. Prospettiva storica .............................................................................................................................. Concetti fondamentali ......................................................................................................................... Elementi costitutivi ............................................................................................................................. Progetto di database relazionali .............................................................................................................. Introduzione ...................................................................................................................................... Sviluppo concettuale ........................................................................................................................... Il Modello ER ...................................................................................................................................... Implementazione del modello relazionale ............................................................................................. Architetture Client/Server ....................................................................................................................... Introduzione ...................................................................................................................................... Architetture C/S ad 3 strati.................................................................................................................. Proposta per un modello di sviluppo applicativo ....................................................................................... Uso di convenzioni di denominazione ................................................................................................... Lavorazione in cascata o prototipale ciclica .......................................................................................... Bibliografia ............................................................................................................................................ Introduzione Non è superfluo ricordare che i sistemi di database sono stati sviluppati per uno scopo che è essenzialmente quello di semplificare lo sviluppo di applicazioni che fanno uso intensivo di dati di tipo strutturato, cioè dati che hanno per natura una struttura in qualche modo ripetitiva. Infatti, nel caso migliore un sistema di database può eliminare intere fasi di sviluppo dato che fornisce una interfaccia semplice ed immediatamente funzionante per la visualizzazione e la modifica dei dati in esso contenuti. In genere maggiore è la parte di elaborazione che si riesce a demandare al database, minore sarà il codice che è necessario sviluppare. Esiste anche il rovescio della medaglia: funzionalità non richieste dal progetto iniziale possono ridurre le prestazioni del sistema senza ragione, e possono rendere il sistema più difficile da capire. Di conseguenza è necessario considerare attentamente quali funzionalità sono necessarie alle applicazioni di destinazione, e come realizzare al meglio le caratteristiche del sistema di database da proporre al programmatore. Evoluzione dei sistemi di database I sistemi per la gestione delle informazioni sono evoluti nel tempo attraverso tre grandi categorie. data management strutture dati semplici ed operazioni semplici (database relazionali) object management strutture dati astratte ed operazioni relative (database ad oggetti) knowledge management sistemi di memorizzazione di informazioni e di regole non strutturate (intelligenza artificiale) In questo documento si porrà l’ attenzione soltanto sulla prima di esse, ed in particolare su un solo tipo di architettura che è quella relazionale. Come si vedrà in seguito tale architettura abbina le caratteristiche di facilità d’ uso e potenza. Non è un caso che tutti gli sviluppi futuri del data management, cioè l’ object management partono invariabilmente da qui. Inoltre le nuove tecnologie di database ad oggetti nascono per risolvere specifiche categorie di problemi per i quali l’ architettura tradizionale è insufficiente. Ciò non toglie perciò che la tradizionale architettura relazionale continui ad essere la migliore soluzione per tutti quei casi di gestione di informazioni semplici, ossia costituite essenzialmente, anche se non esclusivamente, da testo e numeri. Di seguito si descrivono tre modelli relazionali fondamentali, ciascuno dei dei quali è costituito dalla coppia di dato e schema, ove lo schema è un metadato che descrive la struttura dei dati, mentre il dato è lo scopo stesso del sistema. Modello relazionale - RDBMS Il modello relazionale è il primo modello per importanza, a causa della sua diffusione. Inizialmente fu proposto da Codd nel 1970 e successivamente modificato da Date. Deve il suo successo alla semplicità, essendo costituito da una sola struttura dati, la tabella, che contiene tipi di dati semplici (numeri, lettere, ecc.). Il linguaggio di manipolazione del database è costituito da poche istruzioni, e non c’ è il bisogno che esso sia conosciuto dall’ utente del database (QBE). Modello relazionale esteso - ERDBMS Le limitazioni sul tipo di dato che il modello relazionale è in grado di trattare hanno reso necessario lo sviluppo di alcune estensioni, riunite sotto la definizione generica di modello esteso relazionale. Si tratta essenzialmente del modello relazionale ove si aggiunge la possibilità di memorizzare anche dati di tipo oggetto. E’ esclusa o molto ridotta la capacità di manipolare gli oggetti memorizzati, come la capacità di fare confronti, operazioni, ecc. Modello ad oggetti - ODMS Sono sistemi di database basati su un modello astratto dei dati, originato dal paradigma della programmazione ad oggetti nata con prodotti come Simula, SmallTalk e successivamente C++. Questi linguaggi di programmazione sono basati sul concetto di tipo di dati astratto, che è costituito da una interfaccia che definisce in modo esplicito una porzione pubblica ed una porzione privata all’ interno di una struttura dati, detta oggetto. Questo tipo di dati astratto, detto classe, può incapsulare alcune parti della struttura dati privata dell’ oggetto tramite procedure pubbliche dette metodi, ed espone la parte pubblica tramite delle variabili dette proprietà. Il modello relazionale Prospettiva storica La tecnologia dei database si è evoluta fin dall’ inizio nello sviluppo di applicazioni di gesitione aziendale, probabilmente a causa del fatto che lo sviluppo di simili applicazioni ha alle spalle adeguati investimenti, ed ha la necessità di manipolare grandi quantità di dati. La prima soluzione è stata quella dei file indicizzati. Questi file consentivano la memorizzazione su disco e la ricerca di records di vario tipo. Le caratteristiche avanzate dei file ad indici hanno nel tempo costituito le caratteristiche di base dei sistemi di database relazionali. Esse sono_ 1. 1. record di lunghezza fissa con campi di tipo differente all’ interno 2. 2. capacità di memorizzare su disco le informazioni, e di manipolare quantità di dati più grandi della dimensione fisica della memoria disponibile 3. 3. indicizzazione di campi e gruppi di campi per la ricerca e selezione rapida di valori che soddisfano a condizioni fissate sul valore dei campi 4. 4. blocco di file e record, per la gestione dell’ accesso concorrente ai dati Negli anni 70 fu sviluppato il primo sistema di database che usava un modello gerarchico e distribuito dei dati, che otteneva le caratteristiche dette prima insieme ad altre nuove: 5. 5. uso di identificatori di record e di campi di collegamento in grado di realizzare l’ associazione tra dati all’ interno di una rete di computer 6. 6. apertura simultanea di più file indicizzati e collegati da trattare come singolo database 7. 7. vincoli di protezione per consentire o no l’ accesso alle informazioni 8. 8. gestione delle transazioni al sicuro dai crash di sistema, controllo degli errori e della consistenza del database Negli anno 80 fu sviluppato e messo in commercio il primo sistema di database relazionale, che agguingeva altre caratteristiche: 9. 9. linguaggio di alto livello interno con la possibilità di definire modificare e manipolare i dati, insieme a tool di alto livello per lo sviluppo di form, report ed altri elementi per il trattamento delle informazioni 10. 10. indipendenza dai dati, ossia capacità del database di cambiare il modo di memorizzare i dati senza che si debba cambiare la logica delle applicazioni che li manipolano. Il più grande contributo dato dal modello relazionale è stato quello di rendere più semplice da comprendere le strutture dei dati rispetto anche ai sistemi di potenza inferiore. Questa semplicità è dovuta essenzialmente all’ introduzione di pochi concetti come relazioni, query e transazioni, che hanno liberato il programmatore dal lavoro riguardante i dettagli fisici della memorizzazione della informazioni, inclusi i problemi riguardanti la gestione degli errori, la multiutenza, l’ organizzazione dei dati. Molto importante è risultato anche il discreto grado di standardizzazione introdotto dall’ SQL, sia nella manipolazione delle informazioni, che nei meccanismi di indipendenza dai dati delle applicazioni. Le 10 caratteristiche elencate di sopra costituiscono le caratteristiche di massima di qualsiasi sistema di database. Naturalmente ciascun prodotto di questa categoria può singolarmante disporre di ulteriori funzionalità. Essi spaziano infatti attraverso il vasto settore delle applicazioni gestionali, dalla semplice rubrica degli indirizzi fino al sistema di transazioni su larga scala. Concetti fondamentali L’ architettura a tre livelli del modello relazionale Un sistema di database è tipicamente costituito dai seguenti livelli costitutivi distinti: Interno tutto quello che riguarda l’ organizzazione interna dei campi, record, indici, sistemi di accesso, codifica, lettura e scrittura dei dati sul corrispondente media di destinazione. Concettuale tutto ciò che riguarda il tipo dei campi e record, o le relazioni tra di essi. Esterno l’ interpretazione dei dati fornita dal’ applicazione che li utilizza - che può presentare ulteriori vincoli per i dati i tipi. Questo schema è noto come architettura a tre livelli di un sistema di database. In alcuni casi qui o altrove è possibile trovare riferimenti ad una struttura semplificata che include solo due livelli disitinti tra: 1. 1. Fisico (interno) 2. 2. Logico (concettuale ed esterno) L’ architettura a tre strati di un sistema di databaase ha profonde ripercussioni sul successivo argomento delle Architetture Client/Server. Indipendenza dai dati Una caratteristica molto importante dei sistemi di database è l’ indipendenza dai dati, che consente di modificare l’ organizzazione di questi senza che tali modifiche disturbino il funzionamento dei programmi di manipolazione. In una architettura a tre livelli questa indipendenza esiste sia al livello interno che concettuale. Indipendenza fisica-è l’ abilità di cambiare l’ organizzazione interna dei dati (ad es. indici, formati) senza influire sui programmi di manipolazione. Corrisponde all’ indipendenza sia sul piano fisico che concettuale. Indipendenza logica-è l’abilità di modificare lo schema strutturale dei dati (ad es. aggiungere campi, relazioni), senza modificare le applicazioni. Corrisponde ai livelli concettuale ed esterno. Sistema di sicurezza Si presenta spesso il problema di amministrare i livelli interno e concettuale di un sistema di database, e qualche volta anche quello esterno. Questo perché bisogna coordinare le modifiche effettuate dalle varie persone coinvolte nello sviluppo del sistema sia al livello fisico che logico. In genere questo problema si risolve creando la figura di un amministratore di database, essenzialmente responsabile del mantenimento delle strutture sia interne che esterne del sistema di database. Per estensione ci si rende conto che esistono essenzialmente tre figure di utenti del sistema di database: 1. 1. Amministratore: responsabile del livello fisico del sistema e coordinatore delle azioni di modifica in quell’ ambito 2. 2. Programmatore: responsabile del livello esterno 3. 3. Utente finale: tutti coloro che fanno qualcosa di utile tramite gli strumenti creati dalle due figure precedenti Elementi costitutivi Tabelle La tabella è l’ ingrediente di base di qualsiasi sistema di database. Essa è costituita da righe (dette anche record o n-ple) e da colonne (dette anche campi o attributi). E’ quindi una struttura dati rettangolare di tipo NxM senza particolari vincoli posti per le dimensioni di M o N, a parte quelli imposti dalla potenza del sistema hardware che ospita i dati. La differenza fondamentale tra M ed N esiste, però, ed è quella che la modifica del numero di colonne avviene piuttosto raramente ed è compito dell’ Amministratore del sistema di database, mentre il numero di righe viene continuamente variato dagli utenti del sistema. E’ evidente come la variazione del numero di colonne ha luogo nello strato fisico e concettuale, mentre la variazione del numero di righe ha luogo nello strato esterno. Chiavi primarie e chiavi straniere Un sistema di database relazionale è quindi composto da un insieme di tabelle. All’ interno di queste vengono definiti i campi (o attributi, n-ple), i quali sono destinati ad ospitare campi di natura omogenea. All’ interno di un certo campo può essere contenuto un solo tipo di dato. Per ottenere il risultato che ci poniamo, è quasi sempre necessario fare uso di più campi di tipo differente. Ma la differenza fondamentale tra i vari campi non è nel tipo, che pure rappresenta già una grande differenza, ma nel ruolo del campo. D’ altra parte è chiaro già dall’ espressione che è stata usata: tipo, cioè attributo-ed un campo è di per sé un attributo del record, almeno secondo la terminologia usata sopra-e ruolo, cioè compito svolto all’ interno non del record ma dell’insieme di tabelle che costituisce il sistema di database relazionale. Esistono tre ruoli possibili per un campo che passiamo subito a precisare: 1. 1. ruolo banale, notabilmente quello di attributo 2. 2. chiave primaria, è un campo o un gruppo di campi il cui valore deve essere unico tra le righe di una tabella 3. 3. chiave straniera, è un campo o un gruppo di campi che assume un valore scelto tra quelli contenuti in una tabella scelta in un particolare gruppo di tabelle dette tabelle entità. Riassumendo il ruolo della chiave primaria sarà quello di identificare univocamente tutte le righe di una tabella, stabilendo una corrispondenza biunivoca tra i valori assunti dalla chiave primaria e le righe della tabella, mentre il ruolo della chiave straniera è quello di ospitare valori ricevuti dalla chiave primaria di una qualche tabella. Va notato quindi che il modello relazionale non consente righe duplicate all’ interno di una relazione, ossia due record non possono essere identici in tutti i loro attributi. Inoltre ogni relazione ha una chiave primaria nel senso stretto, costituita da tutti i campi della relazione. Questa forma degenerata di chiave primaria non ha nessun tipo di utilità, per cui di seguito fisseremo l’ attenzione solo su chiavi primarie semplici, cioè costituite da uno, al massimo due campi di una data tabella. Tabelle entità e tabelle associazione A seguito della distinsione tra chiavi primarie e straniere, le tabelle si dividono tra tabelle entità e tabelle associazione. Le tabelle entità rappresentano oggetti del mondo reale che vogliamo caratterizzare con dei campi o attributi. Ogni record della tabella entità rappresenta dunque uno ed uno solo di questi oggetti del mondo reale. Le tabelle associazione servono invece per rappresentare le relazioni che intercorrono tra oggetti di tipo diverso contenuti nel sistema di database relazionale. Per quanto detto sopra essi sono contenuti in differenti tabelle entità. Per estensione, dunque, le tabelle associazione servono in qualche modo a memorizzare la relazione esistente tra due oggetti diversi, contenuti nel nostro sistema. Bisogna dire però che non tutte le relazioni richiedono tabelle associazione. Infatti è possibile e anzi capita molto di frequente di realizzare relazioni aggiungendo una o più chiavi straniere in una tabella entità. Tali relazioni uno ad uno ed uno a molti sono dette relazione dirette, per distinguerle da quelle indirette molti a molti che necessitano di una o più tabelle associazione, come vedremo più oltre. Dominio dei valori ed Integrità referenziale Se dal punto di vista teorico il concetto di relazione è un concetto chiave per la teoria dei sistemi di database relazionale, dal punto di vista pratico quello di integrità referenziale ha lo stesso tipo di importanza. Il motore del database, negli strati interno e concettuale, effettua dei controlli sui dati immessi all’ interno dei campi. Come abbiamo detto precedentemente lo spostamento di compiti dallo strato esterno verso strati via via più interni dell’ architettura a tre livelli, semplifica il lavoro di sviluppo dei programmi, ossia lo scopo ultimo della nostra attività. Maggiore è la quantità dei controlli sui dati che spostiamo dall’ esterno all’interno, maggiore sarà la semplificazione che otteniamo. Due compiti essenziali del nostro motore sono dunque i seguenti: 1. 1. verificare la correttezza delle chiavi straniere, e gestire le corrispondenti eccezzionicontrollo di integrità referenziale 2. 2. verificare l’ appartenenza degli attributi ai corrispondenti insieme di valori-controllo di validità L’ integrità referenziale è un insieme di vincoli che vengono fissati sulle chiavi straniere: una chiave straniera contenuta in una tabella deve ospitare solo i valori contenuti nella corrispondente tabella entità. Tolgliendo questo vincolo il database non è più relazionale, anche se resta un sistema di database. La validità dei dati corrisponde in ultima analisi alla validità del tipo, più la validità del valore assunto. Tanto per fare un esempio nel campo ‘data_nascita’ di un ufficio anagrafico non deve essere possibile inserire il valore ‘Giuseppe Aielli’, e, una volta che ci si decide di inserire una data, non deve essere possibile inserire ‘300 a.C.’, ma solo una data successiva ad es. a ‘01-01-1850’. E’ da notare come, se noi togliamo questo secondo tipo di controllo dal nostro sistema di database, esso non è più un sistema di database, essendo degenerato in un archivio puro e semplice, cioè un insieme di file ed indici. Normalizzazione Buona parte del lavoro di ricerca svolto negli anni 80 a proposito dei sistemi di database relazionale fu svolto sul concetto di normalizzazione relazionale. Come abbiamo visto nel caso precedente un sistema di database relazionale può degenerare fino al ruolo di sistema di file ed indici, semplicemente per nostra scelta o ignoranza. Questo significa che un sistema di database relazionale non è in grado da solo di svolgere il compito di ottimizzare il suo funzionamento più esterno. Un passo di importanza fondamentale da compiere verso la creazione di un database relazionale è quindi quello di normalizzare il suo schema, cioè quello di ottenere la migliore rappresentazione concettuale possibile dei dati, sotto forma di tabelle entità, associazioni e relazioni. L’ essenza della normalizzazione, che si vedrà in dettaglio più avanti, è quella di dividere i dati contenuti in tabelle con tante colonne, in più tabelle ciascuna con un numero di colonne inferiore. Questo diventa necessario quando troppe informazioni sono rappresentate in una sola tabella, quando la rappresentazione dei dati può portare confusione, quando la stessa informazione è presente in più posti differenti, oppure quando le informazioni sono male associate tra loro. Si noti come ad esempio la duplicazione di una stessa informazione all’ interno di un sistema di database conduce come conseguenza più immediata ad un potenziale conflitto tra le due fonti, ed ad uno spreco di spazio e di risorse. Per fortuna sono state definite una serie di regole formali dette forme normali, col lo scopo di eliminare problemi ed errori nella definizione dello schema. Tali forme normali, per la loro estrema importanza, saranno oggetto di trattazione successiva. Proprietà delle tabelle Il modello relazionale deriva molta della sua semplicità da tre proprietà delle tabelle: 1. 1. le tabelle sono insiemi nel senso matematico: le righe sono uniche e non sono ordinate 2. 2. gli attributi non sono ordinati: si indicano col nome, ed il nome deve essere unico all’ interno di una tabella 3. 3. i valori assunti dai campi sono atomici: un campo non può contenere al suo interno un insieme (I forma normale). Proprio a causa della matemeticità del modello relazionale è stata possibile la realizzazione di motori di database relazionali in grado di assolvere in modo efficiente al compito di memorizzare ed elaborare le informazioni. Questo ultimo compito viene poi svolto in modo elegante dalla formulazione di un semplice linguaggio di interrogazione, l’ SQL. Accesso concorrente e recupero Introduzione Controllo dell’ accesso concorrente e recupero sono due caratteristiche molto importanti per un sistema di database relazionale. Esse contribuiscono a mantenere l’ integrità logica e fisica di un database, rispettivamente. Il recupero di un sistema di database relazionale consiste nella capacità di ripristinare il funzionamento dopo un errore grave del sistema. Molte sono le ragioni che possono condurre ad un crash di sistema, e non è il caso di analizzarle in questa sede. Preso atto di questa eventualità e del fatto che i sistemi di database relazionale sono particolarmente delicati a causa della loro natura estremamente precisa, è necessario attuare essenzialmente due politiche: 1. 1. backup dei dati sistematico ed affidabile 2. 2. uso delle transazioni, se supportate dal sistema. Sul primo rimedio niente da dire. Il secondo consiste nella capacità del sistema di database relazionale di effettuare le operazioni a blocchi. Per cui se non si riesce ad effettuare tutto il blocco di operazioni, allora le operazioni saranno annullate per tutto il blocco corrente, ripristinando la situazione esistente prima di effettuare la transazione. Il controllo di concorrenza, invece, si occupa della gestione degli aggiornamenti e modifiche dei dati da parte di molti utenti contemporaneamente, tramite il meccanismo del blocco dei dati. Nel caso più semplice si tratta di porre un blocco esclusivo per il numero di record coinvolti da una certa operazione, da parte di un certo utente: tutti gli altri utenti non saranno in grado di modificare i record bloccati fino al termine di quella operazione. Esistono due tipi di blocco: Fisico: avviene in modo esplicito a livello di record, di pagina o di tabella Logico: è definito da una espressione in una query che definisce un set di record da bloccare Il tipo di blocco utile per una certa operazione dipende da questa nel seguente modo: 1. il blocco di una intera tabella è quello più efficiente dal punto di vista computazionale, ma comporta la minore flessibilità possibile, perchè solo un utente alla volta può modificare i dati contenuti nella tabella 2. 2. il blocco di un singolo record è il meno efficace dal punto di vista computazionale, ma il più flessibile per l’ uso 3. 3. il blocco di una pagina rappresenta una scelta vantaggiosa dal punto di vista computazionale, senza sacrificare quasi nulla della flessibilità del sistema, dal momento che i record sono registrati sul disco sotto forma di pagine fisiche costituite da più record alla volta. Il blocco dei record può condurre a situazioni di errore, laddove due o più utenti richiedano sistematicamente il blocco di un certo record o di una certa pagina: l’ utente A potrebbe attendere che B rilasci una certa pagina e viceversa. Questa è detta situazione di deadlock. 1. Transazioni Molti sistemi di database relazionale implementano meccanismi di transazione, che provvedono contemporaneamente al recupero ed al blocco delle informazioni. Il nome di transazione proviene probabilmente dall’ esempio classico in letteratura che viene di seguito riproposto: bisogna trasferire una somma da un conto di un certo cliente a quello di un certo fornitore-si tratta di una transazione anche nel linguaggio bancario commerciale. In che modo il sistema di database realizza tale tipo di operazione? Il sistema è in uno stato consistente all’ inizio ed alla fine della operazione, il che vuol dire che i due stati iniziali e finali sono coerenti con la realtà dei fatti, anche se può esserci inconsistenza per brevi (ed invisibili) istanti durante l’operazione, per esempio quando il conto del cliente è stato già addebitato e quello del fornitore non è stato ancora accreditato. Per chi pensa che la soluzione sia di eseguire contemporaneamente le due operazioni bisogna tenere conto che in primo luogo non è possibile eseguire due operazioni contemporaneamente sulla stessa macchina a causa della natura essenzialmente seriale di questa, ed in secondo luogo, se anche fosse, non si avrebbe la garanzia che le operazioni vengano entrambe eseguite correttamente. La soluzione consiste quindi nel rendere le due operazioni una sola operazione logica, detta transazione. La transazione sarà completata solo quando entrambe le operazioni sono entrambe completate correttamente. In caso contrario sarà annullata l’ intera operazione. Le transazioni sono la migliore soluzione possibile al problema del controllo di accesso e della coerenza dei dati, perché l’ utente finale non deve avere a che fare con blocco, sblocco, backup ed altro. Nel campo dei sistemi di database relazionale l’ uso delle transazioni porta solo dei benefici e non è soggetta a nessuna limitazione, senza contare che i meccanismi interni al motore che implementano le transazioni possono anche rendere più efficienti molte elaborazioni a causa della bufferizzazione delle operazioni che viene effettuata durante un ciclo di transazioni. Database distribuiti Il termine database distribuito viene usato di solito con vari significati differenti. Noi intendiamo per database distribuito un database che abbia almeno le due seguenti caratteristiche: possibilità di accesso da remoto e capacità di gestire un unico database suddiviso su più di una macchina. Accesso remoto La maggior parte dei sistemi di database supportano l’ accesso remoto. Ciò significa che l’ utente di un certo programma attinge o manipola dei dati che non risiedono sulla macchina che stà usando, ma su una macchina lontana che può trovarsi sulla sua stessa rete locale o anche su una rete differente. Il tutto senza che l’ utente possa percepire questo fatto, cioè come si dice in gergo, ‘in modo trasparente’. In altre parole egli ‘vede’ dati locali o remoti esattamente nello stesso modo, perché il software rende ‘invisibile’ il processo di comunicazione che avviene con la macchina lotana. Il meccanismo attraverso il quale un database riesce ad implementare questa funzionalità è molto semplice: solo una piccola parte del sistema di database relazionale risiede con il programma applicativo nella macchina dell’ utente, detta client. Questa porzione di applicazione è responsabile essenzialmente della visualizzazione dei dati e della codifica di query da inviare alla macchina remota, detta server, che gli restituisce poi i risultati sotto forma di record, sempre tramite la rete (locale o no) attraverso la quale aveva ricevuto le ‘richieste’. Esistono poi delle complicazioni addizionali dovute alla natura eterogenea di alcune reti, in particolar modo per quello che riguarda le reti basate su Internet. Attualmente una soluzione che ha preso molto piede consiste nell’ usare i meccanismi di comunicazione intrinseci di Internet per effettuare il dialogo detto prima: il client invia le richieste tramite meccanismi interni come il metodo POST o la posta elettronica (e-mail) e riceve le risposte direttamente in HTML dal server. Partizionamento Si definisce ‘database distribuito’ un insieme di database che appaiono all’ utente come un unico database. Nel caso più semplice i database possono essere su di una unica macchina e possono anche essere ridotti al numero di uno. In questo caso si parla di replicazione di database. Più in generale però si verifica il caso che i database risiedano su macchine differenti in quanto la caratteristica principale del partizionamento consiste nel voler distribuire il carico di lavoro tra differenti macchine server, con l’ evidente scopo di ottimizzare il processo complessivo. L’ evidente condizione per realizzare efficientemente il partizionamento di un database è: 1. 1. che vi sia un partizionamento logico dei dati, cioè che la suddivisione abbia senso dal punto di vista organizzativo prima ancora che tecnico 2. 2. che la necessità di comunicazione esistente tra le parti da separare sia piccola o nulla Mancare la prima condizione è un errore che porta confusione dello schema del database. A questo punto se anche vi fossero dei benefici dal punto di vista computazionalecomunicativo sicuramente si avranno svantaggi nello sviluppo dei programmi. Invece mancare la seconda condizione significa che se anche miglioriamo il processo dal punto di vista computazionale, sicuramente lo peggioriamo da quello della comunicazione, e quindi nel complesso non apportiamo miglioramenti molto significativi. Dentro le condizioni dette prima il partizionamento di un database: 1. 1. consente a ciascun reparto di organizzare in modo autonomo le strutture dei dati ed i meccanismi relativi al loro impiego 2. 2. consente ancora di effettuare query ed analisi su tutto il complesso dei dati ed in modo trasparente, con la gli stessi meccanismi e con la stessa semplicità di un sistema di database non partizionato. I database possono essere partizionati in una varietà di modi. Ricordiamo brevemente i principali: 1. 1. tabelle differenti in database differenti-partizionamento semplice 2. la stessa tabella separata in due o più database con alcune righe da una parte e le altre da un’ altra-partizionamento orizzontale 3. 3. la stessa tabella separata in due o più database con alcune colonne da una parte e le altre dall’ altra-partizionamento verticale 4. 4. la stessa tabella in più copie sincronizzate su macchine differenti-replica. 2. Progetto di database relazionali Introduzione Nell’ ambito dello sviluppo di applicazioni basate su database, il progetto dello schema riveste una importanza particolarmente vitale. Infatti da una parte risulta chiaro che questo è necessariamente il primo passo da compiere mentre dall’ altro ci si rende facilmente conto di due disastrose conseguenze: 1. 1. ogni errore compiuto nella fase di definizione dello schema ha ripercussioni sul funzionamento dell’ applicazione, ed ogni modifica dello schema ha la potenzialità di inficiarne il funzionamento 2. 2. più ci si spinge avanti nel lavoro di sviluppo più la struttura dati risulta essere inadeguata nel tempo a causa dell’ accrescimento conoscitivo delle tematiche che si verifica dalla prima stesura dello schema in poi. In questo capitolo vedremo come evitare il primo dei due problemi. Posto che il progetto accurato dello schema del database se non risolve del tutto almeno mitiga le conseguenze dette sopra, non esiste però una soluzione a portata di mano per il secondo dei due. Nel capitolo intitolato ‘Proposta per un modello di sviluppo applicativo’ si tenta di dare una possibile risposta a questo problema. Sviluppo concettuale Riguardo le tecniche di sviluppo e progettazione di un database, bisogna dire che la loro applicazione deve essere preceduta da una attenta analisi della realtà che si vuole modellare. E’ necessario evitare l’ errore molto comune che è quello di aver fretta di passare alla fase di sviluppo dell’ applicazione. Successivamente vengono spiegate delle tecniche che servono per abbreviare il percorso di sviluppo di una applicazione basata su database. Le spiegazioni sono piuttosto sintetiche e sono intese come guida di riferimento rapido per lo sviluppatore. Chiara determinazione della realtà da modellare La prima cosa da fare è chiaramente quella di farsi raccontare da qualcuno che cosa bisogna ottenere dal software che si desidera sviluppare. In questa fase probabilmente è necessario affiancare il personale della realtà in questione. In altri casi è probabile che il software venga sviluppato da noi per noi stessi. In ciascuna delle due ipotesi è necessario soffermarsi a ragionare su un concetto fondamentale: quasi sempre il nostro modo di lavorare non è sufficientemente generale da poter essere trasformato in programma. Ciò significa che il nostro modo di lavorare è troppo personale per poterlo proporre ad altri tramite il software che si intende scrivere, cosa che probabilmente determinerà l’ insuccesso del nostro software. D’ altra parte ricordatevi che buona parte del software che si scrive non è per nulla necessario agli utenti cui è destinato, ma solamente utile. Di conseguenza ricordatevi sempre di pensare le cose in generale e dall’ alto. In alternativa può accadere che la nostra sintesi della situazione sia un sottoinsieme di un problema più vasto e generale. Di conseguenza la nostra soluzione risulterà stretta, specie in un ambito multiutente, ove le necessità ed il modo di pensare le soluzioni varia da individuo ad individuo. Non esiste naturalmente un metodo su come descrivere in modo adeguato un problema senza essere né troppo generici né troppo vincolati da una soluzione stretta. Il buonsenso insegna che essere il più possibile metodici e non trascurare nessun dettaglio durante l’ interazione col personale responsabile della descrizione è un buon punto di partenza. Il resto lo farà naturalmente l’ esperienza. Successivamente alla descrizione ‘a parole’ della situazione di riferimento, è necessaria la scelta di un modello rappresentativo che consenta di modellare la realtà tramite un diagramma. Noi optiamo senza dubbio per il modello rappresentativo ER (entità-relazione). Il Modello ER Il modello ER fu proposto da Chen 1976. Esso è al contempo molto semplice e consente una rappresentazione espressiva delle realtà in esame. Inoltre, tramite un metodo assolutamente algoritmico è possibile passare con semplici passaggi da questo modello a quello relazionale descritto prima. In questa occasione bisogna citare il fatto che esistono in commercio prodotti software per il disegno dei diagrammi ER e la corrispondente trasformazione nel modello relazionale: ricordiamo Info Modeler, ER-Win, S-Designor, DBSee++ e Code Painter. Gli ultimi due sono prodotti che per la loro completezza ricadono nella catagoria dei CASE (acronimo di Computer Aided Software Design). Il modello ER è costituito soltanto da tre elementi: entità, relazioni ed attributi. Questi elementi vengono disposti su un diagramma seguendo questo criterio: le entità corrispondono ai nomi e vengono raffigurate con dei rettangoli, le relazioni corrispondono ai verbi e si raffigurano con dei rombi (o con degli ellissi). I rettangoli ed i rombi vengono collegati con delle linee. Tanto per fare un esempio la locuzione “i miei clienti pagano le fatture” ha una traduzione nel diagramma ER in: i miei clienti pagano le fatture Il metodo sotteso dall’ esempio precedente è piuttosto bruto, ma semplice da capire e funzionale. Passiamo ora in rassegna le caratteristiche essenziali degli elementi del diagramma ER: le entità sono gli elementi del modo reale, come le persone, le fatture o i prodotti. D’ altra parte ogni entità è costituita da una serie di attributi. Ad esempio i clienti hanno gli attributi di Nome, Cognome, Indirizzo, Città ed altri ancora, mentre le fatture hanno come attributi il Numero, la Data o l’ Importo. E’ importante capire che un attributo o un gruppo di attributi costituisce la chiave primaria di ogni entità. Non ripetiamo il significato dei termini già discussi in precedenza, ma ricordiamo solo che la chiave primaria esiste sempre ed è unica in ciascuna entità. Si tratta di sceglierla tra gli attributi posti, oppure di creare un nuovo attributo, tipicamente un codice identificativo. Una relazione, invece, è un legame di tipo logico che coinvolge due o più entità. Le relazioni hanno un unico attributo esplicito, la cardinalità. In generale la cardinalità indica il numero di entità dell’ insieme A che può essere associato ad ogni elemento di un insieme B. Prestare sempre attenzione alla cardinalità di una relazione che non è sempre semplice determinare. Ad esempio il matrimonio tra due individui, almeno nella società occidentale, ha una cardinalità 1:1, ma evidentemente può avere diversa cardinalità altrove. Sono moltissime le ambiguità che possono presentarsi nella decisione sulla cardinalità di una relazione. Sfruttare il modello ER evitando di ragionare in termini di modello relazionale durante la fase iniziale di sviluppo In generale non bisogna perdere di vista cosa deve fare la nostra applicazione a favore di come deve farlo. A questo scopo bisogna per prima cosa dedurre il diagramma ER completo in ogni sua parte e poi bisogna soffermarsi a lungo nel perfezionamento dello schema fino a quando non si è sicuri di essere il più vicini possibile alla perfezione. In generale da un diagramma ER ben fatto discende uno schema relazionale senza difetti. Uno schema relazionale senza difetti rappresenta la parte pricipale di qualunque applicazione. Esso consente in primo luogo la stesura immediata del programma applicativo. In seconda istanza facilita migliorie ed estensioni da fare in seguito sul programma stesso, oltre che sullo schema dei dati. Vediamo ora un algoritmo per la creazione dello schema relazionale a partire dal diagramma ER. sviluppo del modello ER primitivo: 1. 1. suddivisione del problema in domini 2. 2. individuazione delle entità 3. 3. individuazione delle relazioni 4. 4. definizione delle chiavi primarie e degli attributi principali. Riguardo al primo argomento esso consiste nel suddividere un problema complesso in più sottoproblemi di tipo semplice, da affrontare separatamente. Per quello che riguarda il secondo ed il terzo abbiamo già accennato un metodo che consiste nel trovare dai nostri appunti le entità individuando tutti i sostantivi, e le relazioni tutti i verbi del nostro discorso. Naturalmente è necessario individuare tutti quelli non pertinenti ed i sinonimi, ma alla fine il problema sarà quasi risolto. Volendo proseguire nella analogia gli aggettivi corrispondono agli attributi principali, mentre, per quello che riguarda le chiavi primarie il discorso è un po’ più complicato. Intanto sappiamo che la chiave primaria esiste di sicuro, ed è costituita dall’ unione di tutti gli attributi della nostra entità. A questo punto viene spontaneo di cercare la più piccola chiave primaria tra tutti gli attributi di una entità. Spesso è sufficiente un solo campo o due. Altre volte è necessario creare un campo apposito, ad esempio il ‘Codice’. In definitiva questa fase corrisponde nell’ individuazione di un elemento diversificatore tra gli elementi che partecipano alla nostra entità. Un esempio servirà per chiarire il tipo di percorso da fare. E’ evidente come il ‘Cognome’ di un cliente non sia di per sé sufficiente per essere primario. Anche l’ unione di ‘Cognome’ e ‘Nome’ non basta. Si potrebbe pensare di aggiungere la data di nascita, e a questo punto si ha molta probabilità che la somma di questi tre attributi identifichi in modo univoco una persona. In effetti però il ‘Codice_fiscale’ da solo, è già in grado di reggere il ruolo di chiave primaria. In alcuni casi però potrebbe non essere utile come dato, il ‘Codice_fiscale’, oppure potrebbe non essere sempre disponibile. In questo caso si potrebbe finalmente optare per un nuovo campo, ad esempio un ‘Contatore’ che assegna un numero intero diverso per ogni cliente. Completare il modello ER in ogni sua parte prima di passare alla stesura del modello relazionale Non basta disegnare il diagramma ER se poi non si adottano delle opportune iniziative di miglioria. Per questo è necessario passare alla: seconda fase: riesame del modello: conversione di entità in attributi conversione di attributi in entità spostamento di attributi da una entità ad un’ altra introduzione di nuove entità introduzione di nuovi attributi introduzione di nuove relazioni In questo caso non è necessario seguire un ordine particolare. Le categorie indicate sono categorie teoriche di intervento sul diagramma ER primitivo. Probabilmente sarà necessario effettuare solo poche modifiche. In generale, però, il primo diagramma creato dopo una certa analisi non è mai adeguato, di conseguenza questa fase è molto importante ed è strettamente collegata con il successivo argomento delle forme normali. Passiamo ora ad analizzare il contenuto di ciascuna categoria. La conversione di entità in attributi può avere luogo solo quando una tabella degenera in soli due campi, con una chiave primaria e la sua descrizione. Facciamo un esempio: se in una tabella contenente una anagrafe di persone si indicasse la città come chiave straniera di una tabella località, allora potrebbe essere possibile trasferire il campo località dalla tabella omonima ed eliminare la tabella località. E’ una questione di scelte, in quanto l’ eliminazione di una tabella e di una relazione ha il benefico risultato di semplificare lo schema. D’ altra parte può comportare il disagio di inserire anche il campo cap nell’ anagrafe, mentre questo, essendo dipendente funzionalmente dalla località ha senso nella relativa tabella. A questo punto, nel sistema con due tabelle l’ inserimento del cap di una certa località ha luogo una volta sola, nella tabella località, mentre nell’ altro sistema ha luogo in tutte le righe ove si usa quella località, col risultato di usare più spazio di quello effettivamente necessario, e col rischio di incoerenza dei dati. In questo caso se l’ unca informazione effettivamente necessaria è quella del nome della località è preferibile non usare la seconda tabella, mentre se occorre anche il cap allora conviene usarne due. Senza contare che nel futuro si potrebbe decidere di avere bisogno anche di altre informazioni come il prefisso telefonico, il codice ISTAT o altro. Si tenga presente la regola generica secondo cui ‘il piccolo stà nel grande’ è molto utile in situazioni come questa, per cui è probabilmente è meglio pensare da subito ‘in grande’ i nostri schemi. Un’ altra regola che mi sento di dare è che ‘non si usano mai abbastanza le relazioni’, e questo perché è molto più facile vedere in giro il più grave difetto opposto. E’ molto semplice capire la situazione inversa che non pone problemi di sorta. Ricorriamo al solito esempio: può presentarsi la necessità di avere l’ informazione del numero civico, mentre abbiamo indicato un solo campo per l’ indirizzo. Si tenga presente quale grave ripercussione sul sistema nervoso può avere la necessità di dividere un campo in più sottocampi, quando ormai sono stati già inseriti nel sistema molti record. Inoltre tale necessità può sorgere anche in modo imprevisto ad esempio perché è necessario effettuare un collegamento con un database esterno. Si tenga presente in proposito il fatto che è molto più facile riunire dopo due campi che erano stati pensati separati, che non l’ opposto. Naturalmente vale ancora il discorso di pensare in grande che, come al solito, si dovrà bilanciare con la nostra necessità di avere uno schema semplice, cioè con il numero minimo di campi e di tabelle. Lo spostamento di un attributo è necessario in fase di normalizzazione dello schema. Tale fase è analizzata in dettaglio tra poco. L’ introduzione di nuove entità, relazioni ed attributi è qualcosa che viene automatica. In ogni caso, dopo sarà necessario riconsiderare lo schema per vedere se le introduzioni non rendano inutili oggetti preesistenti o non si sovrappongano ad essi. Il procedimento indicato è dunque ciclico. Ripetendolo successivamente si dovrebbe giungere dopo qualche ciclo ad una situazione di convergenza nella quale non ci sembra più necessario intervenire. A questo punto è possibile passare alla fase finale che consiste nella: creazione dei vincoli di integrità referenziale e di dominio come si è visto in precedenza l’ integrità dei dati si può garantire fissando due tipi di vincolo, uno referenziale ed uno di dominio. Il vincolo referenziale è necessario altrimenti, come abbiamo visto salta tutto il modello relazionale: nel caso più semplice i campi della chiave straniera devono avere valori presi solo dall’ insieme dato dai valori presenti nella tabella entità rappresentata, e questo in qualsiasi momento. Il vincolo di dominio, invece, è opzionale ma non per questo meno importante, e fa’ sì che un dato campo non possa assumere valori non logici per esso, come ad esempio età espresse con numeri negativi, date di nascita maggiori della data di oggi o valori nulli ove siano necessari dei dati. In questa fase si può anche fare attenzione ad altre caratteristiche come il formato di visualizzazione o di memorizzazione dei dati, che, pur non rappresentando dei vincoli, sono comunque della loro stessa natura in quanto agiscono alla radice del processo di sviluppo. Implementazione del modello relazionale Il modello realzionale è evidentemente basato sul concetto di relazione. Secondo la definizione la relazione è un qualunque sottoinsieme del prodotto cartesiano di una lista di domini (insiemi). Un dominio non è altro che un elenco di valori, mentre il prodotto cartesiano è l’ elenco ottenuto da tutte le coppie che è possibile formare avendo due elenchi di valori. Dunque la relazione è qualcosa di rettangolare con tanto di righe e colonne. In particolare la relazione può coincidere con la tabella di un qualunque database, così come la colonna o attributo coincide con il campo di una tabella. La forte matematicità del modello relazionale fa’ sì che sia stato possibile formalizzare una vera e propria algebra relazionale che è alla base del linguaggio SQL e dei procedimenti di calcolo ed ottimizzazione dei sistema di database relazionale. Il modello relazionale è pertanto molto poco espressivo in considerazione del fatto che ogni tabella è considerata una realtà separata dalle altre e non esiste la possibilità di definire esplicitamente le sue relazioni con le altre tabelle. Una volta che si dispone del diagramma ER è quasi automatica la sua conversione nel modello relazionale: per ogni entità si crea una tabella con la sua chiave primaria per ogni relazione binaria 1:n si crea la chiave straniera nella seconda tabella per ogni relazione m:n si crea la tabella associazione. E’ buona regola seguire anche alcune norme come le seguenti convenzioni di denominazione degli oggetti: far precedere il nome di una tabella dal prefisso tbl far precedere il nome di una chiave dal prefisso Id disporre le chiavi, primarie o straniere che siano, come primi campi di una tabella, la primaria prima delle eventuali straniere a parte il prefisso chiamare una tabella con lo stesso nome dell’ entità; lo stesso dicasi per la corrispondente chiave primaria, se possibile per una chiave straniera usare lo stesso nome della chiave primaria che rappresenta usare il carattere AltoBasso senza usare spazi tra le parole sia per le tabelle che per i campi. Se si seguono queste semplici regole si otterrà un modello relazionale più espressivo del normale. Infatti ogni tabella che rappresenta entità avrà lo stesso nome della sua chiave primaria (a parte il prefisso). Ogni tabella mostrerà esplicitamente la relazione diretta ad un’ altra a causa del nome di quest’ ultima (a parte il prefisso) inserita tra i primi campi. Ogni tabella associazione conterrà almeno due chiavi straniere e nessuna chiave primaria. Evitare sistemi di dati ridondanti-normalizzazione Scelta del tipo di campo Il primo e più semplice modo di evitare ridondanza è la scelta accurata del tipo dei campi. In questa occasione vale la pena di ricordare che, a differenza dai primi sitemi di database basati sui campi a lunghezza fissa, i moderni sistemi di database relazionale utilizzano solo lo spazio effettivamente usato per cui ad esempio, un campo località posto ad una dimensione di 50 caratteri utilizza 50 byte di spazio nel caso peggiore e 0 byte nel migliore. Di conseguenza l’ uso di vincoli troppo restrittivi per le dimensioni dei campi di testo hanno un effetto modesto sul risparmio di spazio, ma possono portare conseguenze spiacevoli per l’ utilizzatore. Non c’ è invece nessuna ragione per usare un numero intero o peggio uno con la virgola se siamo sicuri di usare valori compresi in un intervallo inferiore, come ad esempio da 0 a 256. E’ sicuramente da evitare, infine, l’ errore di molti analisti del passato che hanno memorizzato le date con 6 caratteri numerici, rendendo possibile quello che viene definito l’ ‘incubo dell’ anno duemila’. Forme normali Esistono molte definizioni di normalizzazione. Per noi un database è in forma normale se ogni sottoinsieme di relazioni rispetta la terza forma normale. Le tre forme normali sono le seguenti: 1. 1. Prima forma normale-tipo di dato semplice in ogni campo 2. 2. Seconda forma normale-dipendenza funzionale e completa di un record dalla sua chiave primaria 3. 3. Terza forma normale-dipendenza intransitiva del record dalla chiave primaria. Vediamo che cosa significano le forme normali. La prima forma normale impedisce in sostanza che un campo possa contenere una lista di valori. Bisogna notare che anche se i moderni sistemi di database relazionale non consentono di per sé questa possibilità, è possibile che l’ analista fantasioso decida di creare un campo contenente ad esempio una stringa di 10 indicatori tramite un campo di testo di lunghezza 10. In tale caso è necessario creare 10 campi separati. Per dipendenza funzionale si intende corrispondenza biunivoca tra il record e la chiave primaria. In altre parole, stabilito il valore della chiave primaria, tutti gli altri campi sono individuati in modo unico da questo valore. Viceversa ad ogni chiave primaria corrisponde sempre un solo record. La dipendenza completa indica il caso che tale dipendenza avviene tramite tutti i valori della chiave primaria, e non ad esempio, da un sottoinsieme di essa. Per altro verso ‘la chiave primaria è la più piccola’, o non contiene informazione non necessaria. Infine la dipendenza è non transitiva se non è possibile determinare il valore di quel campo ricorrendo ad una funzione o ad altro artificio. In particolare il campo nazione in una tabella anagrafica dipende in modo transitivo dal campo città di quella stessa tabella: una volta nota la città è nota anche la nazione. Per concludere ricordiamo che le forme normali dipendono una dall’ altra: per essere in terza forma normale un certo database dovrà avere tutte le sue tabelle anche in seconda forma normale, e così via. Il procedimento appena indicato conduce alla realizzazione di schemi di database corretti ed efficienti. Le conseguenze positive dello sforzo affrontato in questa sede si avvertiranno durante tutto il corso dello sviluppo applicativo ed anche dopo. Potrete anche misurare la bontà del progetto come l’ inverso delle modifiche che sarà necessario apportare in seguito allo schema, oppure al lavoro di sviluppo che si renderà necessario. Il progetto ottimo di un sistema porta anche altri benefici più invisibili, come ad esempio il fatto di creare tabelle di valori che non erano esplicitamente richieste e che risultano in una maggiore configurabilità dell’ applicativo finale, o in optional comunque utili per gli utilizzatori. Architetture Client/Server Introduzione Per architettura Client/Server si intende la possibilità di legare le tematiche applicative inerenti quelli che abbiamo definito lo strato interno e concettuale di un sistema di database relazionale in una particolare macchina detta server, lasciando la parte detta esterna sulla macchina dove opera l’ utente finale, detta pertanto client. Questa architettura prevede di accumulare le risorse informatiche più costose e delicate in una sola macchina e di distribuire il relativo servizio tramite una rete locale o geografica. In tal modo anche macchine poco potenti potranno eseguire operazioni complesse in tempi brevi. D’ altro canto ogni intervento migliorativo effettuato sul server sarà percepito immediatamente da ogni utente della rete. Questa architettura si contrappone al concetto di condivisione dei file che prevede che ogni client abbia una copia del database in memoria nel momento di eseguire un’ operazione. Quest’ utlimo approccio, meno sofisticato, prevede in tal modo un intenso traffico di rete e diviene di solito inattuabile con il crescere della dimensione dei file del database. Il grande vantaggio delle architetture Client/Server consiste infatti nell’ inviare al server solo richieste sotto forma di costrutti SQL. Il server restituisce a sua volta solo i record necessari, rendendo minimo l’ utilizzo delle risorse di comunicazione. Riassumendo i principali vantaggi di una architettura Client/Server sono: minore impiego di risorse di rete maggiore velocità operativa maggiore economicità con un opportuno numero di utenti maggiore scalabilità, dato che si agisce direttamente e solo sul server. Architetture C/S ad 3 strati L’ architettura Client/Server rispecchia per molti versi quello che abbiamo detto a proposito di architettura del modello relazionale. Tradizionalmente la maggior parte delle applicazioni Client/Server vengono considerate come applicazioni a due strati. I due strati in questione sono costituiti, come si immagina, dal processo eseguito sul server e da quello eseguito sul client. Questa suddivisione è evidente data la diversità fisica delle macchine coinvolte. Non altrettanto evidente è per un progettista stabilire come porre la linea di demarcazione che decide dove una certa elaborazione deva essere eseguita e perché. Nel seguito si cerca di dare una risposta a questa domanda. Una applicazione complessa non dispone solo dei servizi di interfaccia e dei servizi di database. Come abbiamo già visto anche per il modello relazionale esiste un terzo livello, che abbiamo chiamato concettuale. Per comodità lo abbiamo riunito con quello interno nello strato fisico per fare distinsione dallo strato logico. L’ architettura Client/Server mantiene una struttura a tre strati ma essi non coincidono di necessità con quelli visti precedentemente. Un esempio varrà a chiarire. Supponiamo di dover produrre un’ applicazione per la creazione di preventivi per una grande organizzazione, e consideriamo le caratteristiche richieste per tale applicazione: 1. 1. il codice di un articolo deve essere (unico) e composto da 13 caratteri 2. 2. la modifica del codice di un articolo deve ripercuotersi immediatamente su tutti i preventivi che contengono quel codice, o deve essere impossibile 3. 3. se un cliente è in debito oltre il fido previsto non deve essere possibile creare l’ ordine ma solo il preventivo Per quanto visto finora i controlli al punto 1 e 2 saranno effettuati egregiamente dal database, in particolare per quello che riguarda l’ aggiornamento in cascata dei record collegati ad un certo codice, e pertanto saranno effettuati sul server nel processo database. Cosa dire dell’ ultimo punto? Esso riguarda essenzialmente un problema di politica aziendale, pertanto è suscettibile di cambiare nel corso del tempo molto più di quanto non faranno ad esempio le relazione all’ interno del sistema di database, pur essendo un problema che resta molto vicino al database e alla sua natura di controllore. Per tale ragione questo nuovo tipo di controllo rappresenta uno strato intermedio tra client e server. Ciò non toglie che da qualche parte dovrà comunque essere eseguito. Abbiamo dunque il problema di decidere dove fare eseguire lo strato intermedio delle applicazioni Client/Server. Lo strato intermedio cui abbiamo accennato viene anche detto strato degli oggetti LOBject da Line Of Business Object, definizione con cui si intende sottolineare il fatto che essi includono tutto quanto riguarda la linea di condotta di una certa applicazione. Riassumendo una architettura Client/Server è costituita dai seguenti tre strati: data business Servizi di database Tutto quanto riguarda la linea di condotta applicativa user Interfaccia utente Resta il problema di stabilire la demarcazione non sempre facile tra data e business, oltre alla macchina che deve eseguire il servizio business. Purtroppo non esistono, almeno per ora, delle regole matematiche che consentano di ottenere un risultato ottimo, come le regole di normalizzazione dei database viste finora. Solo il buon senso ci può aiutare a risolvere il problema. In particolare una regola destinata a durare nel tempo è molto probabile che appartenga allo strato data, ma ciò è valido solo molto in generale: avete mai visto qualcuno con più di 150 anni di età, oppure più alto di due metri? Se anche esistesse qualcuno così non per questo la vostra applicazione avrebbe fallito il suo scopo. Più difficile dire dove debba essere eseguito un processo LOBject. Una regola euristica potrebe essere la seguente: se il processo deve compiere operazioni complesse basandosi su pochi dati, esso è da eseguire sul client, altrimenti sul server. Infatti un processo che faccia grande uso della CPU non può essere eseguito su un server che deve essere usato solitamente da molti utenti, mentre un processo che faccia uso intensivo dei dati ha la sua sede naturale proprio nel server di database, ottimizzato allo scopo. Questa breve trattazione dei sistemi Client/Server intendeva solo introdurre i concetti essenziali e non esaurice il tema, è solo interessante far notare come vi sia un seme nel modello relazionale a tre strati che porta direttamente al concetto di Client/Server. Bibliografia R.G.G. Cattell, “Object data management”, Addison Wesley, 1994 O.Bettelli, “Dati, relazioni e associazioni”, Apogeo, 1991 J.D.Ullman, “Principles of database and knowledgebase systems”, Computer science press, 1988 C.Batini, S.Ceri, S.Navathe, “Conceptual database design”, Benjamin Cummings, 1992 F.Balena, “Automazione remota in VB4”, Computer programming, 63, Gennaio 1997 Lorenzo Vandoni, “Pensare un database...”, DEV, 20, Gennaio 1997 R.Dadda, “PDCA ed altri spunti...”, BIT, 104, Aprile 1995