讓資料保持彈性的設計:Profile 架構

如果可以由資料庫本身去做彈性設計的話,對於物件使用 ORM 以及擴充上會有正面幫助,物件可以不受物件既有資料表欄位的限制,即可由物件自己去決定會多或會少哪些資料,而資料庫依照物件的要求做出反應,即可確保物件的高彈性,又可以簡化資料表的設計。這個方法即為 Profile 架構。

筆者認為長久以來,一直有一個問題在困擾著程式設計師和系統分析師們,就是要如何設計出具有彈性的資料結構。在物件導向的觀念中,想要設計具彈性的物件是很容易的,但想設計出具彈性的資料結構是很困難的,其中最大的原因是 DBMS 長久以來都是關聯導向(Relation-Oriented),而不是物件導向,在關聯導向的架構中想要建構出具有物件導向能力的存取架構以及綱要設計,其實並不容易。學術界針對這個部份有提出 OO-DBMS(物件導向型資料庫管理系統),然而提出來這麼久,具指標性的大廠中卻只有 Oracle 有提出實際成品,而且採用的廠商也不多,由此可見 RDBMS(關聯式資料庫管理系統)仍會存在好一陣子,而且這一陣子會是十年以上,除非 OODBMS 技術上有重大突破,否則想改變 RDBMS 是不太可能的。

也因為如此,另一個 RDBMS 和 OOP 整合的概念就被提出來:ORM (Object-Relational Mapping),這個概念已經由 Java 陣營的 Hibernate 所實作,.NET 這裡則有 NHibernate(Hibernate 的 .NET 移植版) 與 ADO.NET Entity Framework 兩者,不過想要使用 ORM 技術,事實上仍有很大的困難點,雖然它可以將資料表和物件自動做對應(這是 ORM 最主要想解決的問題),不過它的門檻也不低,而且實際上並沒有解決關聯式資料不夠彈性的問題。

因此筆者試著為這個問題提出一個思考面向,如果可以由資料庫本身去做彈性設計的話,對於物件使用 ORM 以及擴充上會有正面幫助,物件可以不受物件既有資料表欄位的限制,即可由物件自己去決定會多或會少哪些資料,而資料庫依照物件的要求做出反應,即可確保物件的高彈性,又可以簡化資料表的設計。這個方法即為 Profile 架構。

筆者會想到這個方法,導因自 ASP.NET 2.0 開始提供的 Profile Framework,以及筆者最近在某個微軟產品中看到的應用,再加上自己實作的驗證,確實證明 Profile 架構可以提供一部份的資料延展彈性,而且就資料列的角度來看,不像資料欄有個數限制,而且資料欄一旦擴充,若資料表中的列數有相當規模,則會讓資料表中出現許多空白資料(原有資料不可能刪除)或是預設值資料,而且這類型的擴充是需要較長的時間,不太符合彈性的原則,因此不如將一些不固定型的資料(或會依性質不同而產生變化的資料),由另一個表格來儲存,這樣可以保持原主檔表格的不變性,又可以確保前端物件使用繼承以衍生物件時的高彈性。

筆者曾在邁向架構師的暖身運動(2):抽象化的能力提出一個範例,利用一個抽象的產品類別來定義產品主檔,而由子類別針對不同的產品屬性定義各自的屬性資料,而這類型的設計即可利用 Profile 架構來儲存。現就用這個例子(類似)來舉例說明 Profile 架構:

1. 首先在資料庫中先定義主檔以及要裝載 Profile 的資料表:

2. 建立主檔的類別,此例使用 Product 作類別名稱。

3. 建立真正使用的產品類別,此例定義 SoftwareProduct (軟體) 以及 CameraProduct (相機) 兩個產品,可注意兩者的屬性資料不太一樣,但一樣的是都繼承自 Product 類別。

 

這兩個類別的存取都經由 Product 來提供,因此在各自的 Add(), Update(), Delete() 等類別都有呼叫 Product 中的相對方法,不過由於兩個類別中所控的屬性資料不同,因此各自也要負責自己的屬性資料的存取,也就是對 ProductProfiles 表格的讀寫。

4. 撰寫主程式(筆者用的是 Console 應用程式,讀者可自行套用適當的程式到 Windows App 或 Web App 中):

5. 編譯並執行程式,應可以看到:

 

代表資料已寫入。接著到資料庫中看:

資料確實已寫入。

讀者可以試著使用 SoftwareProduct.GetByID() 以及 CameraProduct.GetByID() 去取出資料,並且自行由 Product 類別衍生出自己的物件,並且參考 SoftwareProduct 與 CameraProduct 的 Profile 屬性設定方式設計,感受一下這個設計方法帶來的彈性。

後記:這個方法不見得是 100% 最好的設計方法,但確實可以緩解因為資料結構不夠彈性而造成的類別延展性受限問題,也許讀者看了以後,會激發出比筆者這個方法更好的設計方式,同時也請有想法的讀者不吝給予指教。 

2009/7/17 加註:

此架構僅適用於關聯型資料庫(RDBMS),若是混合型的資料結構(例如文字檔或是不同格式的資料來源)或是系統有跨越不同資料格式的儲存服務時,此架構可能就不適合。