解讀「框架設計原則」

大綱

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 來說,將是很大的壓力(使用對象池?性能不好。)

說說他的好處:

  1. 結構清晰,這個不必講吧。
  2. 充血模型......這個怎麼理解?
  3. 可變和不可變狀態分離,可變狀態集中。通常實體域都是隻讀的,即不變狀態。會話域都是可變狀態。
  4. 所有領域模型線程安全。無鎖編程(lock-free 非常重要)。

關於他們的線程安全性:

  1. 服務域無狀態,天生線程安全。
  2. 實體域屬性只讀,線程安全。
  3. 會話域工作在棧中,線程安全。

所以,需要保證他們是這麼設計的,才能實現無鎖編程。


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 暴露、引用、調用事件,都預留了監聽器。

關鍵路徑,即在管道使用職責連模式進行攔截,保證每個攔截器職責單一。

非關鍵路徑,需要有監聽機制,不能影響主流程運行。

關於協作防禦,我理解爲防禦性編程。

  1. 分離可靠操作和不可靠操作。不可靠操作儘量範圍要小。
  2. 狀態分離,儘量無狀態。狀態要儘可能小。
  3. 對狀態要儘早驗證,因爲如果失敗,通常無人回滾。前後斷言驗證狀態正確性。
  4. 異常防禦,應該是預見性的異常,異常包含環境信息。
  5. 降低修改成本,防止埋雷:不要根據異常類型做分支判斷。保持 null 和 empty 一致。

6 功能演進原則

第一就是開閉原則,微核心加插件機制能夠支持。 軟件質量的下降,來源於修改。

加功能的姿勢:應該是增量式,而不是擴充式,即不在原有基礎上修改,而是新增加功能。

關於高階:頂層接口儘量抽象,且不能依賴底層實現。這樣,當底層實現變化時,高層無需變化。

例如 Dubbo 泛化,在頂層就足夠抽象,底層實現方式不影響高層。


總結

以上是樑飛總結。

今天說的框架設計和現在大部分人喜歡說的架構設計有所不同,現在似乎只需要再 processon 上放幾個阿里雲組件,再連幾條線,就是架構設計了 :)

我個人認爲,框架設計更能考驗一個程序員對程序的抽象和管理能力(也許措辭不當?)

然後,再說說我的總結:關於一個系統的設計,這裏應該指的是框架的設計,首先要知道用戶需求(廢話)。根據需求抽象出模型,再變成代碼,且是可擴展,可複用的代碼。

這裏提到的 6 個原則,應該算是比較成熟的原則了。

1 微核 + 插件,非常理想化,例如 SOFA,也有自己的擴展機制。

2 關於領域模型設計,這 3 個模型的職責一定要劃分清楚,同時實現無鎖編程,這個對於系統的性能非常重要。

3 關於組件協作,一個系統有多個組件,通常需要進行狀態的共享,在 Dubbo 中,使用行爲進行傳遞,也就是會話域。

4 關於功能演進,請遵循開閉原則,但前提通常是有一個好的內核。

5 關於接口分離和模塊分包,通常在後期重構能夠達到更好的效果?

好了,洋洋灑灑說了不少,讀者如有更好的見解,請與我分享,畢竟現在關注這塊的人不多了。:)期待和對此感興趣的人一起討論

https://www.oschina.net/project/topcn2018?origin=homebanner 【開源中國開源項目投票】覺得dubbo的框架設計原則不錯的同學,可以考慮投票支持一下dubbo

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章