致想給遺留系統(tǒng)寫自動化單元測試的開發(fā)團隊——事件風暴之父的工作坊實錄之二:軟件開發(fā)設計

一家大型企業(yè)的關鍵業(yè)務代碼已經(jīng)年久失修成為了難以維護的遺留代碼,有著硅谷高科技企業(yè)軟件開發(fā)管理經(jīng)驗的高管決定在企業(yè)內(nèi)部搞編寫單元測試和重構的極限編程實踐。這需要為企業(yè)遺留系統(tǒng)的代碼編寫自動化單元測試。那么編寫自動化單元測試該從哪里入手呢?

上文所提到的“領域驅動設計中國峰會2017”大會Event Storming 之父 Alberto Brandolini授課一天的“事件風暴工作坊”下午的“軟件開發(fā)設計”(Software Design)環(huán)節(jié),可以讓開發(fā)團隊了解系統(tǒng)應該具備的領域模型及其交互關系,為編寫單元測試進而驅動重構提供指導。

“領域驅動設計中國峰會2017”大會“事件風暴工作坊”下午的“軟件開發(fā)設計”環(huán)節(jié)

以下是實施步驟:

  1. 完成了“探索業(yè)務全景”環(huán)節(jié)。

  2. 確定要建模的需求
    在上午探索培訓機構的業(yè)務的基礎上,下午的任務是要為“替換Eventbrite在線應用“這個需求進行領域建模。假設你是Eventbrite的開發(fā)團隊且想了解如果入手編寫單元測試,那么可以把Eventbrite視作遺留系統(tǒng),用以下步驟來為其建模。

  3. 了解領域模型之間的業(yè)務邏輯鏈
    從需求的起源來看,用戶的需求來自于真實世界和 Read Model,并根據(jù)它們來進行 Decision Command(決策命令)。比如培訓課程的聽眾根據(jù)“課程、價格、日期、講師、城市、是否有空”這些 Read Model 來決定是否去報名參加培訓。
    用戶做了 Decision Command后,就會通過 Aggregate (像個狀態(tài)機)或 External System (外部系統(tǒng))來產(chǎn)生一個 Event(領域事件)。
    這些事件又可能會通過一個 Policy (業(yè)務規(guī)則)來觸發(fā)下一個 Decision Command。


    用戶做了 Decision Command后,就會通過 Aggregate 或 External System 來產(chǎn)生一個 Event,而這又可能會通過一個 Policy 來觸發(fā)下一個 Decision Command

    我照著上圖又畫了一個版本
三種事件風暴領域模型
  1. 用7種報事貼來貼領域模型并梳理業(yè)務邏輯鏈
    • Read model: 淺綠
    • User: 黃色小報事貼
    • Decision Command: 淺藍
    • Aggregate: 黃色大報事貼
    • Event: 橙色
    • External System: 淺粉大報事貼
    • Policy: 紫色大報事貼
      按照從左到右的時間順序來貼:


      用7種報事貼來貼領域模型并梳理業(yè)務邏輯鏈

下面其中一組同學貼出的培訓課程報名訂票的業(yè)務邏輯鏈(報名者根據(jù)培訓日期訂票,通過一個未起名的 Aggregate 生成了 Ticket Booked 事件,這個事件又經(jīng)由 Purchase Policy 觸發(fā)了 Reserve Payment 的命令):


培訓課程報名訂票

事件風暴之父的忠告

  • 領域建模達成一致是很困難的,要有充分的心理準備。

  • 要邀請領域專家和團隊所有成員,貼報事貼的空間要足夠大。


    貼報事貼的空間要足夠大
  • 在團隊貼報事貼時,要觀察不同業(yè)務部門的人的活動范圍(比如財務人員不會跑到左邊“培訓課程準備子域”來貼報事貼,這很正常),這能啟發(fā)你識別核心業(yè)務子域。有些核心業(yè)務子域是長長的一條,像泳道。有些則集中在一處,有些則會出現(xiàn)在一頭一尾,這也很正常。


    有些核心業(yè)務子域是長長的一條,像泳道。有些則集中在一處,有些則會出現(xiàn)在一頭一尾,這也很正常
  • 事件風暴領域模型聚集的方式有點像樓房——一片一片地出現(xiàn)。


    一片一片地出現(xiàn)
  • 開發(fā)團隊不要盲目相信業(yè)務人員編寫的用戶故事,要合理地向業(yè)務人員 challenge 這些用戶故事后面發(fā)生的事情。


    不要盲目相信業(yè)務人員編寫的用戶故事
  • 業(yè)務中的分支和開關會讓你備受折磨,你需要衡量它們的全局價值成效來做取舍。


    需要衡量業(yè)務分支的全局價值成效來做取舍
  • Aggregate 和 Policy 的名字很難起,可以以后再起名。

  • Policy 是一種響應式的業(yè)務邏輯,它一旦接收到 Event,就會觸發(fā)一個 Decision Command。

  • 有時候 Event 會通過"人工"的 Policy 來觸發(fā)一個 Decision Command,但有時事實并不是這樣的……


    有時事實并不是這樣的……
  • 要識別那些“千夫所指”的業(yè)務瓶頸,首先消除這些最大的障礙,才能有效提升全局優(yōu)化的成效。


    首先消除這些最大的障礙,才能有效提升全局優(yōu)化的成效

我的一些理解及 Brandolini 的回復

  • Aggregate 可以理解為“數(shù)據(jù)完整性的維護者”。
  • “千夫所指”的業(yè)務瓶頸可以作為編寫自動化測試的第一個測試用例。
  • 我試圖把 Brandolini 的上述7種事件風暴領域模型與 Evans 的 Model-driven design 中談到的7種領域模型按下面的方式對應起來,但Brandolini給了令我驚嘆的回復:
    • 我試圖兩者對應起來:
      • Read model(淺綠)可以對應 Entities 和 Value Objects,而后兩者可以用 Factory 來創(chuàng)建,其中 Entities 可以保存在 Repositories 里面。
      • User(黃色小報事貼)沒有對應。
      • Decision Command(淺藍,可以對其編寫自動化測試)可以對應 Aggregates、Entities 或 Value Objects 里面的行為。
      • Aggregate(黃色大報事貼,可以對其編寫自動化測試)可以對應 Aggregates ,而 Aggregates 可以由 Factory 來創(chuàng)建,之后可以保存在 Repositories 里面。
      • Event(橙色)可以對應 Domain Events。
      • External System(淺粉,可以對其編寫自動化契約測試)可以對應 Services。
      • Policy(紫色,可以對其編寫自動化測試)可以對應 Aggregates、Entities 或 Value Objects 里面的行為。
        Evans 的 Model-driven design 中談到的7種領域模型

        Brandolini 的7種事件風暴領域模型
    • Brandolini 的回復:
      • Eric Evans的領域模型出現(xiàn)在CQRS之前。雖然這些模型目前仍然有效,但是CQRS的影響力更大。
      • Read Model 如今是(DDD領域中的)一等公民。而將其對應到 Entities 和 Repositories 曾經(jīng)是以前那些做法的薄弱環(huán)節(jié)。
      • Policies 其實是被漏掉了。Eric 從來沒有說過領域模型的搜集工作已經(jīng)完成了。所以對于這一點沒有所謂的官方建議。一些人創(chuàng)建了代表進程的聚合,另外一些人則將大量的邏輯推向了 Application Services(這通常讓領域模型變得貧血)。 Greg Young 曾指出在這些方面應該有所變化。
      • 我偏好于“對稱性”的領域建模,即將 Aggregates 將 Commands 轉化為 Events,而 Policies 對 Events 作出響應并調(diào)度 Commands 來進行工作。

總結
對于要為企業(yè)遺留系統(tǒng)的代碼編寫自動化單元測試的開發(fā)團隊,可以在進行了“探索業(yè)務全景”環(huán)節(jié)之后,使用“軟件開發(fā)技術”環(huán)節(jié)中的識別7種事件風暴領域模型的技術,來優(yōu)先梳理那些“千夫所指”的有業(yè)務瓶頸的業(yè)務的邏輯鏈,然后可以開始對其中的 Decision Command、Aggregate 和 Policy 編寫自動化單元測試。用這些單元測試來驅動遺留系統(tǒng)代碼的重構,讓遺留系統(tǒng)的代碼變得易于維護。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容