一步一步設計你的數據庫之如何提取業務規則
引言:一步一步設計你的數據庫之不可輕視的需求分析中我們通過多種方法來理解客戶的需求并撰寫了需求文檔。本文我們將回答三個問題。1. 為什么業務規則非常重要。2. 怎樣識別業務規則。3. 如何修改關系模型并隔離出業務規則。
什么是業務規則
業務規則描述了業務過程中重要的且值得記錄的對象、關系和活動。其中包括業務操作中的流程、規范與策略。業務規則保證了業務能滿足其目標和義務。
生活中的一些業務規則可能是:
- 當顧客進入店內,最近的員工須向顧客打招呼說:“歡迎來到×××”。
- 當客戶兌換超過200元的獎券時,柜員須要求查看客戶的身份證并復印。當兌換的獎券金額小于25元時,無需客戶簽字。
- 早上第一個進辦公室的人需要把飲水機加熱按鈕打開。
本系列我們關注數據庫相關的業務規則,一些例子如下:
- 只有當客戶產生第一個訂單時才創建該客戶的記錄。
- 若一名學生沒有選任何一門課程,把他的狀態字段設為Inactive。
- 若銷售員在一個月中賣出10套沙發,獎勵500元。
- 一個聯系人必須至少有1個電話號碼和1個email郵箱。
- 若一個訂單的除稅總額超過1000元則能有5%的折扣。
- 若一個訂單的除稅總額超過500元則免運費。
- 員工購買本公司商品能有5%的折扣。
- 若倉庫中某貨品的存量低于上月賣出的總量時,則需要進貨。
從數據庫的視角來看,業務規則是一種約束。簡單的約束如:
所有訂單必須有一個聯系電話。
上述這類簡單的規則可以很容易的映射到關系數據庫定義中,為字段確定數據類型或設定某字段為必填(不能為NULL)。某些業務規則表達的約束會復雜些,如:
學生每天的上課時間加上項目時間必須在1至14小時之間。
我們可以通過check約束或外鍵約束來實現這類業務規則。對于一些非常復雜的業務規則,如:
一名教員每周不能少于30小時工作量,其中分為辦公時間、實驗時間和上課時間。每1小時的課需要0.5小時辦公時間進行備課。每1小時實驗需1小時辦公準備。每周指導學生論文時間不少于2小時。
類似上述的業務規則需要從多個表中收集數據,故在程序代碼中實現最為合適。
識別關鍵業務規則
記錄所有的業務規則并對這些規則進行分類能幫助我們更好的在系統中實現業務邏輯。
如何實現業務規則不僅與當前的業務邏輯有關,而且與該業務邏輯將來如何變化有關。當一個規則在將來很可能變化時,我們需要使用更復雜但更靈活的方式構建該規則。
舉例來說,假設公司只能向當地設有倉庫的城市發貨,這些城市包括:南京、長沙、西安、廣州。業務規則要求訂單中的發貨城市字段必須為NJ、CS、XA、GZ之一。
我們可以把該規則簡單的實現為check約束。但將來公司若在上海有了一個新倉庫,就必須從后臺數據庫端修改該check約束。若公司隨后設立更多新倉庫或業務規則變化為可以向沒有倉庫的城市發貨,每次我們都需要修改該約束。
考慮另一種實現該業務規則的方法——使用外鍵。我們創建一張ShippingCities表,其中存放值:NJ、CS、XA、GZ,并讓訂單表中的發貨城市字段外鍵引用ShippingCities表中的主鍵。這樣訂單的發貨城市列只能接受ShippingCities中存在的城市。當支持的發貨城市增加或減少時,只需要在ShippingCities中插入或刪除記錄。
兩種方式的實現難度差異不大,但前一種方式每次都需要修改數據庫結構,后一種只需要修改數據。修改數據不僅更省力而且技術要求也更低。
上述業務規則實現為check約束可能如下:
ShippingCity = ‘NJ’ or ShippingCity = ‘CS’ or ShippingCity = ‘XA’ or ShippingCity = ‘GZ’
上述代碼并不復雜,但只有熟悉數據庫的程序員從后臺才能修改。ShippingCitis表中的數據相對更易于理解,我們可以提供一個界面來讓用戶自己維護其中的城市。
要識別關鍵業務規則,我們可以問自己兩個問題。
第一、修改規則會有多困難。越是復雜的規則,修改起來越困難且更容易出錯。
第二、規則變化的可能性有多大。變化頻繁的規則需要額外的設計來更好的應對將來的變化。
需要特別注意的規則(關鍵業務規則):
- 枚舉值。例如:有效的發貨城市,訂單狀態(Pending, Approved, Shipped)等。
- 計算參數。例如:對500元以上的訂單免運費。這一數值可能在將來會調整為300元或600元。
- 有效參數。例如:項目組可由2至5人組成。某些項目是否可能由1個人完成或有更多人參與。
- 交叉記錄和交叉表檢查。例如:訂單中可訂購的貨品數量不能超過該貨品的當前庫存數。
- 可概括性約束。如果可預見到將來需應用一些類似的約束,我們可以考慮把這些約束抽象出來進行管理。例如:某保險公司最近主推保險產品A。對每月能賣出20份A產品的銷售人員給予1000元獎金。對于不同的保險產品在不同的時間段可能有不同的推廣獎勵規則。我們可以把產品名稱、編號、銷售量、獎金數額、促銷時間段提取出來放到一張獨立的表中作為計算獎金的參數。
- 非常復雜的檢查。有些檢查規則非常復雜,把這些規則放到程序代碼中實現更為容易和清晰。例如:學生選擇理學院的謂詞演算課程的前提是已通過理學院的命題演算課程或已通過社科院的邏輯I和II課程或者需要導師的允許。該規則在某些數據庫產品中可以通過表級的check約束實現,但放到程序中更易于維護和理解。
一些直接可以在數據庫中實現的業務規則:
- 固定枚舉值。例如:性別(男、女),用手習慣(左撇子、右撇子)。
- 數據類型要求。每個字段具有確定的數據類型是關系型數據庫的重要特性之一。濫用通用的數據類型(如string)對性能和數據防錯都會帶來損害。
- 必填值。例如:會員必須有手機聯系方式。
- 合理性檢查。合理性檢查設定的范圍基本不會變化。例如:商品的價格大于等于0。
作為軟件從業人員不要拒絕或回避變化。世界上唯一不變的就是變化。在收集業務規則時多去了解該規則的業務背景與歷史變化歷程,而不是逼迫客戶保證規則不會變化。盡可能發現所有的業務規則并記錄下來。對這些業務規則按變化的可能性和修改難度進行分類,精心設計那些將來可能變化且修改困難的規則。
#p#
提取關鍵業務規則
識別并分類業務規則之后,我們需要在數據庫中或數據庫外來實現關鍵業務規則。我們可以參考如下方法:
1. 若規則為檢驗一組有效值時,把該規則轉化為外鍵約束。先前舉例中的有效發貨城市就是一個很好的例子。創建ShippingCities表,填入允許的發貨城市。然后把Orders表的ShippingCity列設為外鍵,引用ShippingCities表的主鍵。
2. 若規則為參數可能變化的計算式時,把這些參數提取到一張表中。例如:一個月內賣出總價超過100萬元汽車的銷售員能獲得500元獎金。把參數100萬元和500元提取到一張表中,如果需要甚至可以把一個月的時間段也作為參數提取出來。
我還見過一些軟件系統在數據庫中有一張通用的參數表。該通用參數表中存放系統需要的各種參數,一些是用于計算、一些是作為檢驗、另一些決定系統的行為。每一條記錄有兩個字段:Name和Value。例如需要確定一名銷售員能獲得多少獎金,我們先要查找Name字段為BonusSales的記錄,檢查該銷售員的銷售額是否達到了Value字段的金額,若答案是肯定的再查找Name字段為BonusAward的記錄來確定獎金數額。這種設計另有一好處,在程序啟動時可以把通用參數表讀入內存的某集合中,此后使用參數值時就無需再次連接數據庫。
3. 若邏輯或計算規則很復雜時,則提取到代碼中進行實現。這里說的代碼可以是應用程序端代碼,還可以是數據庫端存儲過程。把規則放到代碼中實現的意義在于業務規則與數據庫表結構分離了,規則的變化不會影響到數據庫表結構。通過結構化編程或面向對象編程來實現復雜的規則更易于維護。
舉一個綜合性的例子:
一本關于數據庫設計的書籍賣出前5000本的版稅為5%,5000本至10000本之間的版稅為7%,超過10000本后的版稅為10%,不同類型書籍的版稅可能不同。
上述規則比較復雜且包含多個可能變化的參數,故使用第1、2條方法。我們可以通過存儲過程來實現該規則,并把參數隔離到一張參數表中進行維護。創建的參數表為RoyaltyRates,并通過BookId與Books關聯(如圖1所示)。這樣為不同書籍創建新的版稅規則就非常容易了。
圖1 參數表RoyaltyRates與Books表的關系
多層應用的概念大家都不會陌生。三層應用是最常見的分層方法。對于復雜的業務邏輯一般會在中間層(即業務層)中實現。對于一些基本的驗證,如必填信息、數字有效區間等,需要在最上層用戶界面以及最底層數據庫端進行雙重檢驗。數據庫端的約束是阻隔臟數據進入系統的最后一道防線,而用戶界面處的檢驗可以避免錯誤數據傳輸到系統后端才被拒絕,節省了系統資源。
注:關于多層應用的更多資料請參見最后的“總結與參考”部分。
主要內容回顧
1. 業務規則決定了業務如何運行,其涵蓋從簡單明了的入門打卡到復雜的獎金計算公式。
2. 對于數據庫而言,業務規則將影響到數據模型。業務規則確定了每個字段的域(值的類型和范圍),是否是必須的,以及該字段要滿足的其他條件。
3. 理解業務規則并識別那些需要特別處理的關鍵規則至關重要。
4. 有些規則簡單且基本不變,它們可以很容易的用數據庫特性來實現。其他的一些規則可能復雜或時常變化,我們可以把它們從數據庫中邏輯的或物理的隔離出來(隔離到參數表、存儲過程或業務層中),使它們易于修改。
多層應用參考
1. 談談對于企業級系統架構的理解(http://www.cnblogs.com/liping13599168/archive/2011/05/11/2043127.html)
2. Multitier architecture(http://en.wikipedia.org/wiki/Multitier_architecture)
3. Software Architecture, Architects and Architecting(http://www.bredemeyer.com/)
原文鏈接:http://www.cnblogs.com/DBFocus/archive/2011/06/08/2075795.html
【編輯推薦】