Dependency Inversion Principle 避免過度依賴外部

Introduction
DIP 應該很常見, 只是常常在談的時候會發現大家忘記了.
因此特別紀錄一下使用 DIP 實質上的好處.

Assumption
  1. 我們大多會希望 business logic code 可以乾淨穩定
  2. 有乾淨穩定的 business logic code, 就可以寫穩定的 unit test code
  3. 如此未來商業邏輯有改變的時候, 如果邏輯有衝突, 或是程式有問題很快就可以 flush

Reality
  1. 在沒有仔細思考的情況下, 分層式規劃結果無法有乾淨的 business logic code
  2. 例如, 假設 DB 是 PostgreSQL, MQ 則是 Kafka
  3. 很容易程式會出現 MyDomainService depends on MyDomainRepositoryHibernateImpl
  4. 這樣的架構就變成 business logic code depends on implementation
  5. 如此, 無法寫出穩定的 business logic test code, 因為都"必須"直接由 domain code 直接依賴 Hibernate & Kafka...
  6. 一個是需要準備 Hibernate & Kafka 的環境 or mock, 可能有些細微的調整沒藏好, 會導致一點小調整都可以讓測試壞掉


Solution
  1. 為了區隔出乾淨的 business logic code, 我們可以替 repository 提出一個 interface
  2. 如此, business logic code 僅止於 MyDomainRepository 以及 MyDomainMessageSender
  3. 同時, 也要注意 interface 上不可以出現底層的相關資訊
  4. 例如 MyDomainMessageSender 的 interface 不該出現 topic 這種 Kafka 概念的資訊 (除非我們自己訂一層 abstraction layer)
  5. 這時候就會看到為何像是 spring-data 會支援直接訂一個 interface 就可以透過 convention access DB


Besides
  1. 同樣的概念也可以套用在不同的 component
  2. 例如 application 跟很多外部系統界接, 所以程式裡面有分成不同的 component
  3. 透過 DIP, 可以把其他 system 的實作與主要的 business logic 獨立開來
  4. 如此就可以直接在測試描述對於外部喜統的 expectation, 而且不用為了 business logic test code 準備外部系統的細節
    (在目前的例子, 不用準備 gRPC and Kafka)





沒有留言:

張貼留言

別名演算法 Alias Method

 題目 每個伺服器支援不同的 TPM (transaction per minute) 當 request 來的時候, 系統需要馬上根據 TPM 的能力隨機找到一個適合的 server. 雖然稱為 "隨機", 但還是需要有 TPM 作為權重. 解法 別名演算法...