「這就象花一樣。如果你愛上了一朵生長在一顆星星上的花,那麼夜間,你看著天空就感到甜蜜愉快。所有的星星上都好象開著花。」
——聖埃克絮佩里
摘自《小王子》
摘要
使用關係限定符可以
- 更精確地表達實體關係
- 直接指導實現**的編寫
- 使領域模型更簡單、更容易理解
讓我們觀察乙個銷售資訊系統的設計,看看關係限定符有什麼用。
領域知識:一種產品有乙個**
一種產品有乙個**,這個就算不問領域專家,也是人人都知道的常識。資料庫表結構如下。
如果你只看到**表引用了產品表的主鍵,並不能肯定產品表與**表是一對一還是一對多的關係,所以我們還在圖中加上了乙個注釋。
使用uml圖會稍稍爽一點,可以使用關聯來表示一對一的關係。
示例資料如下。
新的領域知識:每年要有一套**表
與領域專家進一步溝通之後,開發人員得知,客戶公司會每年制定一套**表,對於不同時間簽訂的銷售合同,將可能使用不同年度的**;但是每種產品每個年度只能有乙個**。看下面的資料會更清楚些。
我們需要為**表增加乙個年度字段,並修改注釋。資料庫表結構如下圖所示。
uml圖該如何修改呢?產品與**變成了一對多的關係,可以使用聚合來表示。
但是,這裡沒有表現出「一種產品每個年度只有乙個**」這個領域知識。在這種情況下,我們可以使用關係限定符來更精確地表達產品和**的關係。
年度框框到**框框的關聯表達了「乙個年度只有乙個**」這一領域知識。年度框框腦袋上面的那個「*」號表示一種產品可以有多個年度(所對應的不同的**)。
關係限定符如何對應於實現**
1. 產品實體類可以使用乙個型別為idictionary的屬性關聯**實體類。
public
class
產品set}}
當我們想知道ak47的2023年度的**時,就可以使用類似於下面的這段**。
=new
產品finder().find產品byname(
"ak47");
decimal
price
=ak47.**s[
2008
].標準**;
2. 可以為**finder新增乙個 findby產品id年度() 函式。
產品 ak47
=new
產品finder().findbyname(
"ak47");
** ak47**
=new
**finder().findby產品id年度(ak47.產品id,
2008
);decimal
price
=ak47**.標準**;
findby產品id年度()函式的返回值是乙個**實體類物件,而不是 ilist《**》,清楚地表達了「一種產品每個年度只有乙個**」這一領域知識。
3. 關係限定符的存在暗示了在插入、修改**表資料前應該驗證「產品id,年度」在**表中是唯一的。
//判斷 產品id、年度 是否已存在。(用於插入資料前的驗證)
public
bool
is產品id年度exist(產品id,年度);
//判斷 產品id、年度 是否已存在(不包括**id所在的那條資料)。(用於更新資料前的驗證)
public
bool
is產品id年度existexcept**id(產品id,年度,**id);
一些題外話
1. uml圖比er圖更有表現力麼?
是的。比起er圖,uml圖可以更加精確、自然地表達實體關係,以本文為例,主要體現在:
a) 從產品實體類到**實體類的單向關聯表達了「系統只關心某個產品的**是多少,不關心**是2500的都有哪些產品」這個領域知識。
b) 使用關係限定符可以更精確地表達一對多關係在某種限制條件下的一對一關係。
c) 雖然都能表達一對多關係,但是從產品實體類到**實體類的聚合怎麼都感覺比**表引用產品表的主鍵的這種表現方式更加自然。
2. 畫了uml圖就是物件導向的設計了麼?
這個當然不是啦。我們都知道武功包括招式和心法,二者缺一不可。如果只知招式而不知心法,則招式全無用處。某些特殊情況下可能打出來的是打狗棍法的招式,暗地裡卻是在運用全真劍法的心法,這時本質上其實是在使用全真劍法。所以建模的時候畫出標準、漂亮的uml圖固然不錯,但是真正重要的是圖形所表達的內容,這又仰仗於是否使用了正確的心法。
有的武功,甚至相同的招式卻有兩套心法,應該使用哪一套要視情況而定,如果用錯了心法,不但不能克敵制勝,反而會死得比不會武功的人還慘!當然,這些內容已超出本文的討論範圍,有興趣的朋友可以看本文的續篇《建模心法》。
參考文獻
martin fowler 著,徐家福 譯,uml 精粹(第2版)標準物件建模語言簡明指南。清華大學出版社,2002。
eric evans, 領域驅動設計(影印版)。人民郵電出版社,2007。
金庸,神鵰俠侶。1976。
引用限定符
通常,我們在乙個物件上呼叫成員函式,而不管該物件是乙個左值還是乙個右值。例如 string s1 a value s2 another auto n s1 s2 find a 此例中,我們在乙個string右值上呼叫find成員,該string右值是通過連線兩個 string 而得到的。有時,右值的...
正則邊界符 限定符
正規表示式的邊界符 開始 寫在正在表示式的始位置 結束 寫在正在表示式的結束置 let str 1a123456abcdefg1 獨立使用只要包含數字,返回值就是true let reg1 d let bool1 reg1.test str console.log bool1 true 新增邊界符 ...
關於const 限定符
很多引用自c primer一書 比如有時候需要將乙個文字中的資料複製到另外乙個文字。我們需要使用緩衝區,緩衝區的大寫我們可以自己來決定比如1024個位元組,這是乙個常量,我們使用bufsize 1024.但是bufersize物件本身是乙個變數。所以我們可以引入const限定符,它將乙個物件轉化為常...