有挺長時間沒有更新博客了。一來是公司比較忙,二是本身也在思考一些新的問題。最近一個月,在我腦海回想最多的一個詞語是「插件化架構」。做此文,也是想簡單分享一下我對這個問題的看法。前端
去年有參與過 Udacity 前端課程翻譯。其中我翻譯了構建工具部分。Webpack 做爲當前主流構建工具,深入影響着前端開發工做流的變革,正如課程中所說,Webpack 聚合當前前端構建工具全部最熱門的構建技術,甚至能夠說,它能夠做任何構建工具能做的事。那麼 Webpack 爲何這麼全能,是由於 Webpack 自身這麼能幹,精通十八般武藝?No !事實上 Webpack 比想象的要「無能」,它的全能是由於它能容萬物只所能。由於 Webpack 自己是一個高度插件化設計的系統,它所表現的能力都藉助於真正身懷絕技的插件的賦能。固然,我這裏所說的插件包含了 Webpack 的內置插件以及經過配置傳入的plugins
。能夠說,Webpack 只抽象了一個軟件運行時環境,在不關心和改動這個系統已有代碼的前提下,卻能獨立開發新的插件來充實整個系統的能力。這不就是軟件設計中所要追求的開閉原則的最佳實踐嗎?從 Webpack 的插件化架構設計上所表現出系統良好的開放性,可持續的簡潔性,我天然想象到,爲什麼不在業務系統中採用這樣的插件化架構。webpack
插件的英文是plugin
,拆分開是plug(插頭) + in
,現實生活生活中,電源插線板就是這樣"plugin"應用的例子。插線板和經過插頭插入其中的電器構成一個物理世界的插件化系統。插線板經過插孔爲「插件」提供電源,而給系統賦予了插件的能力。插入電視的插頭,就擁有看電視的功能,插入冰箱的插頭就具備冷藏食物的功能,插入檯燈的插頭,就具有照明的功能,等等。git
一個良好設計的插件化系統和插線板的設計也是同樣同樣的。系統的核心應該是一個可熱插拔的「插線板」,負責給系統接入的插件提供電源(插件API),系統的能力是全部插件能力的聚合。和物理世界的插線板不一樣是,軟件插線板的插頭沒有數量的限制,也就是說系統能夠接入任意數量的插件,意味着它的功能能夠無限增長。github
若是類比插線板的方式設計一個徹底插件化的系統,系統將包含三個部分:web
其中 pluggableCore
與 pluginApi
是插件化系統的核心部分,或者內部系統,一旦設計好了,不會輕易改變的;而plugin
是外部系統,經過pluginApi
訪問系統內核和全局狀態,實現對應用全生命週期的訪問和控制,只須要遵循接口的定義,plugin
能夠將自身能力賦予給任何插件化系統,而不是與某一個特定的系統耦合在一塊兒。 事實上,plugin
也分爲兩個部分。咱們依然能夠與現實世界的電器,例如上文的電視機對比,它包含用於接入電源的插頭和用於播放電視節目物理實現,咱們能夠看到,雖然電視機是經過電源線才成爲整個系統中的插件一員,但它的物理實現遠比電源線複雜的多,甚至能夠獨立出來一個複雜的系統。一樣,插件化系統中,插件的功能實現也多是一個可獨立出來複雜系統,而只是經過一個簡單的插件註冊或應用接口接入另外一個插件的系統。設計模式
以 webpack 的插件爲例。如下是 webpack 插件的模版:markdown
import VeryComplicatedSystem from "VeryComplicatedSystem"; class AwesomeWebpackPlugin { apply(compiler) { VeryComplicatedSystem.apply(compiler); } } 複製代碼
咱們看到插件的電源線就是包含apply
方法的類,只須要5
行代碼。而插件的功能實現能夠是一個獨立的複雜系統,它還能夠是多個插件的聚合。固然從設計上,插件的功能單一更有利於複用。這裏所要表達的是咱們應該把插件看做一個能夠脫離插件系統自己存在的功能完整軟件系統,讓這個系統成爲插件而爲另外一個插件化系統賦能並不須要重寫內部實現,而只是加上一根符合插件標準的電源線而已。這樣理解,有助於咱們設計出更容易複用的插件,同時也能夠複用已有軟件的系統。架構
正如前文所說,插件化架構一個顯而易見的優點就是它是開閉原則在跨系統級別的最佳實踐。何爲跨系統,若是說設計模式是設計單個系統的最佳實踐,那麼咱們已經論證,插件化架構能夠連接多個子系統,而作到開閉原則。即插件核心和接口不變,系統能夠持續接入新插件,來豐富系統的功能。而且,因爲新接入的插件是一個獨立的子系統,它可獨立開發,運行和進行版本管理,不會由於接入的系統複雜而增長接入成本。試想,在一個非插件化的系統中,業務系統就算通過良好設計,隨着功能模塊的增多,代碼量激增,暫且不考慮系統構建和測試,咱們想要給系統加入新的功能,甚至是修復已有功能的BUG,都會愈來愈困難和低效,但插件化架構的系統,增長新功能,不是在一個龐大系統代碼庫中,而是在一個較小的系統或代碼倉庫中,所以無論已有系統多複雜,開發新的功能的接入複雜度始終同樣。同時,開發編譯或修復測試一個插件,也比針對整個系統要簡單得多。app
插件本質也是一種軟件複用方式,和咱們常說的組件區別是複用的維度不一樣。組件的複用顆粒度更細,它是技術級複用單元,須要通過進一步加工和組合才能成爲解決某一類業務問題的完整部分,而插件是一個更加完整能夠解決某一類業務問題的子系統,是業務級別的複用單元。框架
這裏很差說它必定是將來。暫且認爲是我設想的將來發展的一種可能。即經過創建一個插件標準,實現業務系統的全面插件化,全部以開發和正在的開發的系統都不是耦合在一個特定的系統,而很難獨立出來,在不一樣系統複用。全面的插件化,意味着,咱們不用重複造業務輪子,團隊和企業能夠持續積累本身的插件生態,讓軟件開能夠像汽車等工業製造同樣,打造一條標準化裝配的流水線。
本文的觀點僅是我的思考,還沒有通過權威的論證。其中的設想有過初期實踐,但還沒有造成一個完整的能夠推廣的技術框架,這部分筆者本人還在探索中,就不貼出來,感興趣的讀者能夠關注個人 github。