l

2023年6月14日 星期三

為什麼Teddy沒使用Specification設計模式?

June 14 21:46~22:53


  ▲圖1:定義Specification介面


前言

在6/5~6/7去客戶家上【領域驅動設計與簡潔架構入門實作班】的時候,有一位學員問Teddy:

  1. 為什麼Teddy建議Entities Layer的物件不要直接操作Repository?
  2. 為什麼有人說UoW(Unit of Work)和Repository在DDD裡面算是Anti-Pattern?
  3. 為什麼Teddy沒有用Specification模式?

前兩集談了前兩個問題,今天討論最後一個問題:「為什麼Teddy沒用Specification設計模式」」?

 

***

Specification 設計模式

這一個設計模式是由Eric Evans與Martin Fowler所整理的,可在此下載介紹該模式的pdf檔案

Specification這個名字很容易讓人聯想到規格或是需求,但它的用作其實是Filter(過濾器)Selector(選擇器)。傳統上,開發一般CRUD-Based的系統,開發人員很常直接下SQL操作資料庫去尋找所需的資料。但是在領域驅動設計(DDD)中,強調透過領域模型來表達業務邏輯。「尋找符合條件的領域物件」這件事,本身就是一個業務邏輯,因此在領域模型中應該有相對應的物件來表達這樣的業務邏輯。而Specification設計模式就是為了這樣的應用場景而存在。

實作Specification很簡單,它的介面只有一個方法isSatisfiedBy,請參考圖1。isSatisfiedBy接受一個物件(通常是領域物件,例如Board, Workflow, Card這些物件),如果物件的內容滿足concreate specification所指定的條件,則回傳true,代表這個物件「符合規格(選到這個物件了)」。

***

圖2是以個用來選擇Board是否屬於某個Team的規格,稱為BoardBelongToTeamSpecification。



▲圖2:BoardBelongToTeamSpecification範例程式 

 

圖3為BoardBelongToTeamSpecification的使用方法,首先呼叫getBoardLise()產生四個Board。然後產生BoardBelongToTeamSpecification instance,傳入”Team 1”當作查詢條件。接著用BoardBelongToTeamSpecification 當作過濾條件,從這四個Board裡面選出Kanban Board與Board Game。


▲圖3:BoardBelongToTeamSpecification使用範例 

 

在Eric Evans與Martin Fowler所整理原始的文章中,Specificatoin還可以串接,形成更複雜的選擇規範。

***

為什麼沒用Specification?

由上面例子可以看出來,Specification其實就是一個Predicate。從實作面的角度來看,可以直接用Lambda來完成。Specification之所以存在,還有一個很重要的作用力,就是要重複使用這個業務邏輯。你可以用Specification去資料庫中挑選資料,或是驗證領域模型物件是否符合否項業務規格。在這種情況下,如果使用Lambda來實作,就會產生重複程式碼。

寫到這裡,還是沒講為什麼在ezKanban中並沒有使用Specification。原因如下:

  • ezKanban透過撰寫合約的方式來驗證領域物件的正確性,而非使用Specification。
  • 如果要透過Specification去資料庫挑選資料,那麼資料必須先從資料庫中載入記憶體或是用某種映射的方式,把傳給isSatisfiedBy()方法的物件身上的每一個欄位,去匹配資料庫中的欄位。因為ezKanban支援State Sourcing與Event Sourcing,無法光用傳統State Sourcing的方式如果採用Specification去資料庫比對資料。因此,ezKanban就沒有使用Specification,而是針對不同儲存方式與不同資料庫,用資料庫相依的方法,撰寫特別的查詢物件。
  • ezKanban套用CQRS,而CQRS和Specification是兩種互相衝突的設計模式。詳細原因請參考Vladimir Khorikov的部落格文章 <CQRS vs Specification pattern>。

***

結論

Teddy當年在學DDD的時候,印象中只有在DDD藍皮書中看到Specification的介紹,在比較接近實作的DDD紅皮書與DDD橘皮書中,沒什麼印象提到Specification。可能是Teddy學藝不精,所以開發ezKanban的時候潛意識中就沒有套用Specification。

但Teddy目前沒用也不代表以後不會用,反正這麼多設計模式,多了解一點也沒什麼不好。等到哪天有合適的場合,這些模式會自動跑出來報效國家。

***

友藏內心獨白:用Collection操作資料還是非常方便滴。

沒有留言:

張貼留言