oomusou
  • NEW!
    NEW!  Connect Ideas Across Notes
    Save time and share insights. With Paragraph Citation, you can quote others’ work with source info built in. If someone cites your note, you’ll see a card showing where it’s used—bringing notes closer together.
    Got it
      • Create new note
      • Create a note from template
        • Sharing URL Link copied
        • /edit
        • View mode
          • Edit mode
          • View mode
          • Book mode
          • Slide mode
          Edit mode View mode Book mode Slide mode
        • Customize slides
        • Note Permission
        • Read
          • Only me
          • Signed-in users
          • Everyone
          Only me Signed-in users Everyone
        • Write
          • Only me
          • Signed-in users
          • Everyone
          Only me Signed-in users Everyone
        • Engagement control Commenting, Suggest edit, Emoji Reply
      • Invite by email
        Invitee

        This note has no invitees

      • Publish Note

        Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

        Your note will be visible on your profile and discoverable by anyone.
        Your note is now live.
        This note is visible on your profile and discoverable online.
        Everyone on the web can find and read all notes of this public team.

        Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

        Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

        Explore these features while you wait
        Complete general settings
        Bookmark and like published notes
        Write a few more notes
        Complete general settings
        Write a few more notes
        See published notes
        Unpublish note
        Please check the box to agree to the Community Guidelines.
        View profile
      • Commenting
        Permission
        Disabled Forbidden Owners Signed-in users Everyone
      • Enable
      • Permission
        • Forbidden
        • Owners
        • Signed-in users
        • Everyone
      • Suggest edit
        Permission
        Disabled Forbidden Owners Signed-in users Everyone
      • Enable
      • Permission
        • Forbidden
        • Owners
        • Signed-in users
      • Emoji Reply
      • Enable
      • Versions and GitHub Sync
      • Note settings
      • Note Insights New
      • Engagement control
      • Make a copy
      • Transfer ownership
      • Delete this note
      • Save as template
      • Insert from template
      • Import from
        • Dropbox
        • Google Drive
        • Gist
        • Clipboard
      • Export to
        • Dropbox
        • Google Drive
        • Gist
      • Download
        • Markdown
        • HTML
        • Raw HTML
    Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
    Create Create new note Create a note from template
    Menu
    Options
    Engagement control Make a copy Transfer ownership Delete this note
    Import from
    Dropbox Google Drive Gist Clipboard
    Export to
    Dropbox Google Drive Gist
    Download
    Markdown HTML Raw HTML
    Back
    Sharing URL Link copied
    /edit
    View mode
    • Edit mode
    • View mode
    • Book mode
    • Slide mode
    Edit mode View mode Book mode Slide mode
    Customize slides
    Note Permission
    Read
    Only me
    • Only me
    • Signed-in users
    • Everyone
    Only me Signed-in users Everyone
    Write
    Only me
    • Only me
    • Signed-in users
    • Everyone
    Only me Signed-in users Everyone
    Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.

    Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Explore these features while you wait
    Complete general settings
    Bookmark and like published notes
    Write a few more notes
    Complete general settings
    Write a few more notes
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    1
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # Ch.01 Introducing Domain-Driven Design 筆記 ## Overview 將以 DDD 手法探討如何分析現實世界的 `訂單系統` 。 ## Garbage in Garbage out 有人認為 developer 只是寫 code。 事實上 developer 是以 software 解決問題,coding 只是其中一部分,尚包含 Communition 與 Good Design,這也是本書要強調的部份。 假如你也承認 software development 是一種 pipeline,以 `需求` 為 input,以 `解決問題` 為 output,則 `garbage in, garbage out` 法則也適用,如果 input 為 `不明確需求` 或 `不好的設計`,無論再好的 code 而無法產生預期 output。 本書 part 1:`Understanding the Domain` 就是為了減少 `garbage in`,以 DDD 為方法更清楚的 Communication 與 Good Design (Shared Domain Knowledge)。 本章節將以實際範例討論 DDD 原則並實際分析 domain。 DDD 並不是萬靈丹,也不適用於如 system software、games ... 等領域,特別適合 business 或 enterprise software,也就是 developer 必須與其他非 IT 領域的團隊一起合作,這是本書所要討論的。 ## The Importance of a Shared Domain Model ![](https://i.imgur.com/i9MXOWB.png) 在解決問題之前必須先了解問題是什麼,但可惜的是 Development Team 認知與 Domain Expert 認知不一定相同,因此可能產生 `garbage in`。 一些 software development process 使用 specification 或 requirement document 嘗試以 Development Team 角度捕捉所有問題,由小孩子玩的 `傳聲筒` 遊戲經驗可得知,訊息經過一連串人的理解與傳遞之後,訊息常常會不斷變形,因此造就彼此認知落差。 > * Developer Team:Developer、UX/UI designer、Tester > * Domain Expert:真正了解 Domain 的專家 ![](https://i.imgur.com/XXOXTew.png) Agile 採用方式是 Domain 與 Development Team 直接溝通,避免中繼人員的理解與傳遞,如此可有效避免 `訊息變形`。 但這樣仍有些缺點: * Developer Team 必須將 Domain expert 心中的 Mental Model 翻譯成 Developer 所理解的 Domain Model 用於 code 中,這仍可能造成 `訊息變形` 或忽略重要細節 * 由於 Developer 的 Domain Model 與 Domain Expert 的 Mental Model 仍有所差異,將來接手維護的 Developer 由於沒有直接與 Domain Expert 溝通過,只看到目前 code 中的 Domain Model,因此可能對真正 Domain 造成誤解 ![](https://i.imgur.com/T6fJjT1.png) DDD 則希望 Domain Expert、Development Team 、other stakeholder 都使用相同的 Mental Model 為 Domain Model,code 只是用來處理此 Domain Model 而已,而非 Developer 根據自己的理解重新建立 Domain Model。 使用共同的 Domain Model 有幾個優點: * **更短的 time to market**:避免 `訊息變形` 造成誤解而能更快速解決問題 * **更多商業價值**:避免只是做出 developer 想要的產品而非 customer 想要的產品而走偏 * **更少浪費**:更清楚的需求避免 `garbage in` 可減少將來 rework 時間,也更能儘早發現哪些才是 Domain Expert 認為重要的部分,讓 Development Team 將資源放在對的地方 * **更易維護**:由於 code 中的 Domain Model 與 Domain Expert 一致,也讓將來接手維護的 developer 更容易與 Domain 結合上手 > **The Insanely Effective Delivery Machine** > > Dan North 是一個著名的 Behavior-Driven Development 傳教士,他曾在 `Accelerating Agile` 分享在幾周內開快速開發出 trading system 經驗,他認爲成功關鍵在於 Shared Mental Model,它讓每個 developer 直接與 Domain Expert 溝通,並使用相同的 Domain Model,這使的彼此溝通非常有效率,且最後 developer 也成為 Domain Expert,並能快速建立系統 DDD 歸納出幾個 guideline 協助我們建立 shared domain model: * `將焦點放在 Business Event 與 Workflow 而非 Data Structure` * `將 Problem Domain 切割成更小的 Subdomain` * `根據 Subdomain 建立 Domain Model` * `為 Developer Team 與 Domain Expert 間建立 Ubiquitous Language` ## Understanding the Domain Through Business Events 根據 DDD 第一條 guideline: > 將焦點放在 Business Event 與 Workflow 而非 Data Structure 企業並不是只有 data,而是在於將 data 經過處理而獲利,這是一個 transformation。 到底是什麼促使 transformation 開始呢 ? 它常常是外部 trigger: * 有 email 進來 * 有電話進來 * 每天 10:00 要做 * 若沒有任何訂單就做其他事情 一開始必須將這些 Domain Event 都抓出來。Domain Event 是建立 Domain Model 的起手式。 > 如 `當收到訂單時` 就是一個 `訂單系統` 中觸發 `處理訂單` process 的 Domain Event。 Domain Events 會以 `英文過去式` 表示,表示已經發生且無法改變的事實。 ### Using Event Storming to Discover the Domain * 將所有相關人都加入討論 (Domain Expert、Development Team、other stakeholder) * 牆壁必須有 `白報紙` 或 `白板` 可貼 `便利貼` 及直接書寫 * 所有人將 Business Event 與其觸發的 Business Workflow 寫在便利貼並貼在牆 * 依 `時間軸` 先後調整便利貼順序 * 目的將所有的 Business Event 與 Business Workflow 都找出來 ### Discovering the Domain: An Order-Taking System 本書將以 `訂單系統` 為實例探討 DDD、Domain Model 與 FP 實作。 Max (總經理): > 我們是個小公司,目前訂單作業都是人工與書面處理,由於公司業務擴展迅速,目前訂單處理已經非人工所能負荷,我們希望能全面數位化處理,因此希望有個 seft-service 網站,顧客可自行處理某些訂單業務,如 `下訂單`,`查詢訂單狀態` ... 等 You: > 請開始用便利貼將 Business Event 貼在牆上: Ollie (訂單部): > 我是 `訂單部` 的 Ollie,我們會處理 `訂單` 與 `報價單` You: > 什麼事件會引發這個流程呢 ? Ollie (訂單部): > 當顧客藉由 email 將 `表格` 傳給我們時 You: > 聽起來像是 `order form received` event 與 `quote form received` event 是嗎 ? Ollie (訂單部): > 是的,讓我們將這些 event 用便利貼貼在牆上 Sam (物流部): > 我是 `物流部` 的 Sam,當 `訂單` 成立時,我們將 `接單出貨` You: > 你何時會知道該 `接單出貨` 呢 ? Sam (物流部): > 當我們收到 `訂單部` 的表格時 You: > 你會如何稱呼該 event 呢 ? Sam (物流部): > 稱為 `order avaliable` 如何 ? Ollie (訂單部): > 我們稱即將出貨的訂單為 `placed order`,我們可對該名詞統一嗎 ? Sam (物流部): > 所以稱為 `order placed` event 大家同意吧 ? ![](https://i.imgur.com/jH0Z5dJ.png) 經過一段時間討論,牆上出現以上便利貼。 由以上對話,我們可發現藉由 Event Storm 可幫助我們釐清以下幾件事情: * **凝聚各部門共識** 除了探索出 Business Event 外,因為參與者都一起看到牆上的便利貼,使得大家對整個系統凝聚共識,讓每個部門了解其他部門的 Domain,也澄清了對其他部分 Domain 的誤解,甚至 Development Team 也可發現藉由 IT 技術對整個 Business 有新的解決問題方法。 * **增進各部門了解** 多數人容易以自己的部門來思考事情,而忘記了其他部門也可能相關, Black (帳務部): > 我是 `帳務部` 的 Blake,我們也需要完整的訂單資料,藉此我們才能對顧客收費,因此我們也需要參與 `order placed` event * **找出未發現需求** 當所有 Business Event 都根據時間軸攤在牆上時,很容找出未發現需求。 Max (總經理): > Ollie (訂單部),當訂單成立時,你有告知顧客嗎 ? 我在牆上沒看到便利貼 Ollie (訂單部): > 是的,我忘記了,當訂單成立時,我們會發 email 給顧客通知訂單已經成立並準備出貨,這是另一個 event:`order acknowledgement sent to customer` event 假如問題無法馬上有明確的答案,應該將 `問題本身` 以便利貼貼到牆上,將來另外討論。 事實上很多需求一開始都很模糊,與其一開使就貿然進行開發而事後一再 rework,不如先把問題紀錄下來,另外找時間將問題釐清。 * **各部門以 Event 結合** ![](https://i.imgur.com/X7oh9vt.png) 當所有 Event 與 Workflow 都貼在牆上時,可進一步將之以 `部門分類`,如此可發現當 `訂單部` 訂單成立時,其 output 發起 `order placed` event 正是 `物流部` 與 `帳務部` 的 input。 在此階段並不討論實作細節,如該使用 message quene 或 database ... 等,這裡只在乎 Domain 中各部門的關係。 * **察覺出報表需求** 在了解 Domain 時很容易發現 rocess 與 transaction,但別忘了 reporting 也一樣重要,Event Storm 階段也可一起討論出 reporting 與 UI 部分。 ### Expanding the Events to the Edges 隨著 Event Storm 挖掘出更多的 Business Event 且依時間軸排序後,你應該不斷問自己是否最左側與最右側還存在其他 Event,試圖找出 system 的 boundary。 You: > Ollie (訂單部),什麼會引起 `order form received` event 呢 ? Ollie (訂單部): > 每天早上我們會開啟 email 查看是否有新的 `訂單` 或 `報價單` You: > 所以聽起來我們還需要 `mail received` event 嗎 ? 同理我們也可找出 system 最右側的 boundary。 You: > Sam (物流部),是否存在任何 event 在 `Order shipped` event 之後呢 ? Sam (物流部): > 如果訂單是 `貨到簽收`,當顧客收到貨後,我們會從 `客服部` 收到通知,所以應該加上 `shipment received by customer` event ![](https://i.imgur.com/VtrLlpW.png) * **Scenario**:User 或 department 想要達成的目標,但不包含實際細節,Agile 稱為 **story**。 * **Use Case**:Scenario 的實際細節。 * **Busines Process**:企業想要達成的目標。 * **Workflow**:Business Process 的實際細節。 ### Documenting Commands 當使用 Event Storm 在牆上找到眾多 Business Event 之後,下一步的疑問就是:如何使這些 Event 發生呢 ? 如 `顧客發 email` 的動作才會使 `order form received` event 發生,在 DDD 稱為 **Command**。 >不要跟 OOP 的 Command Pattern 搞混 當 Command 成功執行,它會引起 Workflow,並且發起 Business Event。 * `Make X happen` Command: 執行 `make X happen` workflow,並發起 `X happend` event。 * `Send an Order form to Widget Inc.` 執行 `send the order` workflow,並發起 `Order form sent` event。 * `Place an order` command: 執行 `place an order` workflow,並發起 `Order placed` event * `Send a shipment to customer ABC` command: 執行 `send a shipment` workflow,並發起 `Shipment send` event ![](https://i.imgur.com/3K1XjEE.png) 實務上 Business Process 會以如上的 Model 呈現: * 由 Event 觸發 Command * 由 Command 執行 Workflow * 由 Workflow 觸發更多 Event > 我們可發現這種 Model 剛好跟 FP 的 Function Pipeline 相契合。 ![](https://i.imgur.com/FjwnUnD.png) 根據以上方法呈現我們的 `訂單系統`。 目前我們先假設所有 Command 都成功執行,將在 `Ch.10 Implementation: Working with Errors` 討論如何處理 Command 執行失敗。 此外,並非所有 Event 都是由 Command 觸發,有些 Event 可能由 scheduler 或 monitor system 觸發。 ## Partioning the Domain into Subdomains 根據 DDD 第二條 guideline: > 將 Problem Domain 切割成更小的 Subdomain 雖然目前已經搜集了眾多 Event 、 Command 與 Business Process,但對於整個系統的了解仍是混亂的,在寫 code 之前仍必須做更進一步整理。 也就是將眾多 Event、Command 與 Business Process 的 `訂單系統` 切割成更小的子系統:如 `訂單子系統`、`物流子系統`、`帳務子系統` ... 等,誠如企業中已經存在各部門一樣,我們可稱此子系統為 Domain。 Domain 在 DDD 中定義為 `有特定知識的領域`,白話文就是 `存在 Domain Expert 的領域`。 ![](https://i.imgur.com/5RhXl7K.png) 以我們都熟習的 Domain 而言,`Web Programming` 算 `General Programming` 的 Subdomain,而 `JavaScript Programming` 又是 `Web Programming` 的 Subdomain。 除此之外,Domain 也能 overlap,如 CSS 橫跨 `Web Programming` 與 `Web Design`。 理論上,我們都希望切出來的 Subdomain 能明確而互不相干,但現實世界並沒有想像中單純。 ![](https://i.imgur.com/5f4ligi.png) 現實中的 Domain 會有些 overlap,`訂單部` 必須稍微了解 `物流部` 與 `帳務部` 流程,而 `物流部` 也對 `訂單部` 與 `帳務部` 的業務有所認識。 誠如之前 Dan North 的例子,developer 也該成為半個 Domain Expert,整個開發效率才會大幅提升。 ## Creating a Solution Using Bounded Contexts 根據 DDD 第三條 guideline: > 根據 Subdomain 建立 Domain Model 了解 Problem 與 Domain 並不代表能建立 Solution,畢竟資訊太多了,我們必須找出能解決問題的 Event、Command 與 Process。 ![](https://i.imgur.com/MHPv2lG.png) 首先我們必須將 Problem Space 與 Solution Space 分開,在 Problem Space 中從眾多 Event、Command、Process 中取出與解決問題的資訊在 Solution Space 中建立 Domain Model。 在 Solution Space 中的 Domain 與 Subdomain 在 DDD 稱為 **Bounded Context**,在每個 Bounded Context 中有其各自 Domain Model。 > 之所以 DDD 不稱為 Subsystem,因為其重點在於其 Context 與 Boundary ### Context 在相同 Context 中有其專有名詞與行話,這使的參與其中的人使用共同語言溝通,因為在現實世界中,同一個單字在不同領域常有不同意義。 ### Boundary 在現實世界中,Domain 很難無 overlap,但在 software 開發上,我們會希望各系統能避免彼此耦合、沒有 side effect 而能獨立演進,為了是減少複雜度與方便日後維護,因此我們傾向建立彼此 `沒有 overlap` 的 Domain Model,僅管此 Model 與現實世界的 Domain 有些許出入。 > Bounded Context 與 Subdomain 還是會有些差異,主要是為了更適合 software 開發 在 Problem Space 的 Domain 與 Solution Space 的 Bounded Context 並不需要一對一對應,實務上常常一個 Domain 分裂成多個 Bounded Context,或者多個 Domain 合併成單一 Bounded Context。 假如公司已經分別有 `訂單系統` 與 `財務系統`,假如你必須整合這兩個系統,僅管現實上是不同 Domain,但設計上會使用相同 Bounded Context。 無論怎麼切割 Domain,重點是每個 Bounded Context 有其明確的 responsibility,因為在實作 Domain Model 時,每個 Bounded Context 實作方式可能是獨立 DLL、可能是獨立 Service,或者是獨立 namespace,雖然實作方式並不是現階段重點,但大方向是相同的。 ### Getting Context Right 定義 Bounded Context 聽起來很直覺,但實作上卻很 tricky,事實上 DDD 最大的挑戰就是 `如何決定正確 boundary ?`,這已經是藝術等級,而非科學問題,以下是 DDD 所建議的 guideline: * `傾聽 Domain Expert 建議`:假如該 Event、Command 與 Process 都使用相同行話且關注相同問題, 他們大致上是在相同 Bounded Context 內 * `觀察企業的組織劃分`:畢竟因為業務不同才會畫分出如此的組織結構,他們大致上是在相同 Bounded Context 內 * `別對 Boundary 有婦人之仁`:由於問題變化太快,可能會想將 boundary 模糊化面對,但 boundary 太大或太模糊等於沒有 boundary,俗語說:`Good fences make good neighbors`。 * `為了將來獨立發展`:硬將不相關的 Domain 取其最大公約數放在相同 Bound Context 下將限制未來發展,應將其各自放在不同 Bounded Context 下 * `為了更順暢的 Workflow`:假如該 Workflow 會橫跨多個 Bounded Context,但因為 Cotext 的種種限制而使 Workflow 不順,可考慮將多個 Bounded Context 合而為一,雖然整個設計可能看起來比較醜,但畢竟 DDD 重視的是解決問題與客戶價值,而非設計出漂亮的架構 沒有任何架構是一成不變的,任何 Domain Model 都會隨時間的推進與需求的改變而演化,在 `Ch.13 Evolving a Design and Keep it Clean` 將會深入討論。 ### Creating Context Maps 當設計出 Bounded Context 後,我們還必須設計出各 Bounded Context 溝通方式,此時並不需要對實作部分太講究,只需有整體概念即可,在 DDD 稱為 **Context Map**。 ![](https://i.imgur.com/Y5a3uU5.png) ![11](images/11.png) 如同旅行時使用的 route map 一樣,它並沒有顯示各城市細節,也沒有顯示以何種交通工具來往,它只顯示出下一站的目的地,讓你可以根據它設計出旅行計劃。 ![](https://i.imgur.com/sOrd8Ny.png) 如同 route map 一樣,Context Map 主要在顯示各 Bounded Context 間的關係而非實作細節,可以大致看成 `Order-taking` context 是 upstream,而 `Shipping` context 是 downstream。 很明顯的當兩個 Bounded Context 要溝通時,必須同時遵守一定的通訊協定,通常 upstream 要較高的影響力決定,但有時候因為 downstream 是 legacy system 無法輕易改變,有可能 upstream 必須妥協,或種中間有 adapter 進行轉換,詳細會在 ` Ch.03 A Functional Architecture` 中討論。 雖然目前的 `訂單系統` 只需一個 Context Map 就能搞定,但實務上會有很多 Context Map 用來表示各自 Subsystem。 ### Focusing on the Most Important Bounded Context 當分割出眾多 Bounded Context 之後,要從哪個 Bounded Context 開始開發呢 ? * **Core Domain**:具有企業核心優勢,能使企業賺錢的 Domain * **Supportive Domain**:必須但非核心的 Domain * **Generic Domain**:對企業並非必須的 Domain 以本例而言,`Order-taking` 與 `Shipping` 可視為 Core Domain,而 `billing` 則為 Supportive Domain。 ## Creating a Ubiquitous Language 根據 DDD 第四條 guideline: > 為 Developer Team 與 Domain Expert 間建立 Ubiquitous Language 因為 DDD 強調 Code 與 Domain Expert 必須使用相同的 Mental Model,如 Domain Expert 使用 `Order` ,在 Domain Model 裡也必須稱為 `Order`,Developer Team 不能根據自己的喜好使用其他字彙。 除此之外,Domain Model 也不該出現 Domain Expert 的 Mental Model 中所沒有字彙,如 `OrderFactory`、`OrderManager`、`OrderHelper` ... 等,當然這些字彙在 codebase 中可能會出現,但不應該在 Domain Model 出現,因為 Domain Expert 並不了解。 由於要讓所有人都能了解 Domain Model,因此必須統一大家的觀念與字彙,在 DDD 稱為 **Ubiquitous Language**,白話就是 everywhere language,也就是 Developer Team 與 Domain Expert 在 Domain Model 所使用的共同字彙,除此之外,既然是 everywhere,在 codebase 也該使用相同字彙。 不要以為 Ubiquitous Language 只是 Domain Expert 所定義而已,這是整個 team 共同制定的,且 Ubiquitous Language 也不是一成不變,而是會隨著 project 的進行而加入新的觀念或字彙,在本書後續章節也會看到。 雖然有了共識的 Ubiqutious Language,但有時同一個字彙在不同 Bounded Context 可能有不同定義,如同 `方言` 一般。 如 OOP 的 `class` 與 CSS 的 `class` 就是完全不同意義。 如 `order` 在不同組織中的意義也可能有些許差異,在 `物流部` 關心的是 `產品數量`,而 `帳務部` 則關心 `產品單價` 與 `總金額`,所以儘管有了 Ubiquitous Language 後,仍必須注意其 Bounded Context,否則可能造成誤解。 ## Summarizing the Concepts of Domain-Driven Design * **Domain**:我們要解決的問題中所使用的專業知識領域,會有 Domain Expert 存在 * **Domain Model**:在 Solution Space 內經過簡化的模型 * **Ubiquitous Language**:Domain 中所有 team member 都使用的共同字彙 * **Bounded Context**:在 Solution Space 中有明確 boundary 的 subsystem,且存在 Ubiquitous Language 的 `方言` * **Context Map**:顯示 Bounded Context 之間關係 * **Domain Event**:系統中會發生的 Event,會以 `過去式` 表示,且會觸發其他 Command * **Command**:執行 Process 或觸發 Event,可由其他 Event 觸發 ## Wrapping Up 一開始我們強調 Shared Mental Model 的重要性,接著提出 DDD 四個 guideline: * `將焦點放在 Business Event 與 Workflow 而非 Data Structure` * `將 Problem Domain 切割成更小的 Subdomain` * `根據 Subdomain 建立 Domain Model` * `為 Developer Team 與 Domain Expert 間建立 Ubiquitous Language` ### Event and Process ![](https://i.imgur.com/OQJwxVn.png) Event Storm 中找出了 Domain 中重要的 Event,如: * `Order form received` event 觸發 `Place order` process * `Place order` process 執行完觸發 `Order Placed` event * `Order Placed` event 觸發 `Ship Order` process 與 `billing` process ### Subdomain and Bounded Context ![](https://i.imgur.com/BJci5ZS.png) You: > Ollie (訂單部),你知道 `billing` process 如何運作嗎 ? Ollie (訂單部): > 一點點,但詳細內容要問 `物流部` 的 Sam 由此可知 Billing 為另外一個 Domain,也就是所謂的: > A Domain is what a Domain Expert is expert in ![](https://i.imgur.com/asiRcek.png) 接著我們可將 Problem Space 的 3 個 Subdomain 以 Solution Space 的 3 個 Bounded Context 對應。 ![](https://i.imgur.com/RR3kvyi.png) 以 Context Map 顯示 Bounded Context 之間的關係。 至於何者為 Core Domain,這應該由總經理 Max 決定,我們假設 `Order-taking` Context 是 Core Domain,將由此 Bounded Context 開始開發。 ### The Ubiquitous Language 目前我們已經有如 `order form`、`quote`、`order` 等專有名詞,且隨著專案的進行,還會出現更多專有名詞,為了讓團隊有共識,且讓新進成員快速上手,可建立 live document 或 Wiki 之類加以記錄這些專有名詞及其定義。 ### What's Next ? 雖然目前對於 `訂單系統` 已經有不少了解,但仍缺乏一些東西: * `Order-processing` workflow 詳細的 input 與 output 為何 ? * `Order-processing` workflow 與哪些 Bounded Context 相關呢 ? * `物流部` 的 `order` 與 `帳務部` 的 `order` 認知詳細差異在哪 ? 在 `Ch.02 Understanding the Domain` 將試圖討論以上問題。 ## Conclusion * 對於 DDD 完全沒概念的初學者,可藉由本章對於 DDD 手法有初步認識 * 對於 DDD 最經典專有名詞如 Event Storm、Bounded Context、Abiquitous Language ... 也能有初步認識 ## Reference [Scott Wlaschin](https://twitter.com/ScottWlaschin?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor), [Domain Modeling Made Function Preface](https://pragprog.com/book/swdddf/domain-modeling-made-functional)

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password
    or
    Sign in via Google Sign in via Facebook Sign in via X(Twitter) Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    By signing in, you agree to our terms of service.

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully