大綱
1 模塊分包原則 2 框架擴展原則 3 領域劃分原則 4 接口分離原則 5 組件協作原則 6 功能演進原則
原則總結者:樑飛,dubbo作者
原則解讀者:莫那魯道
1 模塊分包原則
說說我的理解。這裏其實是從框架結構的解讀來解讀,這裏的包指的是 Maven 的 module。
複用度,指的是 maven 包的複用。可以理解爲工具類。這個工具類不應該變化無常。
穩定度:被依賴的包應該保持穩定,或者說,被依賴者應當比依賴者穩定,且不能成環狀依賴。如果不穩定,將會影響其他的包。
抽象度,越抽象,越穩定。越具體,越容易變化。
同時,樑飛給出了一個公式,但是實踐起來有點麻煩.......
關於模塊分包,可以參見更詳細的博客。 以HTTL爲例講講模塊分包&領域模型&擴展框架
2 框架擴展原則
這是其實是說的比較多的東西了。
什麼是微核心 + 插件?按照作者的說法,核心只負責裝配插件。這樣,無論是作者自己的功能,還是第三方的功能,都是平等的,再多的插件也不會影響軟件架構,因爲沒有硬編碼,且都是可以卸載的。甚至微核也是可以擴展的。:)
同時,插件的組裝規則是統一的。說到這裏,你應該想到了 IDEA,Maven,Eclipse 等等。
然後說外置生命週期。這個其實我是有一點不理解的。按照作者的說法,其實是說,框架只負責管理對象,對象的出生和死亡不由框架負責。即,用戶應將實例註冊到框架中。
但 Spring 似乎不是這麼做的。同時,如果使用註冊機制,那麼就需要硬編碼。或者說,Spring 本身就是管理 Bean 生命週期的框架,而 Dubbo 的職責不在於此?
最少化概念模型,這個其實是一種優化。
一致化數據模型:例如 URL 這種對象,就是一致化數據模型,拒絕使用 String 拼接,解析。
3 領域劃分原則
這是在框架設計中,是非常重要的。
PPT 中已經說的非常清楚,我就不再說明。其中,Invocation 一定要輕量。否則,對 GC 來說,將是很大的壓力(使用對象池?性能不好。)
說說他的好處:
- 結構清晰,這個不必講吧。
- 充血模型......這個怎麼理解?
- 可變和不可變狀態分離,可變狀態集中。通常實體域都是隻讀的,即不變狀態。會話域都是可變狀態。
- 所有領域模型線程安全。無鎖編程(lock-free 非常重要)。
關於他們的線程安全性:
- 服務域無狀態,天生線程安全。
- 實體域屬性只讀,線程安全。
- 會話域工作在棧中,線程安全。
所以,需要保證他們是這麼設計的,才能實現無鎖編程。
4 接口分離原則
關於接口分離,我認爲是單一職責的一種實現。
其中提到 API 和 SPI,API 面向用戶,SPI 面向開發者。兩者必須分離。
聲明式 API 和過程式 SPI ,沒看懂,看懂的說一下。:)
API 可配置,一定可編程,這個不用說吧。
區分命令和查詢,例如,不應該有 updateAndGet 這個方法(不包括原子類),應該分成 2 個方法,保證 get 方法冪等。
對稱性接口:很簡單,有 get 方法,就應該有 set 方法,有 add 就由 remove,稱之爲對稱性和完備性。這樣用戶能自行推導出接口。
兼容性:如果接口加方法,應該是增加子接口的方式。其他的沒看明白.......
5 組件協作原則
這個就比較爽了,我們知道 Dubbo 是管道式設計。一個 Invoker 貫通整個流程,事實上,web 服務器都是這麼設計的。例如 Tomcat ,Netty。
關於派發,還記得 Spring 的 dispatchServlet 嗎?
關於狀態的共享:
- 分佈是什麼?即通過行爲傳遞(適合交互性系統)。
- 共享是什麼?通過一個固定的點獲取,稱之爲倉庫(適合管理狀態的系統)。
主過程攔截,還記得 Mybatis 留給我們的插件嗎?還記得 Spring 留給我們的攔截器嗎?框架要在關鍵節點留出攔截點供用戶擴展。
事件派發:觀察者模式,Reactor 模式,另外提到 Proactor 模式,查了一下,通常在 GNU 編程中,由 OS 支持。
Dubbo 暴露、引用、調用事件,都預留了監聽器。
關鍵路徑,即在管道使用職責連模式進行攔截,保證每個攔截器職責單一。
非關鍵路徑,需要有監聽機制,不能影響主流程運行。
關於協作防禦,我理解爲防禦性編程。
- 分離可靠操作和不可靠操作。不可靠操作儘量範圍要小。
- 狀態分離,儘量無狀態。狀態要儘可能小。
- 對狀態要儘早驗證,因爲如果失敗,通常無人回滾。前後斷言驗證狀態正確性。
- 異常防禦,應該是預見性的異常,異常包含環境信息。
- 降低修改成本,防止埋雷:不要根據異常類型做分支判斷。保持 null 和 empty 一致。
6 功能演進原則
第一就是開閉原則,微核心加插件機制能夠支持。 軟件質量的下降,來源於修改。
加功能的姿勢:應該是增量式,而不是擴充式,即不在原有基礎上修改,而是新增加功能。
關於高階:頂層接口儘量抽象,且不能依賴底層實現。這樣,當底層實現變化時,高層無需變化。
例如 Dubbo 泛化,在頂層就足夠抽象,底層實現方式不影響高層。
總結
以上是樑飛總結。
今天說的框架設計和現在大部分人喜歡說的架構設計有所不同,現在似乎只需要再 processon 上放幾個阿里雲組件,再連幾條線,就是架構設計了 :)
我個人認爲,框架設計更能考驗一個程序員對程序的抽象和管理能力(也許措辭不當?)
然後,再說說我的總結:關於一個系統的設計,這裏應該指的是框架的設計,首先要知道用戶需求(廢話)。根據需求抽象出模型,再變成代碼,且是可擴展,可複用的代碼。
這裏提到的 6 個原則,應該算是比較成熟的原則了。
1 微核 + 插件,非常理想化,例如 SOFA,也有自己的擴展機制。
2 關於領域模型設計,這 3 個模型的職責一定要劃分清楚,同時實現無鎖編程,這個對於系統的性能非常重要。
3 關於組件協作,一個系統有多個組件,通常需要進行狀態的共享,在 Dubbo 中,使用行爲進行傳遞,也就是會話域。
4 關於功能演進,請遵循開閉原則,但前提通常是有一個好的內核。
5 關於接口分離和模塊分包,通常在後期重構能夠達到更好的效果?
好了,洋洋灑灑說了不少,讀者如有更好的見解,請與我分享,畢竟現在關注這塊的人不多了。:)期待和對此感興趣的人一起討論
https://www.oschina.net/project/topcn2018?origin=homebanner 【開源中國開源項目投票】覺得dubbo的框架設計原則不錯的同學,可以考慮投票支持一下dubbo