控制你的DTO資料結構 - DZone

banq發表於2022-02-20

文中的想法最適用於實現(複雜)業務規則、狀態轉換並將其資料儲存到某個資料庫的後端應用程式。

複雜的邏輯應該在您可以完全控制內部域模型的資料結構上實現,您可以根據問題對其進行定製以簡化程式碼。

這是本文中使用的術語定義的(自以為是的)列表:

  • 領域= 要保留應用程式邏輯中最複雜部分的程式碼區域。任何架構的目標都是清理實現系統基本複雜性的環境。
  • 資料傳輸物件 (DTO)  = 跨系統邊界移動的物件,例如,編組為 JSON、XML 或二進位制格式。
  • API = 系統的入口點(REST 端點或訊息佇列)以及所涉及的 DTO。許多系統都暴露了一個 REST API,然後依次呼叫其他系統的 API。
  • 領域物件 (例如,值物件、實體、聚合)= 應用程式的內部資料結構,通常儲存在某些資料庫中,但在系統外部不可見

 

避免 DTO 的原因

  • DTO 臃腫

由 第三方方 API 公開的大多數 DTO 更通用,並且包含的​​欄位比您在應用程式中需要的屬性子集更多。理解一種稱為採用包含 3 個欄位的物件的方法比採用具有 12 個欄位(加上 2 個子列表)的引數的方法要容易得多。

  • DTO 扁平

設計 API 的一個關鍵問題是向後相容性,也就是說,當 API 明天發生變化時,不會破壞現有的客戶端。

很多時候 DTO 是扁平的,很容易退化為具有幾十個屬性的結構。另一方面,我們更喜歡在我們的領域中使用更小的結構,只有當我們更積極地將我們發現為巢狀物件的概念建模時,我們才能獲得這種結構。

領域驅動設計強調,當詞語對不同的各方有不同的含義時,這些各方可能屬於不同的有界上下文。

  • DTO 貧血

目前建立 DTO 的方法主要有 3 種:

  1. 手動寫入
  2. 從“客戶端庫”匯入
  3. 從 OpenAPI/swagger/WSDL 規範生成

選項 (3) 使得將自定義程式碼新增到 DTO 變得非常困難,而 (2) 坦率地說,這是不可能的。但是,如果您允許這些物件進入核心邏輯,您必須將行為推送到導致可怕Util或Helper類的其他地方,或者在您的服務中積累大量程式程式碼。

  • DTO 是可變的

許多(較舊的)系統仍然在其 DTO 上同時具有 getter 和 setter,特別是如果 DTO 捆綁在“客戶端庫”中或如果它們是生成的。

  • DTO 不受約束

資料傳輸物件傳輸資料。很神奇吧?他們的責任不是驗證資料或保持一致。

然而,在我們公開的 API 中,許多 Java 團隊選擇向我們的“請求”DTO新增驗證註釋(例如@NotNull,、、@Size... @Pattern) 。之後,我們只要求框架檢查所有內容。這很酷。  

然而,第 3 方 API 的 DTO從不帶有約束。

因此,任何型別的 DTO(或)在 領域中使用時都可能呈現損壞的資料。

但是這裡的“有效”意味著兩件事:

  1. 簡單的全域性約束,例如“必填欄位”。
  2. 強制執行我的域的一致性規則,例如“啟用的合同設定了啟用日期”。

如果您在領域驅動設計的上下文中探索第二條規則,您會發現聚合和領域事件

  • DTO 不受您的控制

它們可能會因外部原因而改變:您被迫升級到 V2。如果您在這些結構上編寫了數千行邏輯,那麼祝您在新結構上重寫所有邏輯會有好運。

 

相關文章