用例驅動實現DDD的方法 - codex
根據UML Distilled(第 9 章),用例是由一個共同的使用者目標聯絡在一起的一組場景(banq:特定角色的各種操作場景上下文)。在這種情況下,我們處理的是一種系統用例,它表示使用者角色與系統的之間的互動。
要表達單個互動操作的概念,請在命名用例時以動詞開頭(例如“列出動作”、“提款”、“刪除我的資料”、“支付購物車”)。在實踐中,用例只是一個函式(一個查詢或一個命令),它應該是純粹的——確定性的並且沒有副作用。(banq注:類似事件風暴中的領域事件中命令動作,注意動作是有限制的上下文BC)
用例應該是最高階別和最可見的架構實體。用例是中心。總是!資料庫和框架都是細節!沒有資料庫
用例是您的應用程式的工作單元(即其架構原子裝置)。他們應該是一等公民,以便在瀏覽其程式碼庫時應用程式的目標立即變得清晰。儘管這與程式碼組織有關,但最終會促進領域驅動架構的良好實踐。
正如房屋或圖書館的計劃對這些建築物的用例大肆宣傳一樣,軟體應用程式的架構也應該對應用程式的用例大肆宣傳 - 尖叫架構
用例驅動的方法在後端應用程式中更有意義,因為這是業務邏輯應該存在的地方。
讓我們以通過 Web API 提供服務的後端應用程式為例:
在領域驅動架構中,Web API 是由 Web 請求處理程式組成的主要介面卡(介面卡是應用程式入口點,不包含業務邏輯)。
在用例驅動的方法中,每個 Web 處理程式只是一個用例入口點——它們具有一對一的關係。因此,每個 web 處理程式都應該有它的實現檔案,包括驗證、解析、(反)序列化、呼叫域、錯誤處理、響應準備、API 文件(例如OpenAPI)、常量等。沒有其他地方可以尋找。一切盡在一處。
class CreateUserHandler( private val createUser: CreateUser, private val generateUserId: () -> UserId, ) : Handler { override fun handle(ctx: Context) { val createUserResult = createUser( ctx.bodyAsClass(UserRepresenter::class.java) .toUser(generateUserId()) ) ctx.status( when (createUserResult) { NewUser -> HttpStatus.CREATED_201 UserAlreadyExists -> HttpStatus.CONFLICT_409 } ) } private class UserRepresenter(val email: String, val name: String, val password: String) { fun toUser(id: UserId) = User( email = email.toEmail(), name = name, password = password.toPassword(), id = id ) } } |
領域
域是業務操作發生的地方。充滿域操作的“服務”/“集線器”檔案是一個壞主意。相反,為每個用例建立一個檔案並相應地命名它。具有支援用例的單個公共功能的檔案並不是一件壞事。事實上,這是一個很好的想法,因為它是模組化的和有凝聚力的。它應該是自包含的,並且僅依靠輔助介面卡來滿足其需求(例如儲存庫)。也就是說,除了實際的用例功能(包括語義驗證、編排等),在同一檔案中還包括其請求/響應模型、錯誤/異常和任何私有幫助程式。
測試
為每個用例建立一個測試檔案。每個測試檔案都會練習一個用例的所有場景。每個測試只需要注入用例的實際依賴項,而不是一堆。這些因素有助於“將測試作為文件”——自動化測試的一個目標——因為它們有助於將用例描述為使用者/客戶。
功能模組化
用例驅動的方法促進了用例之間的解耦。由於它有助於發現它們之間的共享程式碼,因此您犯該錯誤的可能性較小。
按用例組織程式碼庫是識別應用程式存在的原因。用例是應用程式的工作單元。一旦開始利用它,您就可以識別特徵、子域和有界上下文。如果有意義,這有助於建立微服務和/或按團隊拆分工作。
。。。。
點選標題見詳細原文
相關文章
- 用 F#和EventStore實現DDD領域驅動設計
- 領域驅動設計(DDD)實踐之路(二):事件驅動與CQRS事件
- 領域驅動設計(DDD)實踐之路(一)
- 用Scala和Akka實現DDD
- 讀《實戰DDD(Domain-Driven Design領域驅動設計:Evans DDD)》想到的AI
- Java用OCI驅連Oracle資料庫的實現方法JavaOracle資料庫
- 模型驅動設計的構造塊(上)——DDD模型
- 淺談DDD(領域驅動設計)
- 淺談 DDD 領域驅動設計
- DDD-領域驅動設計示例
- 用虛擬函式實現事件驅動! (轉)函式事件
- DDD實體值物件的equals和hashcode方法實現 - wimdeblauwe物件
- 去哪兒網領域驅動設計(DDD)實踐之路
- 實戰DDD(Domain-Driven Design領域驅動設計)AI
- 使用領域驅動設計DDD和CQRS實現身份驗證的微服務原始碼專案微服務原始碼
- 領域驅動模型DDD(二)——領域事件的訂閱/釋出實踐模型事件
- 領域驅動設計 (DDD) 簡介 - jannikwempe
- DDD領域驅動設計:領域事件事件
- 領域驅動設計(DDD)入門&概要
- 領域驅動設計DDD應用心得
- 使用業務能力方法實現DDD戰略建模 - pulse
- 領域驅動設計DDD和CQRS架構模式落地實踐架構模式
- redis驅動-jedis實現1Redis
- <實戰DDD(Domain-Driven Design領域驅動設計:Evans DDD)>讀後疑問AI
- 使用Spring Data JPA實現DDD聚合的動態投影Spring
- github-kgrzybek/modular-monolith-with-ddd:.NET基於領域驅動設計方法的模組化Monolith應用原始碼GithubMono原始碼
- DDD領域驅動設計初探(7):Web層的搭建Web
- 領域驅動設計(DDD)高手養成記
- 領域驅動模型DDD(一)——服務拆分策略模型
- 測試用例驅動閱讀Express原始碼Express原始碼
- 行為驅動開發(BDD)如何與領域驅動設計(DDD)結合?
- TypeScript如何實現DDD的值物件?TypeScript物件
- Vue例項方法之事件的實現Vue事件
- java單例的幾種實現方法Java單例
- 驅動跨行業採用時間序列平臺的四個用例行業
- Java實現DDD中UnitOfWorkJava
- 使用Akka實現Reactive DDDReact
- 用Rust實現單例Rust單例