l

2019年12月3日 星期二

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

Dec. 03 16:43~17:28

▲領域驅動設計與簡潔架構入門實作班課程照片 (原Clean Architecture實作班)


時間過得好快轉眼就要跟2019說Bye Bye,又到了年底排課表的時間。2020年Teddy預計新開一門【行為驅動設計與實例化規格實作班】課程,開課時間大約在2020年8月之後。

以下是泰迪軟體2020年上半年課表,原本的【Clean Architecture實作班】,因為課程內容包含許多領域驅動設計(Domain Driven Design;DDD),所以Teddy將課名調整成【領域驅動設計與簡潔架構入門實作班】。

Scrum敏捷方法實作班

  • 假日班:2月22、23號(六、日)。
  • 假日班:5月9、10號(六、日)。

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

  • 假日班:3月21、22號(六、日)。

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

  • 假日班:3月7、8、14號(六、日、六)。

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

    • 假日班:4月24、25、26號(五、六、日)。

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

    • 平日班:3月24(二)。

    領域驅動設計與簡潔架構入門實作班(舊課程名稱為:Clean Architecture實作班)

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

    單元測試實作班

    • 假日班:4月11、12號(六、日)。

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

    • 假日班:6月13、14號(六、日)。

      軟體重構入門實作班

      • 平假日班:4月17、18、19號(五、六、日)


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

      螢幕截圖 2017-12-12 10.08.45

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

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

      螢幕截圖 2017-12-12 10.15.26螢幕截圖 2017-12-12 10.15.51螢幕截圖 2017-12-12 10.16.10

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

      螢幕截圖 2017-12-12 10.11.38

      ***

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

      2019年12月2日 星期一

      你也可以撰寫模式

      Dec. 02 09:53~10:55


      重複使用知識

      11月30日Teddy辦了第一次一整天的【模式寫作工作坊】,六個小時的工作坊內容包含了:

      • 介紹模式歷史與常見格式。
      • 閱讀模式
      • 寫作模式

      Teddy發現對於第一次寫作模式的人來講,第一個遇到的困難點就是如何挑選寫作題材。模式的定義,可以簡單用以下一句話來說明:

      模式就是在一個特定領域中,針對重複出現問題所提出證明可行的解決方案。

      也就是說,模式不是創新,而是將已知可行且可重複使用的解決方案與其所要解決的問題記錄下來。因此,模式寫作可視為一種整理知識的過程。要寫出好的模式,最簡單的方式就是從自己熟悉的身邊事物開始著手。

      ***

      生活觀察家

      模式不限於軟體開發,而是可以很生活化,包含所有的領域。只要認真做事、認真過生活,便可觀察到許多有趣的模式。

      例如,對於一個專業宅宅而言,每天在家裡關注不同的網路紅人與YouTuber,久而久之很容易察覺這個領域的常見模式。像是:

      • 自己的定位:確定自己要當哪一種類型的網紅,例如知識性、網美、搞笑、旅遊等。
      • 鐵粉:找到自己的定位之後,想辦法吸引一群死忠支持自己的鄉民。
      • 人頭粉絲:有了基本盤之後,要擴大自己的網路人氣。此時可考慮廣納各方人士,增加自己的粉絲人數,壯大氣勢。
      • 互相拉抬:與其他知名的網紅合作,增加彼此的人氣與粉絲人數。
      • 系列故事:製作主題性的系列故事來吸引更多的關注者。
      • 業配:「風蕭蕭兮易水寒,網紅一樣要吃飯」。為了讓網紅這個職業可以長久持續下去,可以考慮接業配增加收入。
      • 安排好的偷拍照片:現在網紅這麼多,如何增加自己的曝光度?利用人們偷窺的好奇心,設計一些「偷拍自己的照片」,然後故意流出到各大社群網站,讓「小時不讀書,長大當記者」的朋友們幫你免費宣傳。
      • 小鈴鐺:你經常發布訊息、照片或影片更新,但你的粉絲卻無法即時收到。請粉絲們按下「小鈴鐺」,以便收到你最新的訊息。

      ***

      模式範例

      接下來Teddy寫一個網紅模式給鄉民們參考。

      安排好的偷拍照片

      ▲圖片來源在此

      Context:你將自己定位為網美型網紅。

      Problem:如何增加自己的粉絲數?

      Forces:

      • 你在知名社群軟體,例如IG與FB經營一段時間,定期發布自己的照片與短片。
      • 你有基本的粉絲。
      • 你不想花太多經費或時間。
      • 你父母不是知名藝人。

      Solution:拍攝自己的清涼偷拍照片,找人將其張貼在PTT、爆料公社等社群,吸引 無腦 媒體報導。

      Resulting Context:大部分的人喜歡看美女/俊男,更喜歡看被偷拍的美女/俊男。套用本模式可在短時間內衝高自己的人氣,進而增加自己的 豬哥 粉絲人數。實施本模式的成本很低,只要自己願意,可以簡易套用。

      但是,不可忽視鄉民的智慧。如果偷拍照片拍得太假,可能造成反效果,被鄉民貼上「假掰」、「做作」的標籤。

      ***

      友藏內心獨白:模式就是有六個空格的便當盒。

      2019年11月26日 星期二

      透過協作產生敏捷需求

      Nov. 26 17:48~18:35


      不是需求

      許多跑敏捷的團隊會使用user story(用戶故事、使用者故事)來表達「需求」,大家一般認為寫user story是Product Owner的責任,團隊只要照著user story所描述的內容就可以做出PO所希望的功能。

      但實際上功能做好之後卻經常被PO要求改東改西,導致開發團隊抱怨:「Product Owner寫的user story太簡略,害他們不能『按圖施工,保證成功』,要不斷地重工」。PO則是不滿開發團隊都不動腦筋,遇到問題也不及時跟他溝通與釐清。

      其實user story不算是傳統軟體開發所說的需求或規格,user story只是引發團隊討論需求的一句話。真正的需求,透過開發團隊、Product Owner與利害關係人的對話、討論、探索而產生。討論之後所產生的需求,可以透過specification by example(實例化規格)的方式記錄下來。

      另外,撰寫user story的責任也不能全部推給PO。User story的「為了…(目的)」所描述的是使用者所遭遇的問題,這是PO需要負責搞清楚的部分。而「我想要…(做什麼)」這句話已經包含某種解決方案,則是需要PO與開發團隊一起討論,尋求各種可能的做法。

      ***

      心態改變

      上週Teddy在上【Scrum敏捷方法實作班】介紹user story的時候跟學員提到上述觀念,下課時有一位學員說…

      以前團隊在product backlog refinement workshop的時候,我們都習慣要求PO要把user story寫清楚,如果有不清楚的地方,我們會責怪PO,覺得他沒有準備好就找我們來開會。但上完課之後,我才發現原來撰寫user story的責任不能完全推給PO一個人。下次再開refinement workshop,我會改變作法,多提供意見。

      ***

      協作遊戲

      敏捷開發是一種協同合作的活動,不是傳統瀑布式開發那種「透過文件溝通」的模式,更不是找個issue tracking system(議題追蹤系統)來「開票、領票」(分派、追蹤工作)。

      只是做做敏捷的樣子,心態沒變,還是白搭。

      ***

      友藏內心獨白:讓團隊每個人都動腦真的不容易。

      2019年11月19日 星期二

      Pattern寫作工作坊

      Nov. 19 16:54~17:57


      一起做功德

      PLoP(Pattern Languages of Programs)是模式(Pattern)社群一年一度的聚會,在全球各洲都有類似的活動,在亞洲舉辦的PLoP稱為AsianPLoP。

      AsianPLoP 2020 明年3月4-6日將於台北舉辦,這個活動往年都在日本東京舉辦,明年是第二次移師到台北來。因為Teddy的指導教授是活動主辦人之一,而Teddy也是模式的愛好者,利用此次機會跟AsianPLoP 2020的主辦單位「台灣軟體工程學會」合作,於今年11/30日在泰迪軟體舉辦一天的【Pattern寫作工作坊】,藉此活動讓更多鄉民有機會接觸的模式社群,從了解模式、閱讀別人的模式,進而能夠利用模式來整理自己的知識(寫作模式)。

      本工作坊費用8,000元,由「台灣軟體工程學會」開立收據。所繳交費用可全額抵免明年的AsianPLoP 2020研討會費用。也就是說,報名此工作坊的學員本人明年可以免費參加在北科大舉辦的AsianPLoP 2020 (無論是否投稿,都可參加)。

      工作坊已確定開課,對模式有興趣的朋友,歡迎一起來聽聽模式的歷史、閱讀模式、寫作模式。

      ***

      Teddy的模式之旅

      Teddy從1997年開始接觸到設計模式,當時讀了GoF的《Design Patterns》,實際應用之後覺得設計模式對於軟體開發很有用,但對於書中提到的23個模式也是一知半解。

      幾年後回北科大念博士班,因為之前工作從事e-learning系統與數位教材製作工具的開發,對design patterns也熟,因此指導教授建議Teddy可以研究e-learning領域的patterns。因此,讀了pattern發明人建築師Christopher Alexander一系列的幾本書,同時也開始寫作e-learning patterns。在2004年時,第一次到美國參加PLoP,那時有種劉姥姥逛大觀園的震撼---原來這就是傳說中的PLoP啊。

      這幾年Teddy建議不少人讀Alexander的書,但似乎效果不適很好。Alexander的書有點哲學的味道,剛開始不是那麼容易讀懂。但他的思想的確影響了很多軟體社群的人,Design Patterns、Architecture Patterns、Testing Patterns這些大家都耳熟能詳就不說了,最近1~2年在台灣流行的領域驅動設計(Domain Driven-Design;DDD),發明人Eric Evans所寫作的「藍皮書」,其實就是一本DDD Pattern Languages,書中介紹了數個DDD patterns。


      ▲「藍皮書」本身就是一堆patterns


      ***

      有什麼用

      PLoP研討會已經舉辦了20幾年,學習pattern不是什麼趕流行,而且坦白說有點門檻。對Teddy而言,pattern(特別是pattern language)的訓練有三個主要的好處:

      • 讓人具備一種關照全面與看到事情本質的能力。學習pattern很重要的一環就是觀察Forces,體驗Forces。漸漸地,你更能關注事物核心的Quality,而不是表面的Name(因為Quality Without A Name)。
      • 吸納新的知識:很多領域專家,會將他們多年累積的知識寫成pattern。對於真正了解pattern的人,就比較容易吸收這些以pattern所表達的知識。以DDD為例,Teddy很晚(2013)年才開始接觸,但因為Teddy的腦中已經內建 九陽神功 pattern解譯器,對於DDD的學習就比一般鄉民要來得容易與深入一些。
      • 系統性的整理自己的知識與經驗。你覺得自己很厲害,好,然後呢?FB貼廢文、寫blog、參加社群聚會當講者,這些都很好。但,如果要更進一步挑戰自己,將自己的經驗整理成pattern是一個很好的方式。

      ***

      報名

      報名表單在此,錯過這次,下一次就要等……不知道有沒有下一次了。

      ***

      友藏內心獨白:我以為畢業後就不用再寫pattern了XD。

      2019年10月18日 星期五

      學習DDD有感

      Oct. 18 14:46~16:18


      客戶的發問

      昨天下午到客戶家介紹領域驅動設計(Domain-Driven Design;DDD),以及如何運用事件風暴(Event Storming)、Clean Architecture、TDD的工具落實DDD。

      活動結束時有同仁問Teddy:「你演講中提到DDD的好處我們都可以理解,具體上有沒有什麼實際的經驗可以分享?」

      ***

      第一次接觸

      Teddy首先想起幾年前剛接觸DDD,讀到《Domain-Driven Design: Tackling Complexity in the Heart of Software》這本書的情景。由於多年來Teddy已經習慣物件導向分析與設計(Object-Oriented Analysis and Design;OOAD)方法,當時覺得DDD強調建立領域模型(domain model)這件事,和OOAD並沒有什麼不同。另外書中提到的ubiquitous language、bounded context等觀念,其實就是pattern發明人Christopher Alexander在《Notes on the Synthesis of Form 》與《The Timeless Way of Building》等書中所提到的設計方法。至於DDD的Tactical Design(戰術設計)所包含的entity、value object、aggregate、factory、service、layered architecture這些patterns,也不過就是物件導向設計中常見的作法。

      結論就是,這本書稍微翻一下就沒再理它了XD。

      ***

      第二次接觸

      過了一陣子,可能是因為微服務(Microservice)流行的緣故,DDD也跟著流行起來,Teddy同溫層的「臉友」談論DDD的人漸漸多了起來。這也引起Teddy的好奇,想說光看《Domain-Driven Design: Tackling Complexity in the Heart of Software》可能不夠,又買了幾本DDD的書,花了不少時間用力讀了一下。此時對於DDD所提出的這堆patterns的內涵有比較完整的認識,但總覺得,要開發軟體我就用熟知的OOAD就可以了,找不到一個施力點來使用DDD。

      ***

      第三次接觸

      兩年前在指導教授的建議之下,Teddy停掉在北科大資工所兼任的「軟體生命週期管理」課程,改教「軟體架構」。當時剛好Robert C. Martin 的新書《Clean Architecture: A Craftsman's Guide to Software Structure and Design》 出版,Teddy就用這本書當教科書。兩年來為了學習與教學的目的,Teddy設計兩個不同的專案,用了好幾種方式來詮釋Clean Architecture的實作。後來發現搭配DDD的domain model、ubiquitous language、bounded context、event storming、entity、aggregate、repository、service、domain event等pattern,以及Clean Architecture,加上採用TDD/BDD/SBE的方式實作系統,可以很漂亮的串起這些軟體開發方法。

      此時,Teddy才慢慢感受到DDD的威力,特別是ubiquitous language in code的實踐,對於軟體的開發與維護所帶來的好處。另外,aggregate與domain event的使用,讓系統模組自然支援現今主流的分散式架構,這是傳統OOAD方法需要特別而外去關注才做得到的地方。

      ***

      第四次接觸

      約一年前Teddy帶幾位研究生開發一個看板系統,當初一開始設定的目標是要採用Clean Architecture作為此系統的架構。隨著開發活動進行,慢慢發現使用到DDD patterns越來越多,像是原本Clean Architecture就很強調的domain model,以及DDD的ubiquitous language in code、aggregate、repository、service、domain event等。

      多年來Teddy也帶過好多組學生開發軟體,每次都立下宏願,希望用畢生所學,讓學生可以開發出「高品質」軟體。坦白說,多年來這個宏願一直無法實現。一方面研究生時間不多,要修課、寫作業、過日子,而且每年都有學生畢業,真正有時間投入專案開發頂多就是一個寒暑假而已。

      另一方面學生的軟體開發能力與經驗也不足,還在學習當中,不容易要求在短時間內就可以做出設計良好的系統。

      但是,這次開發看板系統Teddy感受到一絲曙光。初期Teddy花了很多時間與學生code review,先確認他們的Clean Architecture沒有走偏(目前還是有點偏,但至少沒有歪的太厲害)。後來隨著一個個user story實作的機會,幫助學生認識如何落實domain model與ubiquitous language in code。Teddy覺得光是這兩點做到,再搭配Clean Architecture,整個軟體系統的可讀性提升好幾個檔次。

      Teddy希望有朝一日能做到「即是是學生所開發的軟體,也能夠達到專業的水準」。

      ***

      老外幫我們做實驗

      Teddy後來告訴發問的同仁:「DDD外國外已經提出10幾年了,有很多老外已經幫我們做過實驗。落實DDD的難度相對而言是比較高的,但是一旦公司與團隊能夠掌握這項方法,以我切身的經驗,我相信可以讓軟體開發更接近『讓軟體變軟』這個目標。」

      落實DDD除了技術上的門檻以外,還有一點非常重要,就是團隊中有沒有領域專家,以及這位(或這一票XD)領域專家是否願意與開發團隊緊密合作,採用迭代與增量的模式,共同建立軟體系統的domain model與ubiquitous language。

      DDD的技術門檻,可以來上泰迪軟體的〈Clean Architecture這樣學就會了實作班〉補足。至於有沒有領域專家願意與團隊緊密合作,就只能靠緣分了XD。

      ***

      放下偶包

      整個學習DDD的過程讓Teddy有一個很深刻的感觸:「很多時候以往的成功經驗可能會阻礙自己學習新的事物。」OOAD太熟導致一開始忽視DDD、Waterfall太熟導致覺得敏捷無用、壓專案時程太方便導致沒有給團隊自主決定的機會、成功的大公司導致無法冒險也沒有容忍失敗的空間。

      所以武俠小說裡面的橋段:「欲練神功,揮劍自宮」都是真的。

      ***

      友藏內心獨白:該不會下一頁是不用自宮,也能成功吧!

      2019年7月2日 星期二

      領域驅動設計學習筆記(6):Aggregate (中)

      July 02 21:45~22:48


      在上一集〈領域驅動設計學習筆記(5):Aggregate (上)〉提到為了避免破壞aggregate invariant(聚合不變量或聚合規則),aggregate root在回傳資料的時候,需要考慮:

      1. 完全禁止回傳Aggregate內部的Entity。
      2. 可以回傳Entity,但只回傳immutable Entity或是Entity的deep copy。
      3. 設計immutable interface,讓Entity實作immutable interface並透過immutable interface回傳給客戶端。

      今天討論這幾種做法的優缺點,並展示一個透過自動產生immutable proxy的工具來解決這問題的範例。

      ***

      禁止回傳Aggregate內部的Entity

      • 優點:這個方法因為禁止aggregate root回傳內部entity,所以客戶端不可能透過aggregate內部entity來破壞aggregate invariant。
      • 缺點:為了提供資料給客戶端,aggregate root可能需要將內部entity轉成DTO(data transfer object)再往外傳。這種做法有點類似clean architecture中,use case層定義雙向介面將entity往外傳遞。從架構的角度來看可以切得很乾淨,但是需要花費額外的功夫包一層DTO。

      ***

      回傳immutable entity或是entity的deep copy

      • 優點:用相同的domain model(直接回傳aggregate內部的entity)來處理程式邏輯,而且因為回傳的entity是不可修改的物件,或是原本物件的複製版本,所以也不可能透過這個entity破壞aggregate invariant。
      • 缺點:無論是實作immutable entity或是deep copy(GoF的Prototype設計模式),都需要花費額外的設計、實作與測試的功夫。特別是deep copy,不小心沒有實作好變成shallow copy就GG了。

      ***

      設計immutable interface

      Immutable interface是一種設計模式,請參考c2。簡單講,immutable interface是一個只有getter沒有setter的介面。設計好immutable interface之後,讓你的entity實作此介面。如果aggregate root要回傳entity,只能傳回entity所實作的immutable interface,如此一來客戶端就不可能修改到aggregate的資料。

      Immutable interface的缺點和回傳DTO類似,domain model裡面除了原本的entity,又多了另一種代表「不可修改」的immutable interface。

      ***

      折衷作法

      如果程式語言可以支援自動回傳immutable object,這個問題就不是問題。Teddy不知道有沒有哪個程式語言有這種功能,目前只能從上述三種做法中挑一種來實做。

      Teddy想用方法二。方法二有兩種實作,考慮到回傳entity的deep copy比較不好實作,所以決定優先選擇回傳immutable entity的方式。

      要實作immutable entity,可以套用Proxy設計模式,概念如下:

      Ministage是一個mutable介面,MinistageImpl是這個介面的實作,而ImmutableMinistage則是將MinistageImpl包裝一層,只要客戶端呼叫到setter的函數,就丟出例外。

      這種方法的優點是,從客戶端的角度,他看到的就是Ministage這個domain model的概念。至於它是mutable還是immutable,則只是實作細節。

      這種做法當然也有缺點,首先設計上當然比沒套用Proxy設計模式要來的複雜。其次,因為在編譯期間(compile time)客戶端不知道拿到的Ministage是mutable還是immutable,如果不小心拿到immutable但卻呼叫到它的setter函數,則會出現runtime exception。

      程式設計師都有偷懶的天性,Teddy想回傳immutable entity但又懶得手動實作proxy,於是google了一下,找到一個Java語言的reflection-util工具,可以自動產生immutable proxy。


      ▼使用方法很簡單,以maven建構工具為例,首先加入reflection-util的參考。



      ▼接著在程式中透過ImmutableProxy.create()方法,可以直接產生immutable entity,非常容易使用。

      ***

      從Clean Architecture的角度來看…

      使用reflection-util這種工具,可以幾乎無痛產生immutable entity。但是從clean architecture的角度來看,在最核心的entity層引用外部工具,違反了相依性原則,你的架構就變得不再那麼乾淨了。

      Teddy覺得這個「小違規」目前是可以接受的折衷方案。因為你可以透過將reflection-util再包一層,讓aggregate root透過間接的方式呼叫reflection-util來獲得immutable entity。有朝一日如果真的不想使用reflection-util,也可以在影響最小的情況下,以其他實作方式將它取而代之。

      所以,雖不完美,但還可接受。

      ***

      友藏內心獨白:設計就是取捨後的結果。

      2019年6月17日 星期一

      領域驅動設計學習筆記(5):Aggregate (上)

      June 17 15:36~16:42


      問題

      在物件導向的domain model裡面,物件和物件之間經常有著複雜的關聯(associations)。如下圖所示,一個看板系統的domain model,Board擁有若干的Stage,一個Stage擁有若干個MiniStage,一個MiniStage擁有若干個SwimLane,一個SwimLane擁有若干個WorkItem。


      當修改這些物件狀態時,如果不小心很可能會違反系統的不變量(invariant)或固定規則而導致系統狀態不正確(產生bug)。例如,看板系統的一個不變量是:「SwimLane的WorkItem數量不可以超過WipLimit數值。」

      試想在一個多人使用的狀況下,為了滿足上述不變量,當修改SwimLane的狀態時,你可能要鎖住SwimLane,甚至是鎖住整個系統,導致系統無法使用或效率很差。

      ***

      Aggregate Pattern

      Aggregate是領域驅動設計(Domain-Driven Design;DDD)裡面很重要的pattern。依據《Domain-Driven Design: Tackling Complexity in the Heart of Software》書中的定義,Aggregate想要解決的問題與解決方案分別為:

      Problem

      It is difficult to guarantee the consistency of changes to objects in a model with complex associations. Invariants need to be maintained that apply to closely related groups of objects, not just discrete objects. Yet cautious locking schemes cause multiple users to interfere pointlessly with each other and make a system unusable.

      很難保證具有複雜關聯的模型中物件更改的一致性。 需要維護不變量,這些不變量適用於密切相關的物件組,而不僅僅是離散的物件。 然而,謹慎的鎖定方案會導致多個用戶無意義地相互干擾並使系統無法使用。(中文修改自google翻譯)


      Solution

      Cluster the ENTITIES and VALUE OBJECTS into AGGREGATES and define boundaries around each. Choose one ENTITY to be the root of each AGGREGATE, and control all access to the objects inside the boundary through the root. Allow external objects to hold references to the root only. Transient references to internal members can be passed out for use within a single operation only. Because the root controls access, it cannot be blindsided by changes to the internals. This arrangement makes it practical to enforce all invariants for objects in the AGGREGATE and for the AGGREGATE as a whole in any state change.

      將ENTITIES和VALUE OBJECTS聚集在一起形成AGGREGATES並定義AGGREGATES的邊界。 選擇一個ENTITY作為每個AGGREGATE的根,並透過根控制對邊界內物件的所有存取。 允許外部物件僅保留對根的引用。可以傳遞對內部成員的瞬時引用,以便僅在單個操作中使用。 因為根控制存取權限,所以內部的更改不能繞過它。 這種安排可以確保任何針對AGGREGATE裡面的物件以及AGGREGATE本身的狀態修改都不會違反不變量。(中文修改自google翻譯)

      ***

      實作細節

      以上述看板系統為例子,Stage、MiniStage與SwimLane形成一個Aggregate,Stage是Aggregate Root。依據DDD的定義,為了確保不變量:

      1. 所有對於Aggregate內部物件的操作都要透過Aggregate Root。也就是存取MiniStage與SwimLane都要透過Stage。
      2. 外部物件只可以擁有Stage物件的reference(因為它是Aggregate Root),不可以擁有MiniStage與SwimLane的reference。
      3. 但是,Stage可以將MiniStage與SwimLane往外傳,只不過客戶端程式只能在單一method中操作這些entity,不可以把它們的reference保存起來(例如,不能存在data member裡面)。

      前兩點很容易理解與實作,但第三點就需要進一步討論。因為如果把MiniStage與SwimLane往外傳,既使在單一method裡面使用,也可能繞過Stage直接呼叫MiniStage與SwimLane,因此改變Stage這個Aggregat的狀態而破壞不變量。

      所以,在實作Aggregate的時候,就有幾種可能的選擇:

      • 完全禁止回傳Aggregate內部的Entity。
      • 可以回傳Entity,但只回傳immutable Entity或是Entity的deep copy。
      • 設計immutable interface,讓Entity實作immutable interface並透過immutable interface回傳給客戶端。

      無論採取哪種方式,在實作時都需要特別留意,以免Aggregate的不變量一不小心就被違反了。

      ***

      廣告

      對於DDD的Aggregate與Event Storming(事件風暴)有興趣的鄉民,可參考泰迪軟體的【Clean Architecture這樣學就會了實作班】,2019年7月份課程已確定開課。

      ***


      友藏內心獨白:還是要看定義。