埃文斯分類
2005 年 12 月 14 日
艾瑞克·埃文斯在他的傑作 領域驅動設計 中,對您可能會遇到的不同種類的領域物件進行分類。
- 實體:具有獨特身分,貫穿時間和不同表現形式的物件。您也會聽到它們被稱為「參考物件」。
- 值物件:僅以其屬性的組合為重要的物件。所有屬性值都相同的兩個值物件被視為相等。我也在 P of EAA 中描述了 值物件。
- 服務:在您的領域脈絡中的一個獨立操作。服務物件將一個或多個服務收集到一個物件中。通常,在您的執行脈絡中,您只會有一個每個服務物件類型的執行個體。
這個分類與我在領域模型中需要的經驗非常吻合。問題在於,這三者很難精確定義,它們屬於「我看到時就會知道」的範疇。
因此,一些範例可能會有幫助。實體通常是像客戶、船舶、租賃合約等大型事物。值通常是日期、金錢、資料庫查詢等小事物。服務通常是對外部資源的存取,例如資料庫連線、訊息閘道、儲存庫、產品工廠。
實體與值之間有一個明確的區分,就是值會覆寫相等方法(因此也會覆寫雜湊),而實體通常不會。這是因為你通常不希望在處理內容中有多個物件代表同一個概念實體,但你不在乎有多個「5.0」物件。值可以是基本型別(在有區分的語言中)或有特殊的語言支援(例如 .NET 中),但它們不必如此。一個重要的規則是值物件應該是不可變的(否則你會遇到各種別名錯誤問題)。要變更值(例如我的身高),你不會變更身高物件,而是用新的物件取代它。
服務物件通常透過使用全域變數、類別欄位(Robert Martin 術語中的單一狀態)或單例來實作。它們當然通常是單一的,因為你只有一個,但你如何做到這一點則有更多變化。通常單一性是在處理內容中,因此在多執行緒環境中每個執行緒一個。無論如何,你都應該確保你的實作機制對其他網域物件隱藏,以便你可以輕鬆變更它。Eric 在他的書中指出服務應該是無狀態的,雖然我們已經討論過這一點,但他不再認為有必要,雖然如果你能做到這一點會很好。
這個領域的問題之一是,這個術語雖然令人聯想到,但卻與其他想法混淆不清。實體通常用來表示資料庫表格或對應資料庫表格的物件。服務有整個服務導向架構在進行,以及應用程式架構中的服務層。因此,如果我使用這些術語,我必須清楚說明我在網域模型的內容中使用它們,並根據 Eric 書中的含義使用它們。因此,要小心假設人們像這樣使用這些字詞,它們被嚴重過載了。遺憾的是,沒有太多替代方案。