大家好,我是Eluxjs的作者,Eluxjs是一套基于“微模塊”和“模型驅動”的跨平臺、跨框架『同構方案』,歡迎了解...
文前宣告,以下推斷和結論純屬個人探索,鑒于本人知識水平所限,謬誤在所難免,懇請各位大佬不吝賜教...
為什么在web前端很少有人會提到分層架構,例如經典MVC架構,這是因為瀏覽器誕生之初就只是作為一個后端資料的GUI渲染器,也就是說整體來看,web1.0時代的整個web前端工程就是一個View層,而Model和Controller就是指后端,所以根本無需在web前端工程中去提什么MVC,
然而web生態發展到今天,瀏覽器越來越強大,賦能越來越多,甚至不亞于一個小型作業系統,這時候的Web前端早已不是當初簡單的資料渲染器,隨著PWA、小程式、快應用的推廣,WebAPP已經和傳統的“富客戶端”沒什么兩樣了,那么在這種趨勢下,如果我們的Web前端架構還停留在View的時代,那么顯然是落伍的,
View是最直觀的、最原始的驅動源,解決了所有View的問題也就實作了WebApp的所有功能,前端開發人員的全部作業就是一個又一個的撰寫Component,正是因為這種以View為核心的架構思維,導致我們只為解決表層問題而架構,不去思考頂層設計,這也是很多Web前端工程經過幾輪迭代和人員轉手后,很難繼續維護下去的根本原因,
近年來涌現出一些優秀的UI渲染框架,比如React/Vue/Anglar,它們很強大,可以干很多分內和分外的事情,正因為如此,更造成了開發者的惰性,將所有邏輯都直接以最原始的方式寫在View中,不管是Mode還是Controller,不管是業務邏輯、還是渲染邏輯、還是存盤邏輯、還是通訊邏輯、還是路由邏輯...所有各類邏輯疊加各種UI生命周期,全部都耦合在一個Component中,
從視圖驅動到領域驅動
是時候改變我們的架構思維,從視圖驅動升華到領域驅動,雖然視圖驅動是最直觀也是最簡單的一種架構模式,但是我們不僅要解決問題,還要思考如何優雅的解決問題,這也好比是排版和設計的區別吧!
或者說,在專案野蠻生長的混沌初期你可以從下往上構建,所建即所得,但到了某個重構的時間點,你還是得站在頂部進行上層設計,
當然,這里有個默認前提,那就是需要長期維護的中大型專案,小而快的專案無需談各種架構模式...
將UI框架拉下神壇
UI不是工程的全部,UI的指責只有2個:輸入與輸出,僅此而已,所以即便React/Vue再強大,你也應當僅把它們當成一個GUI工具,類似于Java Swing和.Net WPF,而非整個工程React/Vue一把梭,
~~ 敲黑板:UI只是指令的收集者、傳達者、反饋者,而不應當成為指令的執行者, ~~
應用的核心是業務邏輯
現在問你一個問題:
如果沒有UI,你的應用可以通過命令來驅動嗎?
你可能會懟我說,用戶怎么可能會通過命令來使用我的應用,沒有這樣的業務場景,你這個假設是毫無意義的,然而,這種場景或許并不是為用戶而設,而是為合作伙伴而設、為測驗工具而設、為日志分析而設、為今后的擴展和生態建設而設...
再問你一個問題:
- UI說:應用要改版,皮膚、互動、頁面組織都要調整,要多久?
- 產品說:把H5改改,做成小程式、APP吧,要多久?
- 經理說:React人太難招了,要不我們換成Vue吧,要多久?
- Leader說:Vue3出來了,我們升級為最新版吧,要多久?
- 架構師說:Svelte快到飛,我們重構為Svelte吧,要多久?
業務邏輯不變,僅調整UI和其運行平臺,問你要多久?這個時候,如果你的全部邏輯都是耦合在某種特定的UI框架中的,那你只能是哀默之心大于死...
UI邏輯與業務邏輯分離
從早期的前后端一體化,到后面的前后端邏輯分離,在到這里我重提UI邏輯與業務邏輯分離,都只是順著2件事件在做:讓需要內聚的更內聚,讓可以解耦的更松散,
-
業務邏輯抽象,UI邏輯具體:業務邏輯是抽象的資料模型,而UI邏輯則是抽象事物逐層泛化后的具體表現,它們兩個本身就不再同一個Level上,
-
業務邏輯通用,UI邏輯特殊:UI邏輯通常需要借助于某個具體的UI框架而表達,而UI框架通常都會與運行平臺息息相關,同時也會加入自己的各種各種限制、約束、約定、魔術方法等,所以形象來說,前者是JS國度的普通話,而后者則是方言,
-
業務邏輯直觀,UI邏輯隱晦:UI渲染本身就是一件很復雜的事情,其間涉及到各種組件的各種生命周期、創建、銷毀、更新、重繪等等、在加上各種優化手段造成的心智負擔,所以你會發現某些業務邏輯放在
Redux或是Vuex等純狀態管理框架中,比使用組件內部的Hooks去維護更簡單和直觀,盡管Hooks也可以模擬這些Flux框架,但是不及前者有條理,比如測驗、監控、分析、回滾一個Action多容易,你測驗、監控、分析、回滾一個Hooks試試... -
業務邏輯穩定、UI邏輯多變:UI/UE太感性、太靈活了,帶有很強的個人主觀色彩,經常會被優化、修改、甚至推翻,不像業務邏輯那么穩定,這也是要將UI邏輯和業務邏輯分開的重要原因,如果你將業務邏輯和UI邏輯寫在一起,你本來穩定的代碼將受到不穩定代碼的嚴重騷撓,
鐵打的MV流水的C
現在提MVC是不是過時了?非也,MVC是其實一種最簡單的哲學思想,Model代表抽象事物,View代表具體事物,而Controller則是代表如何在抽象事物和具體事物之間泛化,所以MVC是一種思想,而不是特指某種框架,過時的只會是框架,而非思想,
近年來各種演化如:MVP、MVVM、MVI等等,其實都是在圍繞C做文章,最終的目的無非就是更好的隔離M和V,也就是千方百計分離UI邏輯和業務邏輯,
Flux架構其實也是一種MVC,而Redux/Vuex/Pinia、以及本人的框架Elux,都可以看作它的變種,下面我們就看看如何利用Flux架構來分離UI邏輯與業務邏輯:
從State到Model
MVVM應用中充斥著狀態,有的用來描述Component的內部狀況,它與Component唇齒相依,跟隨Component誕生和銷毀,這就是我們常說的ComponentState,
還有一些狀態,用來描述業務狀態,與具體哪個Component沒有直接關系,不存在復用與銷毀,我們可以稱它為Model,
- ComponentState 是UI邏輯,應當封裝在Component里面,外界也無需知道,
- Model 是業務邏輯,反映整個APP的狀況,與Component無關,應當由Flux框架來統一管理,
從Event到Action
用戶通過UI界面產生的人機互動事件,我們習慣叫"Event事件",而"Event事件"背后的業務目的我們可以叫"Action動作",它們一個是因一個是果,一個是表一個本,
- 處理 Event 的 Handler 是UI邏輯,應當寫在UI組件中
- 處理 Action 的 Handler 是業務邏輯,應當寫在Controller里面
舉個具體的例子吧:"SubmitLoginForm|提交登錄表單",通常要完成如下邏輯:
- 驗證輸入是否有效
- 驗證當前用戶是否已經登錄
- 請求后端API,并等待回傳
- 如果成功,保存用戶資訊,并跳回原頁面
- 如果失敗,提示錯誤,并留在原地
這是一個業務動作,因為它可以不依賴哪個具體UI而運行,用戶可能通過“onClick事件”點擊登錄按鈕來觸發,也可能通過“onKeyPress”按下回車鍵來觸發,甚至你可以直接讓用戶通過“Login命令”來觸發,
所以“onSubmitLoginForm()”應當寫在Controller而非UI組件中,
UI組件中只有"onLoginButtonClick()"或"onEnterKeyPress()",而它們往往也就一句話,就是Dispatch一個Action來觸發Controller中的“onSubmitLoginForm()”
將業務邏輯移出UI組件,這樣UI層就變薄了,回歸到了它的本質:只負責收集業務動作,不負責處理它,
改良Flux框架
傳統的Flux框架也有痛點:
- 全域中心化管理導致邏輯過于集中;
- 單實體、不銷毀容易造成資訊累積爆炸;
- DispatchAction機制過于簡單,不適合處理前因后果的長流程業務,
Elux正是針對以上痛點進行了改良:
- 雖然堅持全域中心化管理,但Elux提出“微模塊”的概念,將應用拆分成獨立自治的一個個“微模塊”,每個微模塊僅處理自己領域內的事情,
- 不再單實體,每次路由變化都會產生一個新的空白Store,然后重新挑選有用的狀態掛載,類似一種垃圾回識訓制,
- 提出了ActionBus的概念,讓Action作為Model中的事件來廣播,
- 讓Action的處理鏈條具備“協程”機制,更好的協同各業務動作之間的關聯,
Elux踐行的分層而治
正是因為遵循了輕UI、重Model的設計思想,讓Elux可以掛接React/Vue等各種不同的UI框架,它們已經變得沒那么重要了,
正式因為分離了UI邏輯和業務邏輯,讓Elux可以用一種工程模式開發Web(瀏覽器)、Micro(微前端)、SSR(服務器渲染)、MP(小程式)、APP(手機應用),
此致!歡迎交流:https://eluxjs.com
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/502662.html
標籤:其他
