這個準則說明資料庫反向工程以及將產生的資料模型表格對映到設計模型中之設計類別所涉及的步驟。資料庫設計者可以利用這個流程,將資料庫修正的開發工作植根於一個發展開發循環中。在專案的整個開發生命週期中,資料庫設計者都必須管理這個反向工程流程。在許多情況下,反向工程流程都是在專案生命週期的早期執行,之後,再漸進地管理資料設計的變更,不需要執行後續的資料庫反向工程。
資料庫反向工程以及將產生的資料模型元素轉換成設計模型元素之流程的主要步驟如下:
-
建立一個實體資料模型,其中包含代表資料庫持續資料之實際佈置的表格。您可以利用關聯式資料庫管理系統 (RDBM) 所提供的工具,或利用最新的視覺化建模工具來自動執行這個步驟。
-
將實體資料模型中的表格轉換成設計模型中的設計類別。您可以將起始轉換的自動化工具支援和後續的手動調整組合起來,以執行這個步驟。
-
定義設計模型中各類別之間的關聯。
-
根據對應的資料模型元素所執行的動作來定義設計模型中之類別的適當作業。
-
依照需要,將設計模型中的類別分組成子系統和套件。
資料庫或資料定義語言 (DDL) Script 反向工程的流程,通常會產生一組模型元素(表格、概略表、儲存程序等)。依資料庫的複雜度而定,資料庫設計者可能需要將反向工程模型元素分割成各個主題區套件,其中包含在邏輯上相關的各組表格。
您可以遵循下列程序,從資料模型中的模型元素產生設計類別。抄寫類別模型中資料庫的結構相當簡單。下列流程說明將資料模型元素轉換成設計模型元素的演算法。
下表顯示設計模型元素和資料模型元素之間的一般對映摘要。
資料模型元素
|
對應的設計模型元素
|
表格
|
類別
|
直欄
|
屬性
|
非識別關係
|
關聯
|
交集表格
|
關聯類別
多對多關聯
限定關聯
|
識別關係
|
聚集
|
基數
|
對應關係
|
含列舉子句的核對限制
|
<<ENUM>> 類別
|
綱目
|
套件
|
資料模型中的某些模型元素,在設計模型中沒有直接的相互關係。這些元素包括表格空間和資料庫本身,它們以元件來表示,用來建立資料庫實體儲存體特性的模型。另一個項目是資料庫概略表,它們是「虛擬的」表格,在設計模型中沒有意義。最後是表格主鍵的索引及資料庫觸發函數,它們用來將資料庫的作業最佳化,但它們只有在資料庫的環境定義及資料模型中才有意義。
對於您要轉換的每份表格,請建立一個類別來代表表格。對於每個直欄,請在適當資料類型的類別上建立一個屬性。請嘗試配對屬性的資料類型和相關直欄的資料類型,越接近越好。
範例
請設想含有如下圖所示下列結構的資料庫表格 Customer:
直欄名稱
|
資料類型
|
Customer_ID
|
Number
|
Name
|
Varchar
|
Street
|
Varchar
|
City
|
Varchar
|
State/Province
|
Char(2)
|
Zip/Postal Code
|
Varchar
|
Country
|
Varchar
|
Customer 表格的表格定義
從現在開始,我們要建立含有如下圖所示結構的 Customer 類別:
起始 Customer 類別
在這個起始 Customer 類別中,Customer 表格中的每個直欄都有一個屬性。每個屬性的可見度都是 public,因為原始表格中的任何直欄都可以查詢。
請注意,屬性左側的 "+" 圖示表示這個屬性是 'public';依預設,從 RDBMS 表格衍生而來的所有屬性都應該是 public,因為 RDBMS 通常允許對任何直欄進行不受限制的查詢。
直接的「表格-類別」對映所產生的類別,通常會包含可分到其他類別的屬性,尤其是當屬性會出現在許多轉換的類別時,更是如此。這些「重複屬性」可能是為了效能原因而將表格反正規化所產生的,也可能是資料模型過度簡化的結果。在這些案例中,請將對應的類別分割成兩個或多個類別來代表表格的正規化概略表。
範例
定義好上述 Customer 類別之後,我們可以定義一個 Address 類別來包含所有地址資訊(假設系統會有其他包含地址的項目),於是我們會有下列類別:
修訂的 Customer 類別及擷取出來的 Address 類別
這兩者之間所繪製的關聯是一項聚集,因為客戶的地址可視為客戶的一部分。
請針對表格中的每個外鍵關係來建立相關類別之間的關聯,從類別中移除對映到外鍵直欄的屬性。如果最初是用屬性來表示外鍵直欄,請從類別中移除它。
範例
假設下列 Order 表格的結構:
直欄名稱
|
資料類型
|
Number
|
Number
|
Customer_ID
|
Varchar
|
Order 表格的結構
在上面列出的 Order 表格中,Customer_ID 直欄是一個外鍵參照;這個直欄包含 Order 所關聯的 Customer 的主鍵值。我們會在設計模型中,依照下列方式來表示它:
外鍵關係在設計模型中的表示法
外鍵是用 Order 和 Item 這兩個類別之間的關聯來表示。
RDBMS
資料模型用所謂的合併表格或關聯表格來表示多對多關係。這些表格使得多對多關係能夠利用中間表格來表示,中間表格含有可合併的兩份不同表格的主鍵。需要合併表格是因為外鍵參照只能參照單一外鍵值;當單獨一列可能關聯於另一份表格中的許多其他列時,便必須用合併表格將它們關聯起來。
範例
請設想 Products 的情況,它可能是許多 Supplier 中的任意一個所提供,而任何 Supplier 也都可以提供任意數目的 Products。Product
和 Supplier 這兩份表格的結構定義如下:
Product 表格
直欄名稱
|
資料類型
|
Product_ID
|
Number
|
Name
|
Varchar
|
Description
|
Varchar
|
Price
|
Number
|
|
Supplier 表格
直欄名稱
|
資料類型
|
Supplier_ID
|
Number
|
Name
|
Varchar
|
Street
|
Varchar
|
City
|
Varchar
|
State/Province
|
Char(2)
|
Zip/Postal Code
|
Varchar
|
Country
|
Varchar
|
|
Product 和 Supplier 表格定義
為了將這兩份表格鏈結起來,以找出特定供應商所提供的產品,我們需要一份 Product-Supplier 表格,下表定義這份表格。
Product-Supplier 表格
|
直欄名稱
|
資料類型
|
Product_ID
|
Number
|
Supplier_ID
|
Number
|
產品供應商表格定義
這個合併表格包含產品和供應商彼此互相鏈結起來的主鍵。表格中的一列指出特定供應商提供特定產品。所有 Supplier_ID 直欄符合特定供應商 ID 的列,都會提供這個供應商提供的所有產品清單。
在設計模型中,這份中間表格是多餘的,因為物件模型可以直接表現多對多關聯。下圖顯示 Supplier 和 Product 這兩個類別及其關係,以及根據先前的討論,從 Supplier 中擷取出來的
Address 類別。
Product 和 Supplier 類別表示法
您通常會發現表格有一些類似的結構。在資料模型中,並沒有一般化的概念,因此,也無法表現出兩份或更多表格有部分共用結構的情況。有時候,為了效能,會因反正規化而產生共用結構,例如上述含有「隱含」的
Address
表格的情況,我們將它擷取到獨立的類別中。在其他情況中,表格會共用更多基本特性,這些特性可以擷取到含有兩個或更多子類別的一般化母類別中。為了找出一般化的機會,請尋找多份表格中重複的直欄,在這裡,各份表格的相似大於差異。
範例
請設想下面所示的 SoftwareProduct 和 HardwareProduct 這兩份表格:
SoftwareProduct 表格
直欄名稱
|
資料類型
|
Product_ID
|
Number
|
Name
|
Varchar
|
Description
|
Varchar
|
Price
|
Number
|
Version
|
Number
|
|
HardwareProduct 表格
直欄名稱
|
資料類型
|
Product_ID
|
Number
|
Name
|
Varchar
|
Description
|
Varchar
|
Price
|
Number
|
Version
|
Number
|
|
SoftwareProduct 和 HardwareProduct 表格
請注意,藍色反白的直欄是相同的;這兩份表格共用大部分的定義,只有稍微不同。我們要表現這一點,可以如下圖所示,擷取一個共用的 Product 類別,以 SoftwareProduct 和
HardwareProduct 為 Product 的子類別:
SoftwareProduct 和 HardwareProduct 類別,顯示 Product 類別的一般化
下圖將所有類別定義放在一起來顯示 Order Entry 系統的合併類別圖(只有主要類別)。
Order Entry 系統的合併類別圖
抄寫行為比較困難,因為典型的關聯式資料庫並不是物件導向,也沒有任何東西類似於物件模型中的類別作業。下列步驟有助於重新建構上面所識別之類別的行為:
-
建立用來取得和設定每個屬性的作業。
您必須有可用來設定、變更和查詢物件屬性值的方法。由於存取物件屬性的唯一方法是利用類別提供的作業,因此,這類作業必須定義在類別上。當建立設定屬性值的作業時,請務必納入可處理相關直欄的任何驗證限制。如果沒有任何驗證限制,您可以依照前面各個圖所採取的相同方式,選擇將屬性的可見度標示為
"public" 來簡單表示屬性可以 get 和 set 的事實。
-
針對處理相關表格的每個儲存程序來建立一項類別作業。 儲存程序是在 DBMS
本身之內執行的執行子常式。這個邏輯必須轉換成設計模型。如果儲存程序只處理單一類別,請利用儲存程序的相同參數和相同傳回類型來建立一項類別作業。請在文件中說明作業中的儲存程序行為,並在方法說明附註中,指出作業是由儲存程序來實作的。
-
建立用來管理類別間之關聯的作業。 當兩個類別彼此關聯時,必須有用來建立、管理和移除關聯的方法。物件之間的關聯是利用物件參照來管理的,因此,如果要建立 Order 和 LineItem
之間的關聯(也就是將 LineItem 加到 Order中),便會呼叫 Order 的作業,並將 LineItem 當作引數來傳遞(也就是
Order.add(aLineItem))。另外,還必須有移除和更新關聯的方法(也就是 Order.remove(aLineItem) 和
Order.change(aLineItem,aNewLineItem))。
-
處理物件的刪除。 如果目標語言支援明確刪除,請將行為加到類別實作參照完整性檢查的解構子中。當資料庫有參照完整性限制時,如連鎖刪除,就必須在適當類別中抄寫行為。例如,資料庫可能會定義一項限制,指出每當刪除
Order 時,也應該刪除所有相關聯的
LineItems。如果目標語言支援記憶體回收,請建立一個在回收相關物件的記憶體時,也會從表格中移除資料列的機制。請注意,這聽起來很難,但實際上還更難,因為您必須實作一項機制來確保沒有任何資料庫用戶端參考記憶體將被回收的物件;執行環境/虛擬機器的記憶體回收功能並不可靠,因為這只是單一用戶端的世界觀。
-
處理查詢隱含的行為。 請查驗存取表格的 SELECT 陳述式,以瞭解資訊的擷取和操作方式。對於 SELECT 陳述式直接傳回的每個直欄,請將相關屬性的 public 內容設為
true;所有其他屬性都應該是 private。對於 SELECT 陳述式中的每個計算直欄,請在相關類別建立一項作業來計算和傳回值。當考量 SELECT 陳述式時,也請併入內嵌在概略表定義中的
SELECT 陳述式。
「表格至類別」轉換所建立的設計類別,應該依照需要,以應用程式的整體架構為基礎,組織到資料模型適當的設計套件和/或設計子系統中。請參閱概念:分層和概念:軟體架構,以取得應用程式架構的概觀。
|