2017-04-10 77 views
3

試圖重構一些代碼。我看到有些類正在創建DTO對象,這些對象正在服務層中傳遞,並由@RestController稍後返回。據我所知,最好只在控制器中構建數據傳輸對象,並將它們傳遞給視圖,特別是當我們使用類似WrapperDTO<T>的get和set值時。當我們用複雜的對象或簡單的數據類型構建WrapperDTO時,可能會有差異。所有oppinions將不勝感激。數據傳輸對象DTO要在哪裏構建

+0

我想你應該看看[這裏](https://softwareengineering.stackexchange.com/questions/277817/what-is-the-best-way-to-create-dtos-from-entities-and-更新實體從dtos) –

回答

5

DTO可用於在應用程序的不同層之間傳輸數據:DAO,Service,Facade,Controller。根據我的經驗,DTO是一個有見地的話題。

在我看來,轉換越晚越好,如果不需要轉換就更好。通常,後者處於應用程序邊界。 DTO不是免費的,它涉及到繪圖和支持。因此,當存在領域模型不匹配或模型技術不匹配時,DTO將是有意義的。欲瞭解更多信息,你可以看看LocalDTO article and the associated link

如果我專注於服務 - >門面 - >控制器層:

  • 服務:他們在做服務的東西,他們可能會叫對方做自己的處理。如果您的域模型在整個服務範圍service => facade中保持一致,則將結果轉換爲DTO爲時尚早。

  • 外牆:他們可以編排服務和轉換輸入/輸出。以我的觀點來看,它將成爲轉換或轉換DTO的合適地點。但只有當它需要時,即。因爲您的域模型必須跨越此邊界進行轉換(過濾字段,聚合...)

  • 網關/控制器:它們位於應用程序邊界。它們的邏輯很簡單,簡化爲邊界邏輯。門面和控制器之間的關係通常是one <-> one。 ***

    合併外牆及控制器通常意義


因此,在我的觀點,你的第一個建議是更適應如。 UserController....。最重要的是要保持務實。

+1

一個很好的,平衡的答案。我在DTO和域對象上寫了幾個帖子,大體上也得出了相同的結論。 https://notesofapragmaticprogrammer.wordpress.com –

2

我會說最好在服務層上創建DTO。

控制器不能知道業務邏輯細節。例如。我們需要返回用戶信息,但一些字段(密碼等)必須排除在外。這些字段存在於用戶實體中,但必須從DTO中刪除。

另一種情況我們在Controller上得到了SomePaginationDTO,我們仍然需要通過DTO來服務解析過濾器,應用排序,限制結果等。所有的邏輯都是服務責任的一部分。所以我會通過SomePaginationDTO來服務。

+1

我有不同的想法。我完全同意SomePaginationDTO,我使用動態DTO(地圖),甚至可以請求「僅某些字段」服務(以類似的方式進行排序,過濾和分頁)。如果我想'用戶無密碼',我使用這種機制。或者,我從控制器的服務中獲得一個實體(或完整的DTO),並在控制器中創建「(動態)dto無密碼」。如果我沒有字段選擇機制,我不會在服務上創建一個getUserNoPassword()方法,我會在控制器中對DTO進行轉換。我不確定這是商業邏輯,對我來說似乎更多的控制器視圖邏輯。我錯了嗎 ? –

+0

對於我來說,控制器不應該知道如何限制數據或者應該如何返回數據。這是IMHO服務的一部分。控制者的職責是數據傳輸(marshall unmarshall),安全檢查,過濾,錯誤處理。 – StanislavL

+0

謝謝。但是如果服務沒有實現選擇列?或者,也許更常見:如果該服務沒有實現排序或分頁,那麼您在哪裏執行內存中的排序或分頁?我在控制器中執行此操作,並以相同的方式在不支持服務時執行屬性/列選擇。它也可能只是一個UI功能,可能是每個用戶的偏好。我真的很想聽聽這個意見。 –

0

我會說沒有正確的方法來執行此操作。這取決於DTO的用途。

我發現了一個簡單的規則,我可以在哪裏使用DTO服務級別和不在哪裏:如果服務級別只有一個客戶端,我在服務級別使用DTO。如果有兩個或更多的客戶端,最好不要在服務級別使用DTO。

讓我更詳細地解釋了這一點:

基本上很顯然,這還不包括DTO到服務級別需要更多的努力。因此,如果只有一個客戶端,我會保持簡單,並使用DTO作爲服務方法的返回類型。

如果有多於一個客戶端的服務,最有可能的客戶端將需要不同的DTO(例如我想有一個對象的jsoncsv表示)。在這種情況下,我不會從服務中返回DTO。否則,我就需要爲每個DTO,或不同的服務方法等有不同的服務

注:我不是說,如果你沒有在服務級別使用DTO必須移動轉換邏輯進入控制器級別。我仍然認爲控制器級別必須儘可能簡單。您可能在控制器和服務之間存在一些中間轉換級別 - 不舒服,但是它有好幾種服務。

-1

作爲其他問題的一部分,我發現了一個很好的答案。當然這/我的答案不參與賞金。這只是一個人的靈感來解釋如何實施現在的事情。所以看看:

  • 模型類。他們沒有得到任何東西的獲取者/定位者。它 取決於模型邏輯。否則,你會得到模型,你可以很容易地打破一致性 。或者哪裏有許多不明顯的事情。假設你有 有User.registrationDate字段。當你構建一個新的用戶對象時,你不應該忘記通過 指定的字段註冊日期字段。所以,只需在您的 構造函數中添加registrationDate初始化並刪除setter!
  • 存儲庫接口就在您的模型中。假設你有一些 業務邏輯取決於現有的存儲對象。您不能將 明確地從您的域邏輯引用到基礎結構 依賴關係(如JPA,Hibernate,JDBC等)。因此,您從接口查詢此存儲的 對象。
  • 商業服務(可選)。他們執行一些複雜的邏輯,涉及許多不同的實體,不包括安全性和事務管理。你的問題是關於它的。是的,如果您需要在您的域邏輯中查詢實體的 ,請將查詢放入存儲庫 並從您的業務服務中調用它。
  • 基礎架構包內的存儲庫實現。使用JPA或mockito或其他方法實現 存儲庫接口。他們 也不包括安全性和交易。
  • 應用程序服務(可選)。如果有一些複雜的與基礎設施或安全檢查的交互 。
  • 遠程外觀界面。客戶端和服務器僅通過 遠程門面接口進行通信。
  • 遠程外觀實現(控制器)。將厚實體 對象轉換爲細DTO(數據傳輸對象)。所有交易 分界和安全在這裏(通常使用註釋)。

您對這種設計有什麼看法?它適用於衆所周知的彈簧mvc嗎?

相關問題