在遠古的時候,人們對世界的認知有限,以為天圓地方,世界是平的。後來,隨著科技進步,大家都知道了地球的形狀,它不但不平,還有山川河流,沙漠海洋。
這很大程度上說明了人所處的環境對認知帶來的影響,我們看待一件事物,從不同的視角去看,所得到的結論未必是相同的。
前後端協作的研發模式
上個月有一天很奇妙,早上有個之前部門的同事跟我探討研發模式,下午有個之前同事跟我吐槽前後端溝通成本高,晚上部門群裡又有人提到檢視跟服務的關係,這麼多巧合,值得在這個事情上寫點東西。
回頭看看這幾年,前端領域在搞的一些東西,除去具體的框架和元件庫,大致有這麼些:
- 工程體系:構建、釋出、持續整合、容器管理
- NodeJS實現的框架、中介軟體、服務
- 圍繞前後端協作展開的一系列探索:BaaS、BFF、函式計算、GraphQL等
- 跨端實踐
這裡面,有很大一部分話題是跟廣義的“前後端分離”有關的。站在今天這個時間回頭看,看得到每個方向的進展,人們逐步習慣了前端有型別、有構建、有包管理、有測試、有持續整合等等,前端開發逐步成為了相對嚴謹的軟體生產活動。
另外一方面,當我們把目光投向整個系統的時候,我們也可能發現研發流程的一些狀況。現在,一個典型的系統,它的開發過程可能是這樣的:
- 前端獨立系統
- 後端獨立系統
- 中間有類似 swagger 的介面約定機制
前端有一套東西,完整的元件化、構建、釋出、依賴管理,後端也有一套,但是,兩者的結合往往是很鬆散的,整個鏈路很長,在流程上會有很不協調的感覺。
形成這個問題的原因是整個研發過程兩極分化,斷裂得很厲害,前後端的唯一橋樑是介面,並且,一般來說,當一端產生了變更之後,很難有一種自動同步機制去影響另一端,通常只能去掃描發現這些不一致的地方,並且手工做調整。
整個系統的研發流程好比細胞的增殖過程,拉伸成了兩塊,中間的維繫很脆弱。
從架構治理角度看,“兩頭大”的情況是需要去控制的,只有主從結構的形態,在流程上才是簡單的。對這麼一個問題,業界存在不同的探索途徑:
- 前端主導的流程
- 前後端合一的研發模式
- 後端主導的流程
前端主導的流程
前端主導的流程是怎樣的呢?
這個流程的要點是讓後端退化為配置,藉助 BaaS,FaaS 這樣的基礎架構,捨棄後端的構建與釋出環節,工程上就會成為這樣的形態:
這樣,後端成為了一種流程無感的環節,前端是整個專案的整合方,後端成為了一種配置化的東西,成為了前端體系下的附屬。這種模式是否能行得通,最大的先決條件就是後端介面是否穩定。在網際網路企業中,尤其是領域模型關聯關係較少的情況下,有不少系統在往這個方向走。
- 輕量業務:完全 BaaS
- 較重的業務:通過 Faas 呼叫微服務
前後端融合的模式
另外,業界也存在一些探索,希望把前後端的開發過程融合。我們所要解決的問題一直都是變更的同步,那麼,如果一個專案的前後端都位於一個工程中,天然對同步也是有利的。
這種模式下,實際上是通過兩者合一的方式,縮短了前後端研發過程之間的距離和溝通成本,在此基礎上,還可以有另外一些手段作優化,比如:
- 根據後端的服務生成前端的呼叫介面,並且附帶 TypeScript 型別描述
- 根據後端的單元測試生成前端的 mock 資料
前後端合一的工程中,最大優勢就是後端介面的變更一定會自動傳導到前端,服務介面欄位變更會導致:
- 前端型別校驗出錯
- 前端的單元測試出錯
並且,由於二者合併在一個專案中,改了一邊忘記改另一邊的情況也更不容易發生,兩者的釋出也是在同一個流程中。
這種模式普適性相對好,但是對人員全棧技能的需求是要稍高的。
後端主導的流程
後端主導的流程又是怎樣的呢?
這個流程是反過來,儘可能地把檢視弱化,讓它成為後端模型的附屬物。在很長的時間裡,這種形態一直是主流,只是可能具體形式上歷經了一些演變。
後端主導的流程推行到極致,工程上就會成為這樣的形態:
在這種路徑下,檢視成為了領域模型的附屬物,當領域模型產生變動的時候,檢視自然跟著變動,即使是檢視之間的聯動關係,也是經由領域模型之間的關係控制的。
這樣,前端成為了一種流程無感的環節,後端是整個專案的整合方,前端成為了一種配置化的東西。這條路徑的先決條件是前端的模式相對固定,可窮舉,不會存在太多的個性化互動。通常,會有一些企業軟體的研發過程採用這種模式。這種模式對人的需求是領域建模能力較強。
元件化
研發流程也會導致實施過程中的一些細節差異,比較典型的就是元件化。
元件化是一個很久遠的名詞了,自從工業革命開始,標準化的可替換部件逐步成為了生產效率的基石。在前端領域,這個詞最近也在越來越多地被提到。然而,對這個詞如何理解,不同的人有不同看法。
元件化的實施路徑是需要隨著技術方案的不同而調整的。剛才我們提到了三種研發模式,元件化實施方案也會有不同的模式。
- 前端不分層的元件化體系
- 前端分層的元件化體系
- 端到端元件化體系
前端不分層的元件化體系
這個體系是當前前端最熟悉的路徑了,在實現者眼裡,後端退化為介面,不關心資料之間的關係。
前端分層的元件化體系
另外存在一種實踐,在前端又引入分層,把真正的檢視和邏輯、資料等等隔離,這個時候,檢視部分實際上就可以變得非常薄,整個檢視部分的元件化,實際上類似於模板化。
端到端的元件化體系
如果考慮到實施的原則儘量簡單,端到端元件是最容易理解,整合難度最低的一種形態。
在此模式下,單個元件應當包含檢視到服務端模型的整個鏈路。元件只跟某個具體的領域模型互動,並不關心其他元件的存在。單個或者多個元件,都能夠直接執行。頁面成為一種通用的容器,把它們整合起來。
舉例來說,一個人員列表與詳情的頁面,如果實現為兩個元件,其功能分別如下:
- 列表元件
- 繫結了某個條件的人員列表查詢服務
- 詳情元件
- 繫結了某個具體的人員
這兩個元件應當是互相獨立的,在這種情況下頁面對它們的整合,包括兩者之間的聯動關係,都是在領域模型(後端)上定義的,然後藉助特定的機制,自動就形成了聯動關係。
從實現角度,這種元件內部也可能接近於其他形態的元件實現方式,比如,元件內部可以有分層,當某元件被註冊的時候,它所屬的各層是分別註冊的。
需要注意的是,以上三種實踐並非直接對應於第一部分我們提到的三種模式,它們是存在並存關係的,可以根據業務場景去適當進行混合。
小結
不考慮實際情況的技術選型是非常可怕的,並不存在通吃一切的技術方案,每種方案都有它的邊界。在實踐過程中,可以問問自己,我們正在做的這個系統:
- 前端跟後端,哪塊更模式化?
- 與其他系統的整合方式是怎樣的?
- 檢視變更與複用程度如何?
- 人員的技能狀況如何?
- 檢視是“寫”出來的,還是“配置”出來的?
對這些問題的不同回答,都會影響到具體實施路徑的選擇。
幾年前,左耳朵耗子說了一句話,被很多人圍攻:“CSS不就是配置檔案麼?”從前端角度看,這句話簡直大逆不道。但是,在某些場景下,當我們把視野放在全域性,到整個系統層面,CSS確實就可以被認為是一種配置檔案。不但如此,在有些場景下,連檢視的大部分都能算是配置檔案了。
有的時候,我們也會看到一些探索,比如說,嘗試用視覺化的方式去配置檢視層,在這種情況下,檢視確實就是由:
- “寫”出來的基礎元件
- “拼”出來的大塊模板
這兩類部分所組成的,這也是我個人在很多情況下很傾向於“模板型”檢視層框架的原因。
我們繞了很大一圈,離題萬里,那麼,世界是平的嗎?
可以試試閉著眼睛去摸一下立體的地球儀,感覺是怎樣的?但實際上這是一種錯覺,因為地球儀對比例進行了誇張,以青藏高原的海拔,相對地球半徑而言,其高度差簡直可以忽略不計。所以,巨集觀角度看,世界確實就是平的。
橫看成嶺側成峰,遠近高低各不同。不識廬山真面目,只緣身在此山中。
——蘇軾
後記:本文是2019年1月19日在網易前端技術大會上的分享。整篇文章想要解決的問題是給出一些建議:前端技術選型應當結合業務場景,社群方案只是自己的工具,技術人員不應當變成工具的奴隸。在不合適的場景下,即使是很著名、流行的工具,也應當果斷捨棄。
分享過程中,我提到自己給自己打的標籤是缺乏情懷的工業黨,所謂工業黨,在我看來,有另外一個名詞可以對等,那就是生產力至上。一個生產力至上者的態度是這樣的:竭盡全力尋找出限制生產力發展的因素,找到最適合的生產方式:
- 如果生產工具(技術框架)是瓶頸,那就改造生產工具;
- 如果研發流程是瓶頸,那就重塑研發流程;
- 如果人是瓶頸,那就改變人。
毛主席教導我們:“敢教日月換新天。”