l

2020年12月29日 星期二

領域驅動設計學習筆記(13):幫Event Storming加上使用者介面

Dec. 29 09:43~11:39


問題

這個月底Teddy去客戶家上了三天的【領域驅動設計與簡潔架構入門實作班】,有好幾位學員都問到:「Event Storming怎麼表達使用者介面設計?」使用者介面是軟體的外觀,關係著軟體好不好看以及好不好用,的確是軟體開發中一個重要的議題。

今天來談談這個問題。

***

Event Storming簡介

Event Storming(事件風暴)在領域驅動設計中經常被使用於讓利害關係人與團隊共同協作,用以釐清業務流程、討論商機、風險、區分bounded context、建立共通語言,乃至於設計與實做軟體的一種方法。Event Storming發明人Alberto Brandolini在《Introducing EventStorming》書中介紹這個方法,圖1為Event Storming工作坊所使用的主要便利貼,不同顏色有不用的用途。


▲圖1:Event Storming常用便利貼顏色與意義


依據《Introducing EventStorming》書中的介紹,Event Storming有三個階段,分別為:

  • Big Picture:依據時間發生先後,在一面「巨大」的牆上,貼上Domain Event、External System、People,並藉此流程觀察Hot Spot(對商業流程有模糊不清、商機、痛點等)。
  • Process Modeling:基於前一個階段的產出,加上Read Model、Policy、Command。
  • Design:加上Aggregate。

一般網路上常看到的Event Storming產出物如圖2所示。


▲圖2:Event Storming示意圖

***

UI/UX設計

▲圖3:《Introducing EventStorming》書中的「The picture that explains everything」


參考圖3,在Event Storming方法中原本就涵蓋了UI/UX。這張圖可以這樣解讀:

***

使用者要使用軟體系統執行某項任務,為了執行這項任務,他需要參考資料以協助他決策判斷。因此,他在真實世界看到一個畫面,這個畫面是由Read Model(綠色便利貼)所產生。例如,你去餐廳吃飯,為了點餐(執行任務)你需要看到菜單(畫面),這個餐單可能是中文、英文、日文,可能只有文字或是圖文並茂,但菜單背後都是該餐廳的菜單資料(Read Model)所後製而成。如何設計給客人看的菜單就牽扯到UI/UX的議題。

使用者獲得足夠決策資訊後,向系統發出一個命令(Command,藍色便利貼),這個命令交給系統中某個聚合(Aggregate,黃色便利貼)去執行,執行完畢後發出一個領域事件(Domain Event,橘色便利貼)。領域事件可能引發後續的處理流程,稱為Process、Rule或Policy(紫色便利貼),後續處理流程再執行另一個命令。例如,告訴服務生(Aggregate)你要點餐(Command),服務生完成點餐動作後產生Order Placed(Domain Event)。Order Placed觸發一個後續處裡的流程—請廚師出菜,因此呼叫「製作餐點」這個Command。

領域事件也可能是由外部系統(External System,粉紅色長方形便利貼)所產生,例如餐廳可能與Uber Eat或Foodpanda合作,由外部系統觸發Order Placed領域事件。

最後,領域事件代表「狀態改變」,因此可從領域事件產生Read Model,再透過這個Read Model製作使用者介面。例如廚師可以從Order Placed領域事件產生「出菜順序」的畫面,作為製作餐點的決策參考資料。

***

範例

看完上述對於「The picture that explains everything」 的說明,在Event Storming中加上使用者介面就很容易了。圖4展示在ezKanban中,Create Project與Move Board To Project這兩個命令(套用Clean Architecture之後,這兩個命令被實作成兩個Use Cases)。使用者介面加在綠色便利貼之前,為了執行Create Project,使用者看到一個畫面,按下Add按鈕,跳出一個New Project 對話框,輸入Project Name按下Submit,把team id與project name當作參數呼叫Create Project使用案例。該使用案例透過Team Aggregate產生一個Project,然後發出Project Created領域事件。該事件代表有一個新的Project產生,因此使用者在執行Move Board To Project使用案例的時候,就可以從畫面看到剛剛新增的Project。


▲圖4:ezKanban範例,在Event Storming加上使用介面。

***

使用者介面如何產生

團隊的UI/UI的人員,可以沿用原本熟悉的工具來繪製使用者介面或是UI操作流程圖,只要將最後的結果截圖貼在Miro上面即可(Teddy與ezKanban團隊使用Miro來繪製Event Storming),不會影響原本的UI/UI設計流程。

最後工商服務一下,想學習DDD + Event Storming + Clean Architecture + TDD,歡迎報名泰迪軟體的領域驅動設計與簡潔架構入門實作班

***

友藏內心獨白:無縫接軌。

2020年12月27日 星期日

領域驅動設計學習筆記(12):Event Storming與User Story

Dec. 27 20:05~21:45

▲ezKanban團隊的開發流程


問題

有朋友問Teddy:「Event Storming做完之後,如何轉成user story與團隊溝通?」

在ezKanban開發過程中,團隊的開發流程從2020年暑假開始從Scrum轉成Kanban。團隊不再額外寫In order too [獲得什麼好處]….As a user, I want to [做什麼事] 這種格式的user story,而是直接將Event Storming的Command變成Use Case放到product backlog裡面。

傳統OOAD的Use Case其粒度一般來講比user story要大,一個Use Case可能有多個執行路徑或多個劇情,每一個執行路徑可視為一個user story。所以直接以Use Case來取代user story,有可能會違反敏捷與精實開發的小批量生產原則—開發的功能儘量切小,可獲得較短的交期(lead time)。不但bug會比較少,品質較好,也可以快速收集使用者回饋。

ezKanban團隊在Event Storming的過過程中不是從CRUD的角度來尋找領域事件,而是找出任務導向(task-oriented)的領域事件,並且採用TDD/BDD/SBE的方式實作Use Case。因此從實作面的角度,也是以step by step、piece by piece、scenario by scenario的方式完成使用者需求,並不會因為沒有將Use Case改寫成user story就造成溝通或是開發上的問題。

***

範例說明:Move Lane使用案例

圖1:Move Lane Command


視覺化是實施看板方法的第一條原則,因此ezKanban軟體自然要提供設計工作流程的功能,讓使用者可以新增Stage(垂直的工作階段)與SwimLane(水平的工作階段)。除此之外,使用者在視覺化工作流程的時候經常需要調整工作流程的順序與層級,因此Move Lane(移動工作階段)使用案例也很重要,如圖1所示。

使用者可以直接用滑鼠將最上層的工作階段拖拉到想要的順序,如圖2所示,使用者正在把Reviewed移到Ready to Deploy之後。


圖2:實作完成的Move Lane畫面

***

實作Move Lane使用案例

因為採用TDD方式開發,因此先撰寫第一個Use Case的測試案例—移動最上層的Stage。請參考圖3,這個測試案例代表最常見使用情況的happy path。


圖3:Move Lane的第一個測試案例

一開始這個測試案例根本無法編譯,因為都還沒寫production code。接著就按照TDD的流程,以最簡單的方式撰寫讓測試案例可以通過的production code,再透過重構來改善設計。

因為移動工作階段這個功能比較複雜,光靠Use Case的驗收測試無法涵蓋所有可能的移動情況,因此以specification by example的精神,以單元測試來代表移動工作階段的各種可能狀況,單元測試案例執行結果請參考圖4。


圖4:Workflow身上的moveLane方法的單元測試


針對move lane的各種狀況,ezKanban團隊目前一共寫了9個單元測試,從單元測試的名稱就可以很清楚看到所想要涵蓋的情況,例如以下兩個單元測試代表移動工作階段的邊界條件測案例。

  • should have correct order when move substage0 from order0 to order0 in the same parent
  • should have correct order when move substage4 from order4 to order4 in the same parent

單元測通過之後,回頭跑Use Case測試案例,順利通過就完成Move Lane使用案例的第一個happy path。

接著撰寫第二個Move Lane使用案例的驗收測試—should succeed when move second root stage containing sublane to first root stage,這個案例比較複雜,代表兩個平行的stage A 和stage B,其中stage B底下還有其他的stages,然後把stage B移到stage A底下。

這兩個驗收測試都通過之後,就可以撰寫rest controller,完成後再寫前端的react程式,把前後端接起來這個Move Lane功能就完成了……第一版。

上述提到兩個驗收測試都是移動Stage,還需要增加移動SwimLane的驗收測試,測試通過後整個Move Lane使用案例才可以算是完成。

目前ezKanban團隊的TDD僅限於use cases與entities這兩層的物件,這兩層以外的開發並沒有採用TDD,而是採用傳統code first方式。

***

通用語言表現在程式碼

領域驅動開發有一個重要的觀念—Ubiquitous Language in Code,能夠做到這個層次,開發團隊本身,以及開發團隊與stakeholders(尤其是domain experts)的溝通也就沒什麼問題。

Teddy整合了DDD、Event Storming、Clean Architecture與TDD/BDD/SBE,首先透過event storming建立ubiquitous language 與domain model,接著透過clean architecture與TDD將ubiquitous language落實在程式碼之中。以上這些都做到之後,如果覺得還是需要撰寫傳統的user story,那也沒關係,就去寫吧。

***

友藏內心獨白:到了離,就不用守了。

2020年12月18日 星期五

領域驅動設計學習筆記(11):Bounded Context(上)

Dec. 18 13:01~17:35

▲ezKanban的儀表板畫面


只有一個Context的問題

Bounded Context在領域驅動設計(Domain-Driven Design;DDD)中是一個很重要個概念,今天先從實作面談一下有無Bounded Context的差別。以往傳統的物件導向設計,整個問題領域就是一個巨大的Context,因此在solution domain自然產生一個很大的物件類別圖, 如圖1所示。

▲圖1:Class diagram,取自JCIS


為了簡化程式設計,這個object graph之內的物件關係往往被設計成雙向連結。例如,圖2是一個用傳統OOAD所設計出的看板系統,其簡化後的類別圖:

  • Team:團隊,每一位使用者至少屬於一個團隊。
  • Project:專案,一個團隊有零到多個專案,可以從團隊得到屬於該團隊的專案,也可以從專案得到所屬的團隊,團隊與專案兩者之間是雙向參考關係。
  • Board:板,代表一個看板。一個專案可以有零到多個看板。專案與板之間也是雙向參考關係。
  • Workflow:工作流,一個板可以有零到多個工作流,兩者之間也是雙向參考關係。
  • Lane:道,代表工作階段。Lane有兩個子類別,分別是代表垂直的Stage,以及代表水平的Swimlane。Lane與Workflow之間也是雙向參考關係。

▲圖2:Class diagram,取自JCIS


程式開發人員可以用team.getProject().getBoard().getWorkflow().getStage() 得到某個Stage。相反地,也可以從stage.getWorkflow().getBoard().getProject().getTeam()得到該Stage所屬的團隊。這麼做的好處是,物件之間靠著參考 (reference) 整個串在一起,操作物件感覺很方便。有優點一定也有缺點,主要的缺點有三項:

  • 相依性太重:任一物件修改都可能會影響其他物件,容易產生漣波效應。
  • 物件永久性與平行處裡的能力受限:為了達到整個系統交易(transaction)的一致性,物件與關連式資料庫經常透過多的表格與外鍵關係來實現。當使用者更新系統物件時,可能需要鎖定多個表格,因而降低系統的平行處理能力。
  • 物件屬性與責任膨脹:整個問題領域只有一個Context,如果問題領域夠大,相同的類別在不同的功能中可能有不同的屬性與責任。例如,從Team與Project的角度,Board只是一種被分類的「東西」。除了board id與board name以外,它們並不在乎Board裡面的實質內容。但是,從Board、Workflow、Lane的角度,Board的內容是整個功能的核心。因為整個系統只有一個Context,因此只有一個Board類別,所以Board類別身上就會包含所有「客戶端」所需要的資料與方法。

***


Bounded Context

▲圖3:兩個bounded contexts


如圖3所示,有了bounded context概念,如果把原本的問題分成兩個bounded contexts:

  • Project Management
  • Board Management

Board同時出現在兩個bounded contexts之中,但是有著不同的意義與屬性。Project Management的Board只需要有board id、board name、project id、team id即可。而Board Management的Board才需要workflows等資料。

如此一來,當Project Management移動Board,就與Board Management的Board沒有關係,解決了上述只有一個Context所造成的三個問題:

  • 相依性太重
  • 物件永久性與平行處裡的能力受限
  • 物件屬性與責任膨脹

區分Bounded Context還有其他好處,像是在多個Bounded Context中找出企業最具競爭力的core domain,以便區分業務優先順序以及安排開發資源。

***

代價

區分Bounded Context所付出的代價就是當企業流程或資料跨越不同Bounded Context時,需要協調這些活動與資料。例如,當Board名稱在Project Management被修改時,需要通知Board Management更新狀態。或是當Board Management新增一個Board時候,也要通知Project Management產生一個Board。

***

友藏內心獨白:要因地制宜。

2020年12月2日 星期三

泰迪軟體2021年上半年開課時間表

Dec. 02 09:29~09:57

▲因應疫情Event Storming (事件風暴) 活動改用線上工具miro


2020年轉眼就要過去,又來到年底年底排課表的時間。今年因為新冠肺炎疫情的緣故,雖然泰迪軟體的生意沒有特別忙,但Teddy在下半年把主要空閒時間都供獻給ezKanban軟體的開發,持續增強【領域驅動設計與簡潔架構入門實作班】的課程深度與累積更多實作經驗。

以下是泰迪軟體2021年上半年課表:

Scrum敏捷方法實作班

  • 假日班:2月20、21日(六、日)。

領域驅動設計與簡潔架構入門實作班

  • 平假日班:1月15、16、17日(五、六、日)。

敏捷開發懶人包:物件導向技能

  • 平日班:2月23日(二)。

Design Patterns這樣學就會了--入門實作班

  • 假日班:3月13、14、20日(六、日、六)。

單元測試實作班

  • 假日班:3月27、28日(六、日)。

看板方法與精實開發實作班

  • 平假日班:5月8、9日(五、六)

Design Patterns這樣學就會了--進階實作班

  • 平假日班:5月28、29、30日(五、六、日)。

軟體重構入門實作班

  • 平假日班:5月14、15、16(五、六、日)。

例外處理設計與重構實作班

  • 平日班:6月22、23日(二、三) 。

***

以為下課程活動照片。


▼領域驅動設計與簡潔架構入門實作班


▼看板方法與精實開發實作班課程照片

螢幕截圖 2017-12-12 10.08.45


▼「單元測試實作班」課程照片。

螢幕截圖 2017-12-12 10.14.10螢幕截圖 2017-12-12 10.15.07


▼「敏捷開發懶人包:物件導向技能」課程照片。

***

友藏內心獨白:2021年還請鄉民們繼續支持。