Linea guida: Reverse-engineering dei database relazionali
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.
Relazioni
Elementi correlati
Descrizione principale

Introduzione

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.

Reverse Engineering database RDBMS o script DDL per generare un modello dati

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.

Trasformazione del modello dati in modello di progettazione

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.

Trasformazione di una tabella in una classe

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:

Definizione della classe cliente

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.

Identificazione delle classi incluse o implicite

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:

Diagramma descritto nel testo associato.

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.

Gestione di relazioni di chiavi esterne

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:

Diagramma UML descritto 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.

Gestione di relazioni molti a molti

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.

Diagramma UML descritto nella didascalia

Rappresentazione della classe Prodotto e Fornitore

Introduzione alla generalizzazione

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:

Diagramma descritto nel testo associato.

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 UML complesso descritto nel testo associato.

Diagramma di classi consolidate per il sistema degli articoli dell'ordine

Replica del comportamento di RDBMS nel modello di progettazione

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:

  1. 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).
  2. 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.
  3. 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)).
  4. 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.
  5. 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.

Organizzazione di elementi nel modello di progettazione

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.