來自Jdon的DDD總結

http://www.jdon.com/jivejdon/thread/39833

 

 

1. "領域驅動設計" = “問題域模型驅動領域建模” + “領域建模驅動軟件實現”

2. 問題域建模的過程就是業務領域分析的過程,對於企業而言就是業務架構的分析和建立過程,這裏不包含任何OO的設計成分,主要從組織、流程和業務能力三個維度來分析業務。

3. 記住很多模式沒有什麼用處,帶着問題在模式中尋找答案纔是正確的使用方式,讓那種解決方案的思想融入到你的模型當中,然後徹底地忘掉那些所謂的模式名詞。

4. 好的領域建模應該具有柔性,能夠伴隨着用戶一起成長。

5. 這讓我意識到業務建模應該回歸自然:一談起來建模技術,就離不開國外提出的OO、EDA之類的東西,其實我們的老祖宗早就有了“摸脈”的說法,現在的SOA、ESB之類的東西是不是就像打造一個企業的“神經脈絡”,而“OO”是不是就像“神經元”,它們之間的通訊就是靠生物電脈衝,這就是消息驅動。

6. 《領域驅動設計》一書中只是強調了業務的水平分割,然而在大項目裏還有垂直分割,注意垂直分割不完全等同於包的劃分。目前有一種非常錯誤的做法,就是一上來就開始對象建模,然後再進行歸類劃分模塊;正確的做法應該是前期以確認領域邊界功能爲主,後期以確認領域內的對象模型爲主。關於領域的切分,《領域驅動設計》沒有過多談及,其實方法就是不斷對企業業務知識的學習和分析。當你對一個業務認識不清的時候,最好的辦法就是不同企業環境下去分析這個業務,那這個業務的所有發展變化就清楚了,這就像那些生物學家總是喜歡通過長期的野外考查來學習知識。這個工作做好了,項目就成功了50%。

7. 領域的邊界就是服務,也是對外提供服務的唯一入口。領域服務和領域對象模型是一個業務領域的2個不同側面。領域服務強調是從外向內看,反映了“外部對業務領域的使用功能”;領域對象模型強調業務領域就像一個獨立的具有一定自主能力的生命體,反映了“業務領域的內部運行機制”。領域對象模型的功能是不能對外暴露的,不然會造成外部對領域對象的耦合。

8. 不要一說“面向關係設計”就是錯的。因爲用戶的角度看,業務本來就是面向關係和過程的,這非常自然;而從設計看,業務是不同主體在相互作用。這就是爲什麼越靠近用戶的地方面向關係和過程的設計味道越濃的原因了。

9. “類和職責”的叫法讓我總感覺比較僵化,像是沒有生命的死細胞一樣,覺得這是一種西醫模式。我更崇尚一種中醫模式,強調建模是動態的、基於場景交互的,應該用更自然的還原業務本來面目的眼光去審視建模過程,也就是說“有機的業務建模”實際上就是“技術建模”的問題域建模,而“技術建模”只是“業務建模”的技術落地而已。

10. 關於建模工具,像“用例圖,流程圖,狀態圖之類”的並不是我理想的建模工具,雖然他們確實能表達一些東西。我理想的業務建模工具應該是能從角色(組織或者人)、流程、業務能力三個維度立體地、動態地分析描述業務模型,希望可以是一個動態的3D視圖和流圖,並可以按不同的維度分析展開。

 

11. 那對於我們做企業業務建模,終極目標應該是個什麼樣子呢?我認爲這個終極目標一定是非常複雜的(也就是我原來常說的大項目場景),因爲只有在複雜的場景下才能真正檢驗各種建模技術的偏頗。想想看,我們的建模目標應該向誰學習。論壇也有人說過,“自然的就是最好的”。是啊,經歷過億萬年才進化出來的模型難道不值得我們學習嗎,難道不是我們的目標模型嗎!呵呵,答案已經呼之欲出了,就是“仿生物建模”。是的,沒錯,如果說利用我們的建模技術能夠去構建出一個複雜的仿真人,具備人的一些特徵和功能的話,那這種建模技術就是完美的。

12. 企業的業務建模可以分爲兩個層面,”宏觀建模”和“微觀建模”。“宏觀建模”是指首先要對企業做一個整體的信息化規劃,對企業進行整體的的業務架構建模,其成果就是業務組件。其中的方法論可以參照IBM的CBM,不過IBM好像也只是諮詢,真正的落地還要靠自己對CBM的領悟。Evans的DDD主要屬於“微觀建模”部分。對於“微觀建模”,我認爲分爲2個方面:“結構化建模”和“行爲建模”,這是一體兩面。我覺得Evans對DDD總結了幾個關鍵的要素:實體、值對象、聚合、工廠和存儲,但其中還少了一個非常重要和關鍵的要素:“事件”。

13. 衆所周知,人體是由很多細胞構成的,那細胞之間是如何作用的呢,其實就是“刺激”和“響應”。其中“刺激”就是“事件”,所以“事件”是業務模型本來就應該具備的要素,而不是什麼技術層面的東西。從“事件”角度看,“職責的本質就是事件的響應”。

14. “結構化建模”是指建模中除了靜態的實體和值對象的結構關係外,從“事件”角度看,實體或者值對象還具備一些“本能的反應”,比如"手指會彎曲"。而“行爲建模”是指通過神經中樞(消息總線)來控制不同對象的本能反應來完成一個複雜的組合,比如"用手彈鋼琴"。

15. “一上來先識別類,然後就考慮怎麼分配職責”的做法是一種本末倒置的僵化的靜態建模。這種方式往往讓人落入一種只注重“形”而忽略“意”(業務本來的面目)的怪圈。我認爲建模分爲2個階段,第一個是“有機的業務建模”,第二個是“技術建模”。“業務建模”和“技術建模”的區別是:“業務建模”完全是業務語言,不含任何技術成分,比如“類、值對象和職責”的概念,在“技術建模”中才涉及那些概念。“業務建模”做好了,“技術建模”就成了自然而然的東西了。
“有機的業務建模”的一個非常重要的特徵就是“有機”,就是強調業務模型中的每一個“業務主體”都是一個生命體。這些業務主體都有“生命特徵”,在一定條件下受到外界的刺激就會發生一定的行爲。這些業務主體構成了整個業務模型。當然,這些業務主體的規模和層次不同:比較大的業務主體就是“領域主體”,他有明確的領域邊界;而領域主體的對外界響應其實是通過內部的“業務核心主體”的協作來完成的,有的看見的見摸得着————具有業務實體的特點,有的比較抽象————控制規則和流程,當然有的“業務核心主體”可能是個多核細胞。“有機的業務建模”有一個非常重要的工作就是“檢查業務模型的生命健康狀況”。需要注意的是這個業務建模可能是通過不完善的用戶需求建立起來的,所以我們需要構建多種場景通過不同的刺激去看這個領域主體內部的響應中是否有“異常情況”,如果有那就要開刀了。
關於“技術建模”,我認爲“對內功能和對外功能要分開”,領域對象不建議同時承擔對內和對外的功能,但小項目除外。服務對外要封裝和隱藏領域內部的東西,提供的是服務接口;同時服務要負責領域內部對象的行爲組裝。從另外一個層面看,服務是需求,領域對象模型是實現。值對象的本質就是反映業務主體的不同業務特徵,可能是業務主體的臨時狀態(比如用戶的發帖數)或者屬於另一業務主體的狀態值。從微觀看,聚合是交互最緊密的業務對象的封裝,從宏觀看,聚合是一個具有明確業務邊界的獨立業務核心主體。所以聚合只是形式,業務模型的正確建立纔是決定要素。

16. 相互作用原則全面、深刻地揭示了事物之間的因果聯繫,是因果關係在邏輯上的充分展開。在客觀世界的普遍聯繫鏈條中,原因和結果經常互移其位、相互轉化。受原因作用的事物在發生變化的同時也反作用於原因,從而把因果性關係轉變爲相互作用的關係。其中每一方都作爲另一方的原因並同時又作爲對立面的反作用的結果表現出來。整個物質世界就是各種物質存在普遍相互作用的統一整體,相互作用是事物的真正的終極原因,在它之外沒有也不可能有使它運動和發展的原因。相互作用也是系統內部諸要素的關係和聯繫的形式。要素之間相互作用的方式構成系統存在的基礎,系統中要素的相互作用是決定系統發展方向的因素。相互作用只有藉助於特殊的物質載體才能實現,相互作用的內容取決於組成要素的物質層次和性質。例如,現代生物學把相互作用劃分爲分子的、細胞的、器官的、機體的、種的、生物圈等不同水平的形式。社會生活是最複雜的相互作用的形式。 相互作用是客觀的、普遍的。具體的相互作用是整個物質世界相互作用鏈條的環節和部分,相互作用的普遍性和絕對性通過無限多樣的具體的相互作用而體現出來。相互作用是事物的屬性、結構、規律存在和發展的條件。相互作用範疇具有重要的方法論意義。認識事物意味着認識它們的相互作用,要揭示事物的本質屬性,就必須研究事物之間具體的相互作用的特殊性。相互作用的實質是矛盾以及矛盾諸方面的相互依存和鬥爭。在諸多因素的相互作用中,必有一種起着主導的決定的作用。在實際工作中,只有認清事物之間相互作用的特點和規律性,才能認識和把握事物的本質。 “事件”這個詞的確有技術範疇的嫌疑,但說到“相互作用”、“輸入和輸出”,大家都會明白的。過去的OO過於僵化、教條,偏重於靜態場景,忽略了客觀世界運動和相互作用的本質規律,而最近出現新技術和對OO的反思“正在迴歸自然”。

17. “世界是有事物及其活動組成”或者“世界由事物及其相互作用組成”是非常樸素、直觀的世界觀。

18. 建議學習“經過億萬年進化而來的客觀存在的生物控制模型”,我們都知道“人體是通過神經網絡來控制不同的肌肉、骨骼來做出各種複雜的動作的”。“刺激和響應”是客觀存在的,而“場景”只是我們對客觀世界的主觀認識。“刺激和響應”,舉個例子,人的最外層的皮膚就如同“門面”,用來接受外界的“刺激”,內部再由“大腦”下達指令,指揮各個“肢體”進行“響應”。 “神經網絡”是被這層皮膚覆蓋加以保護。 “神經元”向“皮膚”註冊可能完成的“響應”,而“皮膚”接受“刺激”後由大腦進行反饋而回調“神經元”,“神經元”再完成各個指令動作。

19. 業務建模應該遵守客觀規律。

20. DDD強調“充血模型”。在複雜業務中,這很有用,可以提高對象的可複用性。但是要注意,“充血模型”雖然很好,但其背後卻隱藏玄機。複雜場景中,如果所有的行爲都放到了對象中,那領域對象就會變得沉重無比,帶來各種副作用。同時,描述狀態的值對象往往不是一蹴而就,而是充滿着變化,難以把握。當業務不明時,"貧血模型"容易把握,這也就是爲什麼現在”充血模型“不多,而"貧血模型"大行其道的原因。

21. DDD認爲"領域對象應該是有行爲的",大家都認可。如果說"貧血模型"造成了對象和行爲的分離的話;那麼"充血模型"也是有問題的,因爲DDD中簡單地認爲把行爲放到對象中就行了,殊不知這其實是關於對象和行爲之間的一種靜態地僵化的看法。而DCI對這種思想進行了修正,認爲對象在場景中才具有行爲。對於DCI中的對象(數據),我認爲DCI中的對象(數據)是一種裸對象,但卻不是簡單意義上的"貧血對象"。DCI中的對象和行爲是一種動態關係,是依賴於場景而存在的。這也就是說對象不會無緣無故的產生行爲,(呵呵,那是神經病),對象具有行爲一定是有意義的。也許有人擔心場景會變成"貧血對象"模式下service那樣的噩夢,造成對象和行爲的分離。其實不用擔心,在DCI中可以用"事件"把對象和行爲聯繫在一起就避免了"貧血對象"的問題。呵呵,這是不是應了中國的一句老話:"分久必合,合久必分"。

22. 對於DDD中的聚合,我也有不同的理解。其實DDD提出聚合的概念是爲了保證領域內對象之間的一致性問題。但是我對DDD中對"聚合"這個概念的落地形式表示質疑,DDD特別強調聚合根的封裝性,然而這可能會導致領域內對象之間的邏輯強耦合。也許有人說領域內部的對象是高內聚的,這樣做沒關係。但是在實戰中,領域模型內部的值對象往往存在着變數,這是我們認識客觀世界的必然規律。然而這會導致領域模型的不穩定性。所以我認爲及時領域內部的對象也應該注意低耦合,這個問題同樣需要靠事件來解決,事件纔是保證領域對象一致性的關鍵。

23. “一致性”究竟是什麼呢,我認爲“一致性”是事物相互作用的本質內在聯繫,也就是在一定場景下外界刺激在沿着一定路徑傳遞而導致一系列對象的變化。所以“外界不可以繞過根實體直接修改狀態”並不能反應這一本質,因爲外界刺激並不全都是先作用在根對象上面的。在我看來,這種非本質的封裝反而會造成耦合,尤其是採用“直接調用”的形式。應該說,“直接調用”是造成對象耦合最大根源,因爲“直接調用”是在強調對象的上下級關係,這很生硬。如果我們換一種方式,用一種平等的心態去看待對象間作用關係,用“告訴我做什麼”的方式而讓對象間解耦。

24. 在思考語言範式時,我曾這樣想過,面向對象,行爲與屬性綁得太緊,面向過程,行爲與屬性放得的太鬆。但這裏不是僅僅選擇“分”或“合”那麼簡單,“貧血模型”與“充血模型”實際上與“面向過程”與“面向類(對象)”的矛盾是相似的。

“貧血對象”是將“行爲”與“屬性”完全放開的一種表達,而“充血對象”則又矯枉過正,把“行爲與屬性”綁得太緊。

類是表達共性的概念,而對象則是充滿個性,而且這些個性是依賴場景的,離開場景將失去意義。所以,在“充血模型”中,用類表達對象時,實際是將“個性”統統視爲“共性”,在任何具體的場景中,對象的角色或職責都已經定義好了,這顯然是不合適,因爲一個對象可以多種角色參與不同的活動或場景(可能使得類繼承體系非常龐大和複雜),而且在參與新的活動或者場景時,以“類”及“繼承”的方式定義對象則更是力不從心。

而在“貧血模型”中,則將“共性”統統視爲“個性”,這是抹掉“共性”的做法,與“充血模型”抹掉“個性”的做法剛好相反。前者是“白馬非馬”,後者則是“白馬即馬”。都沒有協調好“共性”與“個性”的關係。

因此真正自然的“領域模型”應該是這樣的,如果對象的某些行爲在任何場景都是通用的,那麼就放在領域中去,將其綁定,這是尊重“共性”的約束;如果對象的某些依賴於具體的場景,那麼則在具體的場景中注入相應的行爲,賦予對象相應的角色,這是尊重“個性”的自由。所以,對象的行爲該不該放入“領域模型”,我們要先分析一下這些行爲是對象所固有的,還是依賴於場景的,如果是固有的,即是共性的,就放入領域模型(domain),如果不是則延遲在具體的場景(service)中注入,賦予其角色的個性(DCI)。

25. 設計模式可以在領域模型中使用(domain),也可以在具體業務場景(service)中使用。設計模式是在局部、微觀層面的一種支持變化的機制,在具體業務場景中使用再合適不過了。將來可能會出現的現象是,在領域層(domain)各個模型中用的更多是“結構型”模式,而在業務層或服務層(service)的各個場景中用得更多的是“行爲型”模式,兩者都可以使用“創建型”模式。

26. 不要把業務和領域等同,業務是客觀存在,領域是主觀認識。

27. 領域和場景是不同的。領域是宏觀層面的,場景是微觀層面的,雖然它們有相似點。
如果可以用一個領域模型來描述“企業”的所有業務,我當然希望是這樣的,但問題是有誰可以做到,那就是共產主義了,完全可以憑此打敗微軟、IBM之類的公司成爲老大了。領域“有界無邊”,說起來拗口,簡單說領域雖然有界,但其邊界時可以擴展的,領域雖然有界,但其邊界是無形的。比如說音樂界不斷髮展,但界還是存在,雖然界也是一種主觀認識的劃分。因爲音樂界不能獨立於人類的所有活動。

28. 領域的邊界是由用戶的需求來決定的,用戶的需求是動態可擴展,所以領域的邊界也如此。所謂領域語言,就是從有所需的用戶心中提煉出來的。用戶需求相對於領域來說是一個“客觀存在”。

29. 領域雖然是對客觀存在主觀上一種劃分,但不是一成不變的。一個領域模型是根據業務(用戶需求)對領域的一種素描,業務不同,素描也就不同。

30. 我們應該學會逆向思考:
1.服務是什麼?自己在過去的項目中用過服務嗎?如果不用,會怎麼樣?如果用了,用好了嗎,出現了DDD指出的問題嗎?
2.聚合是什麼?爲什麼要用聚合?自己用過聚合嗎?DDD的聚合採取的形式是什麼?除了DDD中的聚合,還有別的聚合嗎?
DDD其他的要素可以以此類推。其實DDD不太適合初學者和小項目,DDD是經歷過很多項目的失敗和成功才總結出來的。所以我是反對把DDD當成一種理論學習的,在實戰中不懂得東西不要亂用,但是一定要感悟,也就是說你可以先不去用DDD,但可以在實踐中感悟DDD的思想和要素,然後明悟真僞。所以我發了這麼多帖子,希望大家從自己的實戰去印證,共鳴。這裏不是沒事無聊的閒談,而是基於實踐的關於DDD的靈魂的交流。

31. DDD是對一些複雜IT項目成功要素的總結而形成的一種理論。正確地理解DDD是關鍵,只要成功運用DDD的思想和要素就可以了,絕不是照搬。就算沒見過DDD,也可能在實踐中運用過DDD的思想和要素。

32. 領域建模與設計模式的思想不是隻有高手才能領悟,就像數學與哲學思想不是隻由數學家和哲學家才能領悟。思想與知識是兩個相關又不同的範疇,建模思想與技術知識/經驗同樣如此。不要因爲新手知識的不足,而認爲新手就不能領悟思想。如果出現這種情況,我只有兩種理解:a)這個老手不懂;b)這個老手懂,但不想告訴你,可能出於自私,也可能覺得你還不適合。

33. 不同於設計模式的關注點在如何設計模型以支持需求的變化,分析模式的關注點如何將需求轉化爲模型。Martin Fowler的《分析模式--可複用的對象模型》、Peter Coad的《對象模型--策略、模式、應用》等等關於分析模式的著作,都尚未拜讀,加上經驗實在匱乏,所以本不想說。可是對於Peter Coad的《Java Modeling in Color with UML》一書中的四色模型,一見如故,極其簡單的四色模型,在我心裏已經將其作爲自己關於分析模式的核心認知,這裏說說自己對四色原型的理解(再次感謝Jdon讓我遇見了四色模型)。

四色模型中有四個最核心的概念(剛好設計模式也是運用了OO的四個基本概念,無巧不成書呀),分別是MI(Moment Interval)、Role、PPT(Party Place Thing)、Desc(Description), 不同設計模式運用的OO的Abstraction、Encapsulation、Inheritance、Polymorphism四個基本概念在中文有很好的翻譯:抽象、封裝、繼承、多態。這四個詞,直譯起來,似乎沒什麼感覺:瞬間-間隔時間、角色、聚會場所-物件、描述。查閱一些資料,其描述我不是十分滿意,這裏我嘗試用簡短的言語解釋其本質:MI描述活動,Role代表參與活動的事物;PPT代表未參與活動的事物,Desc描述事物。舉個例子,比如一件商品,商品本身就是PPT,商品的類別信息、廠家等商品的元信息就是Desc,如果這件商品爲顧客所購買,此件商品就變成了Role(當然顧客此時也是Role),而顧客購買商品這個活動就是MI。

世界可以簡單理解爲由事物及其運動(MI)構成,事物又有動靜之分,動即參與活動之事物(Role),靜即未參與活動之事物(PPT),此外,可能還需要描述事物的信息(Desc)。爲了將原型形象化,我們可以根據色彩的冷暖動靜之感,將活動(MI)塗上活躍的紅色,將參與活動的事物(Role)塗以暖色黃色,將未參於活動的事物(PPT)塗以安靜的綠色,將描述事物的信息(Desc)塗以冷色藍色。這樣四色原型就誕生了,通過四色原型,我們可以像孩子拼接積木一樣,一塊一塊地拼接出需求模型的原型了。

34. 分析模式將需求轉化爲原型,設計模式支持需求模型的變化,而實現模式爲何而生?實現模式關注的是代碼本身,我們在分析和設計上付出的努力,終究要落實在代碼上。分析和設計再好的模型,也可能被充滿smell的代碼掩蓋或破壞。Kent Beck在《實現模式》一書提出了77個實現模式,6條原則和3種價值觀。77個實現模式涉及一些具體的代碼規範的建議,暫且不論;6條原則,局部化影響、最小化重複、將邏輯與數據捆綁、對稱性、聲明式表達和變化率,也暫且不議;3種價值觀:溝通、簡單、靈活,我也只想說說其中的一點:溝通,因爲個人認爲這是實現模式最根本的意義所在。Kent Beck在書中說:過了20年,把別人當作空氣一樣的編程方式纔在我眼中褪盡了顏色。作爲一位programmer,代碼的作用不僅在於與機器交流,更重要的是與別的programmer交流,將“溝通”的價值觀貫徹到代碼的編寫中,是值得每個programmer堅持去做的事情。上面所說的三本很薄的書,可以作爲關於分析、設計、實現模式的認知基礎,值得收藏。

發佈了26 篇原創文章 · 獲贊 1 · 訪問量 1222
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章