# 第五章 軟體所顯示的類型
CH5 本章重點:
* 本章主要討論如何設計和簡化關聯的開始,主要專注三種模型
* ENTITY
* VALUE OBJECT
* SERVICE
---
## 關聯
關聯的控制
1. 規定一個關聯方向
2. 增加一個限定條件,以便有效的減少多重關聯
3. 減少沒必要的關聯
以下有三種關聯類型
* 一對一關聯
* 一對多關聯
* 多對多關聯
## ENTITY
1. 實體(Entity)
根據系統需求分析,寫出及畫出所有的實體(Entity),並加以說明其意義。將真實世界的人、事、物等實體,以一個方框圖來表示,如果實體必須依附其他實體而存在,則為弱實體,使用雙方v框圖表示。例如選課系統中的學生與課程兩個實體,學生的緊急聯絡人則為弱實體,因為學生轉學,則該學生的緊急連絡人。
下圖是學生選課系統中的實體:
![](https://i.imgur.com/XsLFbkG.png)
2. 屬性(Attribute)
實體擁有的特性稱為屬性(Attribute),以橢圓形來表示屬性,當屬性具有多重值時,則以雙橢圓形來表示,屬性為主鍵,則屬性名稱底下畫一條底線區別,複合屬性(Composite attribute)則為屬性再分割,衍生屬性(Derived attribute)則以虛橢圓形來表示,例如選課系統中的學生實體擁有學號、姓名、性別、地址、年齡和電話等屬性。
可以如下所示:
![](https://i.imgur.com/RYyePru.png)
課程實體其屬性如下圖所示:
![](https://i.imgur.com/aziW5tC.png)
緊急聯絡人是弱實體,必須依附著學生實體,其主鍵若設定為學生學號,則此處不必繪出,如下圖所示:
![](https://i.imgur.com/ANI9MUz.png)
3. 實體關係(Relationship)
說明各實體之間相互關聯(relationship)的限制(constraints),是指實體與實體之間如果有關聯,則將此關聯以菱形連結兩實體,並寫出對應的基數。例如:每一個學生可以選修許多課程,一門課程可以被許多學生所選;每位學生皆有一位緊急聯絡人,每位聯絡人也只對應到一位學生。
![](https://i.imgur.com/wn5U8FY.png)
當實體間的關聯為多對多時,並需將此關聯改為一個實體,如下圖所示:
![](https://i.imgur.com/8wBeqPW.png)
## VALUE OBJECT
與 Entity 相反,當一個物件沒有概念上的標識 (conceptual identity),而你只關心它的屬性時,這個物件就可以建立成 Value Object。所以值物件可以是 3, 1.5, "1234", Date(2019-10-1)、姓名、貨幣、地址,甚至是更複雜的物件等等。不過在實作上,我們會會特別指稱那些被包成物件的稱作 Value Object。
Value Object 的屬性都是為了要描述某一個事物的特徵。
Value Object 的幾項特徵,分別有描述性、不變性、概念整體性、替換性。
1. 它度量或描述了領域中的某項概念
一間房子有戶籍地址作為標示,所以在系統中你把它當作一個 Entity,但房子擁有屋齡、顏色,這些東西並不是實際的東西,而是對房子本身的度量。屋齡描述了這間房子建成後到現在的時間,而顏色是對於他外觀的描述。
2. 不變性 (Immutability)
一個 Value Object 在創建後就不能再改變了,不過作為某個物件上的描述性屬性,他可以被替換掉。繼續用房子做例子,一間房子作為 Entity,他的屬性「顏色」這個 Value Object 可以被替換掉,如從「藍色的」房子變成「紅色的」房子,但你不會說「藍色」變成了「紅色」。
實作上,我們會用 house.color = new Color('Red') 來代替 house.color.set('Red')
3. 將相關屬性組成一個「概念整體 (Conceptual Whole)」
這就像前面提到的金錢的例子,你必須要將相關的概念整合起來,才能完整且正確地描述一件事情。
想想看,當你今天要去銀行換匯時,你想拿 300 台幣換 10 美金。這時候你有可能遇到:
行員拿一支簽字筆在你的台幣上寫「變成 10 美金」
行員會收下你的 300 台幣,然後直接拿出 10 美金替換給你。
當你有如下的設計:
class Product {
protected name;
protected amount;
protected currency;
}
應該將相關的概念 amount 與 currency 合成一個 Value Object 如下:
class Product {
protected name
protected Money money
}
class Money {
protected amount;
protected currency;
}
4. 當度量與描述改變時,可以用另一個 Value Object 替換
Value Object 的可替代性前面已經稍微提到。為了顧及不變性與概念整體性,當 Value Object 被改變時,我們會重新賦值給它。
假如說要修改商品的金額從100元變成200元,程式碼會像這樣:
class Product {
protected name;
protected Money money;
__construct()(name, money) {
this.name = name;
this.money = money;
}
function changePrice(Money money){
this.money = money;
}
}
const p = new Product('A', new Money(100, 'TWD'));
p.changePrice(new Money(200, 'TWD'));
## SERVICE
serviec是作為介面的一種操作,在模型中是獨立,不向entity跟 value object 具有封裝的狀態
主要強調的是與其他物件的關西,通常是一個行為的命名
1. application service(應用)
某種功能的入口,假如要寫一個api用來註冊賬號會使用AccountApplicationService來處理註冊的服務
2. infrastructure service(基礎設施)
實現不依賴於業務(domain)的功能。簡單的例子來講,比如紀錄log,發送信件,獨立的服務
## model driven design
1. 不要和實作範式對抗
2. 把通用語言作為依靠的基礎
3. 不要一昧依賴UML
4. 保持懷疑態度