領域物件初體驗

昨天已經稍微學會了依據應用程式的功能面,將程式切割成數個專案分別處理該有的功能。今天就先來學習阿源哥哥向來認為整個應用程式靈魂所在(最值錢的)的領域物件部分。

為解決某項領堿問題而設計的物件

為了不一下子就要將整個應用程式所要使用到的領域物件全部設計出來而造成學習上的挫折感,今天先假設要簡單地來學習對於外送很重要資訊之一的外送地址的設計。

講到地址,或許有人認為,啊!不就是一個字串型別讓使用者填寫例如:「高雄市鳥松區大埤路涵碧巷300號11樓」之類的有什麼好設計的?但是請想一想,假如有一家店是開在高雄市湖內區,該家店有可能會去高雄市那馬夏區外送嗎?(雖然同在一個縣市)但是卻有可能願意送到台南市南區(雖然在不同縣市)。所以一項地址的資訊應該可以切割出其所在的行政區域(區、鄉、鎮)才對。

地址資訊除了可以用來決定某行政區是否在外送區域之外,如果是用在搬家公司的估價上,也可以用遷出地址的行政區和遷入地址的行政區做為估價的計算基準,所以光是一串字串是不夠的,因為填寫人有可能將前面所提的例子寫成:「高市鳥松大埤路涵碧巷300号11F」,填寫人認為這樣寫郵差看得懂,是沒錯啦,但是電腦看不懂。所以地址資訊至少要以三個物件關聯組合才夠(如果還要區分到街道,那就要四個了)。

對於領域物件的設計,以程式語言的觀點來講也只是設計個類別(Class)而已,所以先在 Domain 專案裡加入一個類別,類別的名稱(請千萬不要用中文命名)取個有意義的,因為是要儲存台灣所有的縣市,所以就命名為 City.cs 吧!

接著加入如下的程式代碼,習慣上我們都會為每一個物件加入一個主鍵(Primary Key),一般的命名規則會以:類別名稱 + Id 或 Id 來命名,阿源哥哥是習慣以 Id 來命名。 如果沒特別需要會以 int 當該主鍵值的型別(往後會再介紹其他型別的使用時機),字串(string)型別的 Name 用來儲存例如:台北市、新北市、台南市、高雄市 ..... 等縣市名稱: 

namespace Demae.Domain
{
    public class City
    {
        public int Id { get; set; }        
        public string Name { get; set; }
    }
}

同樣地也為區域設計一個類別,就命名為 Area.cs 並加入如下的程式代碼:

namespace Demae.Domain
{
    public class Area
    {
        public int Id { get; set; }       
        public string Name { get; set; }
    }
}

一對多的關聯

一個縣市內有許多鄉鎮(或區),一個鄉鎮只能屬於一個縣市,因此先前所設計的 City 和 Area 類別之間有一對多的關聯,接著就來為這兩個類別加入相關聯的程式碼:

在 City.cs 的程式碼中加入 public virtual ICollection Areas { get; set; } 表示在一個縣市下有許多的鄉鎮,加入後的程式碼如下:

namespace Demae.Domain
{
    public class City
    {
        public int Id { get; set; }        
        public string Name { get; set; }
        public virtual ICollection<Area> Areas { get; set; }
    }
}

在為 Area.cs 類別加入關聯之前,先為 Domain 專案安裝 System.ComponentModel.Annotation 套件:

接著再為 Area.cs 類別加入 public City City { get; set; }表示一個鄉鎮是屬於某一縣市,並以 [ForeignKey("CityId")] 修飾詞來說明該兩物件間是以 CityId 為外來鍵做關聯,請記得要加入 using System.ComponentModel.DataAnnotations.Schema;命名空間的參考:

using System.ComponentModel.DataAnnotations.Schema;

namespace Demae.Domain
{
    public class Area
    {
        public int Id { get; set; }       
        public string Name { get; set; }
        public int CityId { get; set; }
        [ForeignKey("CityId")]
        public City City { get; set; }
    }
}

這樣縣市與鄉鎮的一對多關聯就已經建立。

註:
物件之間除了有:《一對多》的關聯之外,還有《一對一》和《多對多》的關聯,往後會再以更多的實例來講解說明。

接下來就是今天重頭戲的地址物件了,類別名稱為 Address.cs 程式碼如下,以 Area 型別的屬性就可以知道該地址是在哪一個行政區,而 Area 往上對也可對應到哪一個縣市,字串型別的 Line 屬性是用來儲存街道名稱和號碼樓層等其他地址資訊:

namespace Demae.Domain
{
    public class Address
    {
        public int Id { get; set; }
        public int AreaId { get; set; }
        [ForeignKey("AreaId")]
        public Area Area { get; set; }
        public string Line { get; set; }
    }
}

好吧,今天就學習到這裡,明天再來學習如何將領域物件對應到資料庫的資料表,以用來將這些資料儲存到資料庫中。