About domain driven develop

jerry80409
4 min readMar 12, 2021

--

Clean architecture, from Diagram by Robert C. Martin

依賴注入

依賴, 翻譯就是沒有 ooo 就無法做 xxx, 像是沒有 JDBC 就不會有 ORM 這樣的概念。

注入, 翻譯就是透過物件初始化 constructor, method paramers 來將依賴的物件(元件) 放到程式碼的流程裡.

圖中的箭頭, 是依賴的方向,

  • Use Case(案例) 依賴 Entities(業務實體)
  • Controller (REST API 接口) 依賴 Use Case(案例)
  • Web (外部使用者行為) 依賴 Controller 對資料 CRUD

簡單的概念是這樣…

因此, 在拿到需求的分析上, 不應該從 DB 或是 API 接口去作為設計的出發點, 而是先定義好 Entities(業務實體), 再來反思 DB 跟 API, 而這樣的設計卻又跟從操作介面定義開始的 UX 設計是不同層面的看法.

UX 設計重視的是使用者的經驗, 而經驗來自於同類型的產品, 或是日常操作類似產品的經驗, 這樣的使用者又跟軟體開發時需要的 領域專家(Domain Expert) 不一樣, 如果找的使用者是偏好某種品牌, 很可能設計出來的東西會被該品牌影響, 而失去一種創新的機會, 離題了.

透過依賴注入來管理依賴

若熟悉 Container Framework 的開發者, 應該會非常熟悉在 Service Component 去定義 Use Case, 所以 Service Component (以 Spring framwork 來說就是一個 Singleton instance), 裡面可能會有一些 method 對 Entities 做一些事情. 舉例來說 Sibala(十八啦) 的遊戲 (91 哥的課 CP 值很高).

Entities, 大致上我會設計成 Player(玩家), Dice(骰子), 這兩種 Entities 放到 RuleService 裡面.

class PlayerEntity {  
// 玩家名稱
private String name;
// 骰子
private Dice dice;
}

class DiceEntity {  
// 每個骰子, 骰到的點數
private List<Integer> nums;
}

@Service
class RuleService {

// 計算分數
Integer calPoint(DiceEntity dice) {
// dice.nums -> point
}

// 比大小, 分數高的勝出
Player compareTo(List<Player> players) { }
}

這種方式的設計, 就不需要去關心 Dice 或 Players 細節, 怎麼被實體化, 也不用去關心 Player 有幾個, 整個 RuleService 關心的就是 算分數, 比大小, 而這種從外部去放入 Entities 的方式就是一種依賴注入. 這有幾個優勢.

  • 閱讀起來很清晰, 明確
  • method 容易專注在單一業務上, 因此容易寫測試
  • 看起來也算是各司其職, 符合 SOLID 精神

值得去質疑的是, Rule 到底需不需要被定義為 Service Component?

如果只有簡單的業務情境, 我大概不會考慮使用 Service Component, Service Component 的好處, 在於產生一個 Singleton, 並且容易與 Spring 相關的服務整合, 比如 (@Transactional), 一但整合了 Spring context 測試的複雜度就會慢慢提高, 比如是否要去測試 @Transactional 的 ACID?

但或許可能不需要想那麼多, 專注在測試業務測試上就好了…

--

--

jerry80409
jerry80409

Written by jerry80409

隨便記錄一些沒有整理很清楚的想法

No responses yet