Questa guida al tool descrive le operazioni coinvolte nel reverse engineering di un database e la mappatura delle
risultanti tabelle dei modelli
dati alle classi di progettazione nel modello
di progettazione. Questo processo potrebbe essere utilizzata dal progettista del database per inviare lo sviluppo di modifiche al
database come parte di un ciclo di sviluppo di evoluzione. Il progettista di database dovrà gestire il processo di
reverse engineering per tutto il ciclo di vita dello sviluppo del progetto. In molti casi, il processo reverse
engineering viene eseguito nella fase iniziale del ciclo di vita del progetto e quindi le modifiche alla progettazione
dei dati vengono gestite in modo incrementale senza dover eseguire operazioni di reverse engineering successive del
database.
Le principali operazioni nel processo di reverse engineering di un database e di trasformazione dei risultanti elementi
del modello dati in quelli del modello di progettazione sono le seguenti:
-
Creare un modello dati fisico che contiene tabelle per rappresentare il layout fisico di dati permanenti nel
database. Questa operazione può essere eseguita automaticamente utilizzando i tool forniti con il RDBMS
(Relational Database Management System) oppure attraverso i tool di creazione modelli visivi più moderni.
-
Trasformare le tabelle, presenti nel modello dati fisico, nelle classi di progettazione, presenti nel modello di
progettazione. Questa operazione può essere eseguita attraverso una combinazione di tool automatizzati di
supporto alla trasformazione iniziale eseguita mediante correzioni manuali.
-
Definire le associazioni tra le classi nel modello di progettazione.
-
Definire le operazioni appropriate sulle classi nel modello di progettazione, basate sulle azioni eseguite sugli
elementi del modello di progettazione corrispondenti.
-
Raggruppare le classi nel modello di progettazione in sottosistemi e pacchetti.
Il processo di reverse engineering del database o di script DDL (Data Definition Language) in genere produce una serie
di elementi del modello (tabelle, viste, procedure memorizzate, etc...). . A seconda della complessità del database, è
possibile che al progettista del database occorra suddividere gli elementi del modello, su cui ha effettuato il reverse
engineering, in pacchetti di area tematica che contengono l'insieme di tabelle correlato logicamente.
La seguente procedura può essere utilizzata per produrre classi di progettazione da elementi di modello nel modello
dati. La replica della struttura del database in un modello classi è relativamente semplice. Il processo elencato qui
di seguito descrive l'algoritmo per la trasformazione degli elementi del modello dati in quelli del modello di
progettazione.
La tabella qui di seguito mostra un riepilogo della mappatura generale tra gli elementi del modello di progettazione e
quelli del modello dati.
Elementi del modello dati
|
Elemento del modello corrispondente
|
Tabella
|
Classe
|
Colonna
|
Attributo
|
Relazione non identificativa
|
Associazione
|
Tabella di intersezione
|
Classe di associazione
Associazione molti a molti
Associazione qualificata
|
Relazione identificativa
|
Aggregazione
|
Cardinalità
|
Molteplicità
|
Vincolo di controllo con proposizioni numerate
|
Classe <<ENUM>>
|
Schema
|
Pacchetto
|
Esistono alcuni elementi nel modello dati che non hanno correlazione diretta nel modello di progettazione. Tra questi
elementi sono compresi i tablespace e il database stesso, che crea modelli per le caratteristiche della memoria fisica
del database e vengono rappresentati come componenti. Un altro elemento sono le viste del database, che sono tabelle
"virtuali" e non hanno alcun senso nel modello di progettazione. Infine, gli indici sulle chiavi primarie delle
tabelle e le funzioni di trigger del database, utilizzate per ottimizzare l'operazione del database, hanno senso solo
nell'ambito del database e del modello dati.
Per ciascuna tabella che si desidera trasformare, creare una classe per rappresentare la tabella. Per ciascuna colonna,
creare un attributo sulla classe con il tipo dati appropriato. Far corrispondere il tipo dati dell'attributo e il tipo
dati della colonna associata quanto più è possibile.
Esempio
Considerare la tabella del database Cliente, con la seguente struttura, illustrata nella seguente figura:
Nome colonna
|
Tipo dati
|
ID_cliente
|
Numero
|
Nome
|
Varchar
|
Indirizzo
|
Varchar
|
Città
|
Varchar
|
|
Char(2)
|
Codice postale
|
Varchar
|
Nazione
|
Varchar
|
Tabella di definizione per la tabella Cliente
A partire da questo punto, viene creata una classe, Cliente con la struttura illustrata nella figura seguente:
Classe Cliente iniziale
In questa classe Cliente iniziale, vi è un attributo per ogni colonna della tabella Cliente. Tutti gli
attributi hanno visibilità pubblica, poiché tutte le colonne della tabella di origine possono essere sottoposte
a query.
Si noti che, l'icona "+" posta a sinistra dell'attributo indica che l'attributo è 'pubblico' per impostazione
predefinita, tutti gli attributi che derivano delle tabelle RDBMS devono essere pubbliche, poiché RDBMS di solito
consente che tutte le colonne siano sottoposte a query senza alcuna limitazione.
La classe, che deriva dalla mappatura tabella-classe diretta, spesso conterrà attributi che possono essere suddivisi in
una classe separata, specialmente nei casi in cui gli attributi vengono visualizzati in un numero di classi tradotte.
Questi 'attributi ripetuti' possono derivare alla denormalizzazione delle tabelle per motivi di prestazione oppure
possono essere il risultato di un modello dati supersemplificato. In questi casi, suddividere la classe corrispondente
in due o più classi per rappresentare una vista normalizzata delle tabelle.
Esempio
Dopo aver definito la classe Cliente appena citata, è possibile definire una classe Indirizzo che
contenga tutte le informazioni relative all'indirizzo (presupponendo che esistano altri elementi con indirizzi nel
nostro sistema), che fornisce le seguenti classi:
Classe Cliente revisionata, con la classe Indirizzo estratta
L'associazione tracciata tra queste due classi è un'aggregazione, poiché si può ritenere l'indirizzo del cliente
come parte del cliente.
Per ciascuna relazione di chiavi esterne nella tabella, creare un'associazione tra le classi associate, eliminando
l'attributo dalla classe che è mappata con la colonna delle chiavi esterne. Se la colonna delle chiavi esterne è stata
rappresentata come un attributo, eliminarla dalla classe.
Esempio
Assumere la struttura per la tabella Ordine elencata qui di seguito:
Nome colonna
|
Tipo dati
|
Numero
|
Numero
|
ID_cliente
|
Varchar
|
Struttura per la tabella Ordine
Nella tabella Ordine appena citata, la colonna ID_cliente è un riferimento di chiave esterna;
questa colonna contiene il valore di chiave primaria del Cliente associato all'Ordine. Verrà rappresentato nel modello
di progettazione come illustrato qui di seguito:
Rappresentazione di relazioni di chiavi esterne nel modello di progettazione
La chiave esterna viene rappresentata come un'associazione tra le classi Ordine e Articolo.
I modelli dati di RDBMS rappresentano relazioni molti a molti con ciò che viene chiamata una tabella di unione
oppure una tabella di associazione. Queste tabelle consentono alle relazioni molti a molti di essere
rappresentate utilizzando una tabella intermedia, che contiene chiavi primarie di due differenti tabelle da poter
unire. Le tabelle di unione sono necessarie perché un riferimento di chiave esterna può solo contenere un riferimento
ad un singolo valore di chiave esterna; quando una singola riga può essere correlata a molte altre righe di un'altra
tabella, occorre una tabella di unione per associarle.
Esempio
Considerare il caso dei Prodotti, che possono essere forniti da un numero qualsiasi di Fornitori e
qualsiasi Fornitore può fornire qualsiasi numero di Prodotti. Le tabelle Prodotto e
Fornitore hanno le tabelle definite qui di seguite:
Tabella del prodotto
Nome colonna
|
Tipo dati
|
ID_prodotto
|
Numero
|
Nome
|
Varchar
|
Descrizione
|
Varchar
|
Prezzo
|
Numero
|
|
Tabella del fornitore
Nome colonna
|
Tipo dati
|
ID_fornitore
|
Numero
|
Nome
|
Varchar
|
Indirizzo
|
Varchar
|
Città
|
Varchar
|
|
Char(2)
|
Codice postale
|
Varchar
|
Nazione
|
Varchar
|
|
Definizioni della tabella del prodotto e del fornitore
Per collegare due tabelle per individuare i prodotti offerti da un particolare fornitore, occorre una tabella
Prodotto-Fornitore, che viene definita nella tabella qui di seguito.
Tabella Prodotto-Fornitore
|
Nome colonna
|
Tipo dati
|
ID_prodotto
|
Numero
|
ID_fornitore
|
Numero
|
Definizione della tabella Prodotto-Fornitore
Questa tabella di unione contiene le chiavi primarie dei prodotti e dei fornitori, collegandoli insieme. Una
riga nella tabella indica che un particolare fornitore offre un particolare prodotto. Tutte le righe, la cui colonna
ID_fornitore corrisponde ad un particolare ID fornitore, forniscono un elenco di tutti i prodotti di quel fornitore.
Nel modello di progettazione, questa tabella intermedia è superflua, poiché un modello oggetto può rappresentare
direttamente associazioni molti a molti. Le classi Fornitore e Prodotto e le loro relazioni vengono
illustrate nella fugura qui di seguito, insieme alla classe Indirizzo, che viene estratta dal Fornitore,
secondo quanto discusso in precedenza.
Rappresentazione della classe Prodotto e Fornitore
Spesso, verranno rilevate tabelle con strutture simili. Nel modello
dati, non esiste il concetto di generalizzazione, pertanto non è possibile rappresentare due o più tabelle che
hanno in comune la stessa struttura. A volte la struttura comune deriva dalla denormalizzazione delle prestazioni,
quale il caso sopra citato relativo alla tabella Indirizzo 'implicito', che è stato estratto in una classe
separata. In altri casi, le tabelle condividono caratteristiche più fondamentali che possono essere estratte in una
classe parent generalizzata con due o più classi secondarie. Per individuare più opportunità di generalizzazione,
individuare le colonne ripetute in più tabelle, dove le tabelle sono più simili di quanto siano differenti.
Esempio
Considerare le seguenti tabelle, ProdottoSoftware e ProdottoHardware, come illustrato qui di seguito:
Tabella di prodotti software
Nome colonna
|
Tipo dati
|
ID_prodotto
|
Numero
|
Nome
|
Varchar
|
Descrizione
|
Varchar
|
Prezzo
|
Numero
|
Versione
|
Numero
|
|
Tabella di prodotti hardware
Nome colonna
|
Tipo dati
|
ID_prodotto
|
Numero
|
Nome
|
Varchar
|
Descrizione
|
Varchar
|
Prezzo
|
Numero
|
Versione
|
Numero
|
|
Tabelle ProdottoSoftware e ProdottoHardware
Si noti che le colonne evidenziate in blu sono identiche; queste due tabelle condividono la maggior parte delle
definizioni in comune e sono solo leggermente differenti. È possibile rappresentarle estraendo una classe
Prodotto comune con ProdottoSoftware e ProdottoHardware come classi secondarie del
Prodotto, come illustrato nella seguente figura:
Le classi ProdottoSoftware e ProdottoHardware, mostrano la generalizzazione per la classe Prodotto
Riunendo tutte le definizioni delle classi, la figura qui di seguito illustra un diagramma di classe consolidata per il
sistema degli articoli dell'ordine (solo le classi più importanti).
Diagramma di classi consolidate per il sistema degli articoli dell'ordine
La replica del comportamento è più complessa, poiché in genere i database relazionali non sono orientati a oggetto e
non sembrano avere operazioni analoghe su una classe di un modello oggetti. Le seguenti operazioni possono agevolare la
ricostruzione delle classi identificate qui sopra:
-
Creazione di operazioni per richiamare ed impostare ciascun attributo Occorre un modo per impostare,
modificare, interrogare i valori degli attributi degli oggetti. Poiché il solo modo di accedere agli attributi di
un oggetto avviene attraverso operazioni fornite dalla classe, queste operazioni devono essere definite nella
classe. Quando si creano le operazioni, che impostano il valore di un attributo, accertarsi di incorporare tutti i
vincoli di convalida che possono operare sulla colonna associata. Se non vi sono vincoli di convalida, è possibile
semplicemente decidere di rappresentare che gli attributi possano essere richiamati e impostati
contrassegnandoli come elementi che hanno visibilità "pubblica", poiché ciò è stato effettuato nel diagramma qui
sopra (con l'icona a sinistra del nome attributo).
-
Creazione di un'operazione sulla classe per ogni procedura memorizzata che opera sulla tabella associata. Le
procedure memorizzate sono subroutine eseguibili che vengono eseguite in DBMS stesso. Questa logica deve essere
tradotta nel modello di progettazione. Se una procedura memorizzata opera solo su una classe, creare un'operazione
sulla classe con gli stessi parametri e lo stesso tipo di ritorno della procedura memorizzata. Documentare il
comportamento della procedura memorizzata nell'operazione, accertandosi di annotare nella descrizione metodo
che l'operazione viene implementata dalla procedura memorizzata.
-
Creazione di operazioni per gestire associazioni tra classi. Quando esiste un'associazione tra due classi, è
necessario che esista un modo per creare, gestire ed eliminare associazioni. Le associazioni tra oggetti vengono
gestite attraverso i riferimenti agli oggetti, in modo da creare un'associazione tra un Ordine e un
Articolo (ad esempio, aggiungere un Articolo all'Ordine); verrà richiamata un'operazione su un
Ordine, che passa l'Articolo come un argomento (ad esempio Order.add(aLineItem)). Ci devono
anche essere dei modi per eliminare ed aggiornare le associazioni (ad esempio Order.remove(aLineItem) e
Order.change(aLineItem,aNewLineItem)).
-
Gestione della cancellazione di oggetti Se il linguaggio di destinazione supporta la cancellazione
esplicita, aggiungere il comportamento al distruttore della classe che implementa la verifica dell'integrità
referenziale. Nei casi in cui vi sono vincoli all'integrità referenziale nel database, quali eliminazione a
cascata, occorre che il comportamento venga replicato nelle classi appropriate. Ad esempio, il database può
definire un vincolo in cui si stabilisce che ogni qual volta che viene definito un Ordine, si devono anche
eliminare tutti gli Articoli associati. Se il linguaggio di destinazione supporta la raccolta dati obsoleti,
creare un meccanismo mediante il quale sia possibile eliminare le righe dalle tabelle, quando l'oggetto associato è
una raccolta dati obsoleti. Si noti che è più difficile di quanto possa sembrare, poiché occorre implementare un
meccanismo per assicurare che nessun client del database possieda riferimenti all'oggetto, che è una raccolta di
dati obsoleti; non basta contare sulle capacità di raccolta dei dati obsoleti della macchina virtuale/ambiente di
esecuzione poiché si tratta semplicemente di una vista client della situazione.
-
Gestione del comportamento implicato dalle query. Esaminare le istruzioni Select che accedono alla tabella
per verificare quante informazioni vengono richiamate e manipolate. Per ciascuna colonna restituita direttamente da
una istruzione Select, impostare la proprietà public dell'attributo associato su true; tutti gli
altri attributi devono essere private. Per ciascuna colonna calcolata in un'istruzione Select, creare
un'operazione sulla classe associata per calcolare e restituire il valore. Quando si considerano istruzioni Select,
vengono anche incluse le istruzioni Select incluse nelle definizioni delle viste.
Le classi di progettazione, create dalle trasformazioni da-tabella-in-classe, devono essere organizzate in pacchetti di progettazione appropriati e/o in sottosistemi di progettazione nel modello di progettazione, basato
sulla struttura complessiva dell'applicazione. Consultare il Concetto: Livelli e
Concetto: Architettura software per una panoramica sull'architettura
dell'applicazione.
|