跳至頁尾內容
Iron Academy Logo
C#常見問題

CQRS 處理器(C#)具有領域邏輯和管道 - 通過 Derek Comartin 的影片解釋

[[academy-video-youtube({"vid": "oxs46k1fLTA", "start_time": "0", "title": "Clean Up Bloated CQRS Handlers with Domain Logic & Pipelines", "creator": "Derek Comartin", "length": "8m 03s"})]]

命令查詢責任分離 (CQRS) 是 .NET 應用程式中一個強大的設計模式,有助於保持讀取和寫入操作的明確分離。 這種分離能夠提高可擴展性、可測試性以及對複雜業務邏輯的控制。 然而,隨著應用程式的成長,C# 中的 CQRS 處理程式可能會因邏輯過於膨脹而變得難以維護和測試。

在他的影片《使用域邏輯和管道清理膨脹的 CQRS 處理程式》中,Derek Comartin 說明安全清理這些 CQRS 命令處理程式的方法,透過將邏輯轉移到域模型和結構化管道以逐步管理命令邏輯。在這篇文章中,我們將詳細探討 Derek 的方法,並學習如何構建更具可維護性的 C# CQRS 實作。

膨脹處理程式的問題

Derek 首先指出許多 web 應用程式中常見的情況:當您打開 C# 中的 CQRS 處理程式時,它一團亂。 內含資料驗證、授權、業務邏輯、狀態轉換、事件發佈、記錄——都糾纏在一起。

他用一個調度發貨的命令物件來說明這一點。 處理程式負責:

  • 存取資料儲存來載入運送。

  • 檢查運送狀態是否準備好。

  • 更新狀態(即,更新資料)。

  • 將更改保存回資料存取層。

  • 發送電子郵件。

  • 發佈域事件。

這一切都在一個地方發生。 這違背了 CQRS 模式的初衷,其目標是分離關注點並提升性能及可維護性。

將域邏輯移動到資料模型中

Derek 的第一步是將驗證和狀態轉換邏輯移入資料模型。 他在貨運類別中建立了一個 Dispatch() 方法。 這就是域邏輯現在所在的地方。

不再在處理程式中手動檢查運送狀態,邏輯封裝在此方法中,確保了資料完整性和 一致行為,無論在何處觸發調度。 這是在基於 CQRS 的應用中實行乾淨架構的關鍵。

例如,任何地方調用 shipment.Dispatch() 都會自動執行所有驗證和狀態轉換。 這與 CQRS 設計模式一致,有助於保持處理器與域邏輯之間的明確分隔。

集中化邏輯的重要性

Derek 指出,這種變化不是為了新增不必要的抽象層。 相反,它是將跨應用程式程式碼不同部分使用的邏輯集中化。 如果多個命令處理程式需要調度運送,那麼此自定義邏輯應當位於一個地方——域模型內。

這使得您的資料模型更加健壯,CQRS 處理程式的 C# 實現更簡單且易於維護。

引入管道模式

為了進一步清理命令處理程式,Derek 引入了一個管道模式。 這個結構將命令作為一系列的小型、單一目的的步驟來處理,每個步驟獲取一個上下文物件並調用下一個步驟。

這在概念上類似於 ASP.NET Core 的中介,每一步專注於流程中的特定部分:

  • 檢索貨物(即,讀取資料)

  • 派送(執行寫入操作)

  • 發佈事件

  • 保存到資料儲存

這些步驟使用共用的命令物件在管道中流通。這創造了一個乾淨且模組化的命令和查詢責任分離實現。

管道的範例實現

在他的範例實作中,Derek 結構化了管道,其步驟如:

  • 載入運送 – 使用倉儲從資料存取層提取資料。

  • 發送運送 – 調用 Dispatch() 方法來應用域邏輯。

  • 新增域事件 – 將 "ShipmentDispatched" 事件附加到上下文。

  • 發佈事件 – 調度事件以通知外部系統。

  • 保存更改 – 將更新持久化到資料儲存。

每個步驟代表了命令邏輯的一個獨立部分,增強資料驗證並保持職責分隔。

Derek 也指出,電子郵件通知現在是通過響應域事件單獨處理的。 這符合事件來源原則,促進最終一致性。

測試與維護的好處

這個模式的最大好處之一是可測試性。 一個大的命令處理程式可能擁有多個依賴(例如,倉儲、郵件服務、日誌)。 當您將處理程式分解為管道步驟時,每個步驟只需要幾個依賴。

這種模組化的方法允許您輕鬆地使用依賴注入測試個別步驟,根據需要使用假物件或模擬物件。 例如,如果您正在測試調用 Dispatch() 的步驟,您不需要模擬一個電子郵件服務或事件發佈器。

這種關注點分離遵循責任分離的CQRS模式,使讀寫模型更乾淨且更專注。

可組合性與重用性

管道方法的另一個好處是,它具備可組合性。 如果您使用像 Outbox 模式之類的東西,您可以確保事件只在寫入模型被持久化之後才被發佈。 這種控制在關心一致性和交付保證的 CQRS 實現中至關重要。

您也可以在不同的 CQRS 處理程式中共享步驟——例如,一個通用的 "SaveChanges" 步驟或一個 "ValidateRequest" 步驟。

使用像 MediatR 程式庫那樣支援命令和查詢處理的工具,您甚至可以透過 .NET Core 應用程式中的 IServiceCollection 服務注入來註冊這些步驟。

為了建立這個系統,您可能會透過 Visual Studio 的套件管理器控制台執行 Install-Package MediatR——這是一個實施 C#中 CQRS 的常見步驟。

權衡過程

Derek 並不避諱這種方法所帶來的複雜性增加。 管道引入了間接性,當您查看調用堆棧時,感覺就像在迷宮中穿行。

然而,對於複雜的業務邏輯,這樣的權衡往往是值得的。 如果一個處理程式有 10 多個依賴和數百行邏輯,CQRS 可以讓開發人員更好地構建和維護這些流。

何時進行重構的最後想法

Derek 在結尾提醒觀眾仔細考慮他們的 CQRS 處理程式 C# 實作是否真的是膨脹的。 並非每種情況都需要管道。他的目標是展示可能性,而開發人員需自行評估他們的 CQRS 實作以決定此類模式是否有所幫助。

他鼓勵開發人員檢視程式碼中關注的分隔能幫助保持一致性、使程式碼更模組化、並更好地管理讀寫操作的區域——尤其在 CQRS 網頁應用中。

結論

Derek Comartin 的影片 提供了一個實用指南,使用域邏輯封裝和管道清理 CQRS 處理程式。 這種方法有助於解決程式碼膨脹問題,促進資料完整性,並通過將應用程式程式碼細分為不同的模型來增強可維護性。

不管您是在處理員工資料、產品詳細資料,還是新的使用者命令,採用適合管道和域驅動設計的 CQRS 模式會讓您的程式碼庫更加可擴展、可測試且穩健。

透過使用資料傳輸運算元、分離模型以及保持讀寫邏輯的明確分隔,您的 .NET 應用程式將更具結構,並更易於隨時間變化而發展。

Hero Worlddot related to CQRS 處理器(C#)具有領域邏輯和管道 - 通過 Derek Comartin 的影片解釋
Hero Affiliate related to CQRS 處理器(C#)具有領域邏輯和管道 - 通過 Derek Comartin 的影片解釋

分享您所愛以賺取更多報酬

您是否為使用 .NET、C#、Java、Python 或 Node.js 的開發者建立內容?將您的專業知識轉化為額外收入!

Iron 支援團隊

我們線上24小時,每週5天。
聊天
電子郵件
給我打電話