YU-SHIH-PENG
    • 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
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    ###### tags: `領域驅動開發` `DDD` `Domain Driven Design` # DDD實戰-Module ### 一、關於Module 在闡述Module前,讓我們先來比對非物件化設計與物件化設計的差異性。看到下圖左,在非物件化的傳統設計,資料與方法操作上是整個拆開設計,在資料流複雜外我們可以看相依性高,偶合的狀況也較高。 接著討論物件化設計部分,先不論封裝等物件操作技巧,單純根據資料與方法關係設計出物件(物件特性:資料(Data) 物件行為:方法(Function)),我們可以看到原本互相依賴的Fun關係可各自獨立使用,在資料流上也較為單純。 ![](https://i.imgur.com/eCnw2lV.png) 物件化後,雖然在資料操作面上簡化許多,但隨著專案功能性逐漸增加,物件與功能處理流程上會趨近越複雜,如下圖為一個簡易的系統,此系統根據外部Sensor系統獲取、過濾與計算資料,在沒模組化的設計前提,可以看到Control與Data Flow呈現一個較零散的關係狀態 ![](https://i.imgur.com/tYs6Ybt.png) 此時我們根據Sensor功能額外設計一個Sensor模組如下,此時我們就可以針對Sensor相對應的資料模組將之封裝在模組內,此模組對外則就單純開放運算(calculation)與過濾(filtering)的功能。 模組化後可以明顯看出控制與資料流的彼此相依性值,因此降低了修改與擴充狀況的互相影響性值。 ![](https://i.imgur.com/bQWCuAH.png) 模組化指是將**系統功能程序作分離獨立(特定功能class的容器)**,除了功能獨立外,也強調設計上可以根據功能隨意抽換模組。達到高內聚、低耦合的目的,進而提高開發者的生產力(將複雜的功能拆分管理)。並讓程式碼能夠透過引用的方式來重複使用,提升重用性(Reusable) > Modular design allows code to remain agile in the face of ever-changing requirements. --- ### 二、構成Module考量五要素 - Propose:Module功能目標單一職責,盡量不要與其他模組設計有太多相依關係。 - Interface:模組功能API所提供使用方式要簡潔易懂,通常User不需要去了解實際內部的實作方式,只需專注在確定輸入什麼,會輸出什麼可達到什麼功能。 - Encapsulation:封裝模組,除了讓不暴露資料結構讓使用者亂使用外,對於在修改細節上也能較不容易直接影響使用端。另外再使用抽象實作上,物件抽象化多少還是難以避免Leaky Abstractions的問題。 - Implementation:實作上除了考量功能正確性外還需考慮效能、測試與功能架構程式碼最小化。 - Connection(關聯性):呼應Propose功能單一職責,將與其他模組相依性最小化。 --- ### 三、Package Vs Module 在了解Module構成要素後~隨著專案模組(Module)的增加,將難以管理及問題的追蹤,這時候就能將模組(Module)打包成套件(Package),利用其階層式的結構來彈性規劃模組(Module)。 - Module:單一功能模組 - Package:多Module組成 ### 四、一般Module設計方法 在非以領域事件為出發點的設計上,大部分狀況會根據功能設計成物件與介面使用。下圖為Zebra SDK Package的Module列項,我們可以大致分得出,他的Module設計就是根據功能性值去區分(graphics, certificate...) ![](https://i.imgur.com/9r6cSWk.png) 接著我們點近discovery看提供什麼API功能,可以看到可以使用的介面功能以及相關功能可使用的功能物件。 ![](https://i.imgur.com/qEtuOCR.png) 在點進個別更詳細功能介紹,我們就會看到這物件功能具有什麼資料特質、物件實體化須提供什麼參數以及此物件可使用哪些方法。 - Field: address,IP or Mac Adress - Constructor:物件實體化須提供印表機的IP or Mac Adress - Method:可使用的物件功能,在此例看起來需實作getConnection功能 ![](https://i.imgur.com/BU8pxp3.png) 上述為印表機找到印表機裝置功能的模組化介紹 --- ### 五、未使用DDD的一般Service服務設計 上述一般Module設計概念聊完,在聊DDD Module設計之前先來聊一下在一般未使用DDD領域設計的服務系統會如何設計。 在對大部分的開發者,一開始習慣設計都以數據為考量的集中式設計架構。設計架構上會出現比較常見到的分層式設計,大致分成Controller, Service, Repositories, Models - xxx/Model - 數據庫Model、Request Model, Response Model - xxx/Controller - 給Client端的API第一時間接口,提供Get,Post,Delete,Update API。除了此在此層一般都會安插屬性驗證Client第一時間傳過來的資料是否正確。並作實際的DTO(Object 與DB Model Mapping)轉換。 - xxx/Service - 這層基本上就是作商業邏輯的處哩,進到此層的資料基本上都是做完DTO轉換,在此層通常會作實際的資料邏輯處理處理完後再往DB方向送。 - xxx/Repositorie - DataSource(DBContext)上一層,一般會除了實際面DataSource讀寫變更操作外,Source 資料Join處理也會在此層處理。一般多這一層都是為了隔開DataSource的來源切換,不管置換不同的DB系統,或是Source改成Shared Prefs,都可快速置換資料來源。 ![](https://i.imgur.com/jh6V5V1.png) --- ![](https://i.imgur.com/E0aH4K0.png) --- ### 六、在DDD世界中的Module設計 上述稍微帶過Module的設計概念後,接著探討在DDD世界裡,Module的設計概念如何~大致分成幾個探討議題 #### 1.DDD設計步驟流程 ![](https://i.imgur.com/UxkUrru.png) - 在探討需求架構DDD設計的第一步,就是根據需求情境列出事件風暴(Event storming),並在事件風暴中的用戶操作、事件、以及依賴關係根據這些要素設計歸納出領域與實體。 - 接著第二步在領域實體之間找尋彼此務的關聯性,將具有相關的實體組合成聚合(Aggregate),同時確定聚合根(Aggregate Root)。在聚合根行程時,基本上第一層邊界(邏輯邊界-虛線)也會跟著產生,他們會在同一個服務器中運行。 - 當聚合規劃好後~會根據業務及語意邊界等因素,將一個或多個聚合規劃訂製在一個限界上下文內(服務邊界),形成領域模型。 ![](https://i.imgur.com/m9zqq3B.jpg) #### 2.程式碼一級目錄架構 ![](https://i.imgur.com/Lo710em.png) - Interface(API Interface) - 給使用者API介面,使用者透過Restful請求,將資料傳到此層,解析用戶傳送的請求資訊,資料的組裝、資料傳輸格式以及 Facade 介面等代碼都會放在這一層目錄裡。 - Application - 他有點像是原先集中式設計Service的功能,實作所有相依於指定前端之使用案例的地方。 例如,與 Web API 服務相關的實作。若使用的是 CQRS 方法,它便會包含查詢、微服務接受的命令,甚至是微服務之間的事件驅動通訊 (整合事件)。 - Domain - 它主要存放領域層核心業務邏輯相關的代碼。領域層可以包含多個聚合代碼包,它們共同實現領域模型的核心業務邏輯。聚合以及聚合內的實體、方法、領域服務和事件等代碼會放在這一層目錄裡。 - Infrastructure - 它主要存放基礎資源服務相關的代碼,為其它各層提供的通用技術能力、三方套裝軟體、資料庫服務、配置和基礎資源服務的代碼都會放在這一層目錄裡。 #### 3.在DDD Module準則 例子:如何對電商平台上的顧客進行模塊設計 對於顧客來說,一般須要維護顧客的 - 個人訊息 - 收穫地址 - 付款方法 這三個之間的關係是緊密相關,不可獨立存在,我們根據這三點抽象出三個Aggregate - Customer 個人訊息 - AddressBook 收穫地址 - Wallet 付款方法 那該如何去放置這些Aggregate,是針對每一個Aggregate作資料夾分類還是這三個Aggregate放同一格資料夾?基本上這三個Aggregate就是一個Custer Module,所以都會放到Custer Module資料夾內。 ![](https://i.imgur.com/fkBiQjS.png) 當整理出Aggregate與Module後,接著會開始根據各Module去實作事件應用處理 基本上我們在DDD模塊的設計上有幾個注意要點 - Module應該要和Domain概念一致:一般一組聚合集成(領域),我們會相對應建立一個Module。 - 根據通用語言來命名:模組命名要一眼就看出這是在做什麼的。 - 模組設計盡量鬆偶合:盡量與其他模組不要有太多的偶合,若有也許在領域設計上還沒切得很乾淨。 - 如果有PeerModule或父子Module出現,盡量避免循環相依。 #### 4.關於Module命名 ![](https://i.imgur.com/jLYf3Ot.png) #### 5.Module界線與限界上下文不同 為了對領域模型中進行準確建模,需要將領域模型劃分成多個子域,每個子域對應一個或多個限界區域。 模塊。所以,從子域到限界某些再到模塊,應該是依次包含關係。 ![](https://i.imgur.com/dRmq7U3.png) ### 補充 #### 補充一 - Abstracion: - 將真實世界物體與事件的大量資訊縮減一個概念或是一個現象的資訊含量來將其廣義化,保存和一特定目的有關的資訊。例如,將一個皮製的足球抽象化成一個球,只保留一般球的屬性(形狀)和行為(滾)等資訊。 - Leaky Abstractions - 所有非不證自明的抽象概念,都有某種程度的疏漏。例如TCP雖簡化(抽象化)網路行為,設計上也保證網路傳送過程中不遺漏資訊,但不保證就真的能完整傳到資訊,例如我們無法避開海底電纜被魚咬斷因此斷訊的狀況。 ### 參考 [範例](https://github.com/kgrzybek/modular-monolith-with-ddd#32-module-level-view) [The 5 Essential Elements of Modular Software Design](https://shanebdavis.medium.com/the-5-essential-elements-of-modular-software-design-6b333918e543) [The Law of Leaky Abstractions](https://www.joelonsoftware.com/2002/11/11/the-law-of-leaky-abstractions/) [The Three Principles of Excellent API Design](https://nordicapis.com/the-three-principles-of-excellent-api-design/) [解析Python模組(Module)和套件(Package)的概念](https://www.learncodewithmike.com/2020/01/python-module-and-package.html) [Module Design](http://www.the-software-experts.com/e_dta-sw-design-module.php) [Domain Events vs. Integration Events in Domain-Driven Design and microservices architectures](https://devblogs.microsoft.com/cesardelatorre/domain-events-vs-integration-events-in-domain-driven-design-and-microservices-architectures/) [DDD理论学习系列(13)-- 模块](https://www.cnblogs.com/sheng-jie/p/7266557.html) [DDD理论学习系列——案例及目录](https://www.cnblogs.com/sheng-jie/p/6931646.html)

    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 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