解讀「框架設計原則」

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 關於介面分離和模組分包,通常在後期重構能夠達到更好的效果?
好了,洋洋灑灑說了不少,讀者如有更好的見解,請與我分享,畢竟現在關注這塊的人不多了。:)期待和對此感興趣的人一起討論
原文釋出時間為: 2018-11-17
本文作者: Kirito的技術分享
本文來自雲棲社群合作伙伴“ ofollow,noindex" target="_blank">Kirito的技術分享 ”,瞭解相關資訊可以關注“ Kirito的技術分享 ”。