我的經理告訴我,最佳實踐是:將從服務層返回的 dto 對映到控制器。
我的想法是:控制器只有一行,只需將邏輯委託給服務層並返回響應實體,因此在能在控制器中對映一個dto。
網友建議:
1、因為你可能需要在一個服務中使用另一個服務。然後你正在混合領域物件和DTO:DTO 是外部合約,所以在我的工作中,控制器只是負責與實體物件之間的轉換。
2、如果您想對服務層做到真正嚴格和乾淨,您的內部服務不應使用透過 API 公開的相同 DTO,這為您提供了最大程度的解耦。
因此,您的服務應該返回一個內部物件或記錄,並且您應該有另一個服務從該物件轉換為 API DTO,這樣您的控制器就會有一個流程,例如將請求 DTO 轉換為內部服務物件、呼叫內部服務、呼叫服務來轉換內部服務結果響應 DTO。
這樣,領域部分只理解領域物件。控制器應該使用介面卡 服務,這個服務至少可以在 API 物件與域物件之間進行轉換或對映
3、控制器不應執行任何業務邏輯。它還有其他責任。驗證只是這些職責之一。
一般來說,控制器(例如 API 或表示層)負責將從業務層獲取的資訊轉換為客戶端可以理解的表示形式。這不可能總是在一行中完成。
- 控制器可能需要為其客戶端設定 cookie。控制器可能需要將其獲取的資料轉換為符合 hatoas 的(例如 Hal 風格)形式。
- 控制器可能不是服務 api,它也可能是 html api,需要執行更多操作,而不僅僅是從業務層返回資料。
- 控制器甚至可能根本不是控制器,它可能是一個為事件佇列轉換來自業務層的資料的元件。
我們將這些問題分開的原因是,您不希望這些責任中的任何一個洩漏到您的業務邏輯中。
鑑於此,您不應該將自己簡化為“我的控制器只允許包含一行程式碼”之類的簡單規則,因為這會導致您將技術程式碼從控制器洩漏到業務層。
4、你的問題沒有簡單的對錯之分,因為答案取決於問題:你想封裝什麼?
- 如果您在控制器中對映 dto,則 dto 將成為表示或 api 邏輯的一部分,從而主要將服務的客戶端封裝在服務內部的更改中。
- 如果您在服務中對映 dto,則 dto 將成為服務業務層的一部分,從而主要封裝服務的表示/api 層,使其免受業務層中的更改的影響。
因此,問題就變成了:您期望每個層多久更改一次?
- 如果您預計業務邏輯會頻繁更改,那麼在那裡引入 dto 層可能是明智的選擇,這樣業務邏輯的客戶端(控制器)就不必隨著業務層的每次更改而更改。
- 如果您希望 api 經常更改或者希望封裝服務的內部,那麼在那裡引入 dto 層可能是明智的選擇。
您甚至可能對這兩個問題的回答都是“是”,因此在 api/表示層以及業務層中引入 dto 層可能是明智的。
5、我們曾經將 DTO 對映到控制器中,但一旦對映中發生了業務邏輯,我就把它移到服務層。