# 第五章 軟體所顯示的類型 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. 保持懷疑態度