程序員過關斬將--你的業務是可變的嗎

請不要跟我說用ES或者其餘,其實不少中小公司的業務就是如此,就是基於mysql或者sqlserver 來搞這樣的業務mysql

業務場景

不知道經過D妹子的闡述,你們瞭解狀況了沒。這裏菜菜再詳細說一下。D妹子的程序記錄了訂單的log來供其餘業務(好比統計)使用,這裏就以統計業務來講,OrderLog表設計以下:sql

列名 數據類型 描述
OrderId nvarchar(100) 訂單號,主鍵
UserId int 下單用戶id
Amount int 訂單的金額
其餘字段省略...

除此以外還有一個用戶信息表UserInfo,設計以下:數據庫

列名 數據類型 描述
UserId int 用戶id,主鍵
ProvinceId int 用戶省的id
CityId int 用戶市的id
CountyId int 用戶區縣的id

涉及到拆單等複雜的訂單操做,表的設計可能並不是如此,可是不影響菜菜要說的事bash

變數的業務

如今假如要統計某個省的訂單總數,sql以下:架構

select count(0) from OrderLog o inner join UserInfo u on o.UserId=u.UserId where ProvinceId=@ProvinceId
複製代碼

有問題嗎,sql沒問題,這時候用戶A的省市區縣信息忽然變了(也許是在其餘地區買房,戶口遷移了),也就是說UserInfo表裏的信息變了,那用以上的sql統計用戶A之前省市區縣的訂單信息是否是就會出錯了呢?(產品狗說在哪下的訂單就屬於哪的訂單)sqlserver

業務的定位

以上的問題你以爲是否是很簡單呢?只要稍微修改一下表也許就夠了。可是,菜菜要說的不是針對這一個業務場景,而是全部的業務場景的設計。那你有沒有想過爲何D妹子的設計會出現這樣的問題呢?ui

深入理解業務才能避免以上相似的錯誤發生,必定要深入理解不變和可變的業務點。 拿D妹子的統計來講,你的業務是統計區域的訂單數,這個業務在產品設計上定義的是不變性,也就是說在行爲產生的那個時間點就肯定了業務性質,這個業務的性質不會隨着其餘變而變。具體到當前業務就是:用戶在X省下的訂單不會隨着用戶區域信息的變化而變化,說白了就是說用戶在X省生成的訂單永遠屬於X省。spa

談到業務性質的不變性,對應的就有業務的可變性。假如你開發過相似於QQ空間這樣的業務,那確定也作過相似訪客的功能。當要顯示訪客記錄的時候,訪客的名稱在多數狀況的設計中屬於可變性的業務。什麼意思呢?也就是說一個用戶修改了姓名,那全部顯示這個用戶訪問記錄的的地方姓名都會同時改變。架構設計

說到這裏,各位再回頭看一下D妹子的業務,這裏又牽扯到一個系統設計的問題,衆所周知,一個好的系統設計須要把業務的變化點抽象提取出來,D妹子訂單統計的業務變化點在於用戶的省市區縣會變化,訂單的金額、訂單號等信息不會變化。因此大家以爲是否是D妹子的數據表能夠修改一下呢?設計

數據表的改進

改進用戶信息

按照以上的闡述,D妹子業務的變化點在於用戶的省市區域信息,因此能夠把用戶信息的表抽象提取出來,主鍵再也不是用戶id

列名 數據類型 描述
Id int 主鍵Id,主鍵
UserId int 用戶id
ProvinceId int 用戶省的id
CityId int 用戶市的id
CountyId int 用戶區縣的id

這樣的話用戶訂單log表中就變爲

列名 數據類型 描述
OrderId nvarchar(100) 訂單號,主鍵
UserBId int 對應用戶表中的主鍵id
Amount int 訂單的金額
其餘字段省略...

這樣設計的話,若是用戶的省市區縣信息有變更,相應的用戶信息表中會存在多條用戶省市區縣數據

這裏的用戶信息表並不是是用戶對象的主表,而是根據訂單業務衍生出來的表

改進業務數據表

根據業務的變性和不變性,既然把訂單區域統計的業務定義爲不變的業務性質,那訂單的log表徹底能夠這樣設計

列名 數據類型 描述
OrderId nvarchar(100) 訂單號,主鍵
UserId int 下單用戶id
ProvinceId int 用戶省的id
CityId int 用戶市的id
CountyId int 用戶區縣的id
Amount int 訂單的金額
其餘字段省略...

寫在最後

各位讀到這裏,可能會感受菜菜此次寫的其實很雞肋,可是,D妹子的場景倒是真實環境中遇到的問題。問題的本質仍是變性業務和非變性業務的定義和劃分,和架構設計同樣,數據庫的設計其實也須要把變更的業務存儲點進行抽象,其實應該說是抽離出來。

但願你們有所收穫 --菜菜


添加關注,查看更精美版本,收穫更多精彩

image
相關文章
相關標籤/搜索