服務應該總是返回 DTO,還是它們也可以返回域模型?
我正在(重新)設計大型應用程序,我們使用基於 DDD 的多層架構。
我們有帶有數據層(儲存庫的實現)、域層(域模型和介面的定義 - 儲存庫、服務、工作單元)、服務層(服務的實現)的 MVC。到目前為止,我們在所有層中都使用域模型(主要是實體),並且我們僅將 DTO 用作視圖模型(在控制器中,服務返回域模型,控制器創建視圖模型,並將其傳遞給視圖)。
我讀過無數關於使用、不使用、映射和傳遞 DTO 的文章。我知道沒有任何明確的答案,但我不確定是否可以將域模型從服務返回到控制器。如果我返回域模型,它仍然永遠不會傳遞給視圖,因為控制器總是創建特定於視圖的視圖模型——在這種情況下,它似乎是合法的。另一方面,當領域模型離開業務層(服務層)時感覺不對。有時服務需要返回域中未定義的數據對象,然後我們必須將新對象添加到未映射的域中,或者創建 POCO 對象(這很醜陋,因為有些服務返回域模型,有些有效地返回 DTO)。
問題是 - 如果我們嚴格使用視圖模型,是否可以將域模型一直返回到控制器,或者我們是否應該始終使用 DTO 與服務層通信?如果是這樣,是否可以根據服務需求調整域模型?(坦率地說我不這麼認為,因為服務應該消耗域所擁有的。)如果我們應該嚴格遵守 DTO,它們是否應該在服務層中定義?(我想是的。)有時很明顯我們應該使用 DTO(例如,當服務執行大量業務邏輯並創建新對象時),有時很明顯我們應該只使用域模型(例如,當會員服務返回貧血使用者( s) - 創建與域模型相同的 DTO 似乎沒有多大意義) - 但我更喜歡一致性和良好實踐。
Article Domain vs DTO vs ViewModel - 如何以及何時使用它們?(以及其他一些文章)與我的問題非常相似,但它沒有回答這個問題。文章我應該使用 EF 在儲存庫模式中實現 DTO 嗎?也類似,但它不處理 DDD。
免責聲明:我不打算使用任何設計模式,因為它存在並且很花哨,另一方面,我想使用好的設計模式和實踐也因為它有助於設計整個應用程序,有助於分離擔心,即使使用特定模式不是“必要的”,至少目前如此。
領域模型離開業務層(服務層)感覺不對勁
讓你覺得你正在拉出膽量,對嗎?根據 Martin Fowler 的說法:服務層定義了應用程序的邊界,它封裝了域。換句話說,它保護了域。
有時服務需要返回域中未定義的數據對象
你能提供這個數據對象的例子嗎?
如果我們應該嚴格遵守 DTO,是否應該在服務層中定義它們?
是的,因為響應是您的服務層的一部分。如果它被定義為“其他地方”,那麼服務層需要引用該“其他地方”,為您的千層面添加一個新層。
是否可以將域模型一直返回到控制器,或者我們是否應該始終使用 DTO 與服務層進行通信?
DTO 是一個響應/請求對象,如果您將其用於通信,則它是有意義的。如果您在表示層中使用域模型(MVC-Controllers/View、WebForms、ConsoleApp),那麼表示層與您的域緊密耦合,域中的任何更改都需要您更改控制器。
創建與域模型相同的 DTO 似乎沒有多大意義)
這是 DTO 對新人來說的缺點之一。現在,您正在考慮重複程式碼,但隨著項目的擴展,它會更有意義,特別是在不同團隊被分配到不同層的團隊環境中。
DTO 可能會給您的應用程序增加額外的複雜性,但您的層也是如此。DTO 是您系統的一項昂貴功能,它們不是免費的。
為什麼使用 DTO
本文提供了使用 DTO 的優點和缺點, http ://guntherpopp.blogspot.com/2010/09/to-dto-or-not-to-dto.html
總結如下:
何時使用
- 對於大型項目。
- 項目壽命為10年及以上。
- 戰略、任務關鍵型應用程序。
- 大型團隊(5人以上)
- 開發人員在地理上分佈。
- 領域和表現形式不同。
- 減少成本數據交換(DTO 的初衷)
何時不使用
- 中小型項目(最多 5 名成員)
- 項目壽命為2年左右。
- GUI、後端等沒有單獨的團隊。
反對 DTO 的論據
- 程式碼重複。
- 開發時間、調試成本。(使用 DTO 生成工具<http://entitiestodtos.codeplex.com/>)
- 您必須始終同步兩個模型。(我個人喜歡這個,因為它有助於了解變化的連鎖反應)
- 開發成本:需要額外的映射。(使用自動映射器,如<https://github.com/AutoMapper/AutoMapper>)
- 為什麼數據傳輸對象 (DTO) 是反模式?
與 DTO 的爭論
- 沒有 DTO,表示和域是緊密耦合的。(這對於小型項目來說是可以的。)
- 介面/API 穩定性
- 可以通過返回僅包含絕對需要的那些屬性的 DTO 來為表示層提供優化。使用linq-projection,您不必拉出整個實體。
- 為了降低開發成本,使用程式碼生成工具