如何構(gòu)建一個(gè)完整的To B應(yīng)用開發(fā)平臺(tái)?(to b運(yùn)營(yíng)怎么做)
作者丨榮多君
1、前言
互聯(lián)網(wǎng)時(shí)代演進(jìn)到現(xiàn)在,在 5G 和 IOT 的影響下,整個(gè)人類社會(huì)實(shí)現(xiàn)全產(chǎn)業(yè)數(shù)字互聯(lián)的愿景變得逐漸清晰,某個(gè)行業(yè)通過行業(yè)標(biāo)準(zhǔn)的制定,采用同一套標(biāo)準(zhǔn),甚至同一套軟件,通過行業(yè)領(lǐng)域能力的復(fù)用,來快速構(gòu)建產(chǎn)業(yè)平臺(tái),并通過需求的更新與場(chǎng)景的優(yōu)化,來不斷積累行業(yè)的量變,最終形成質(zhì)變。而 B 端,正是實(shí)現(xiàn)產(chǎn)業(yè)數(shù)字互聯(lián)的重要組成部分,因此,以 AT 為代表的大廠都開始把目光指向了 B 端。
與傳統(tǒng)的 B 端軟件交付廠商不同,各互聯(lián)網(wǎng)大廠憑借雄厚的產(chǎn)品與技術(shù)實(shí)力,大都已完成 C 端的業(yè)務(wù)與技術(shù)基礎(chǔ)設(shè)施建設(shè),因?yàn)榧夹g(shù)具有通用性,因此,暨希望通過現(xiàn)有產(chǎn)品和技術(shù)進(jìn)行小規(guī)模的改造,來滿足 B 端(Saas 化或私有云)交付和部署,便成為各個(gè)廠商的普遍思路。
但要真正走向 B 端,做好賦能和服務(wù),還會(huì)面臨許多困難。
2、To B 的難點(diǎn)
簡(jiǎn)而言之,就是要解決“集成與被集成”的問題。
2.1. 集成與被集成
對(duì) to B 領(lǐng)域的認(rèn)識(shí)很容易陷入到無邊界的陷阱中,從技術(shù)和產(chǎn)品的角度去評(píng)估會(huì)認(rèn)為都可以做,實(shí)際上進(jìn)入更廣泛的領(lǐng)域之后,會(huì)發(fā)現(xiàn)各行各業(yè)大多都有自己獨(dú)特的知識(shí)體系和產(chǎn)品,一套體驗(yàn)、一套流程、一套配置很難包打天下。這時(shí),廠商就會(huì)考慮更新戰(zhàn)略,重塑業(yè)務(wù)邊界,通過引入 SI 與 ISV 來構(gòu)建產(chǎn)品生態(tài)。
引入 SI 與 ISV,除了是一種思想戰(zhàn)略的轉(zhuǎn)變,同時(shí)也是技術(shù)的變革,是從提供一個(gè)從頭到尾的完整解決方案,變?yōu)閯e人解決方案的一部分,成為 inside,實(shí)際上要求是更高了,包含了從產(chǎn)品的被集成,到技術(shù)的被集成,到生態(tài)的被集成。
2.2. 被集成的難點(diǎn)
本文主要談技術(shù)方面。
以近些年,互聯(lián)網(wǎng)企業(yè)在 To B 領(lǐng)域的實(shí)施情況來看,很多成功都是依靠投入很多精兵強(qiáng)將才做成的,說明互聯(lián)網(wǎng)企業(yè),其技術(shù)面對(duì)復(fù)雜場(chǎng)景,離標(biāo)準(zhǔn)化輸出、快速?gòu)?fù)用、方便二開還有一定的距離。To B 解決方案無論是在公有云還是專有云上,和自有技術(shù)產(chǎn)品實(shí)施相比,存在很多差異和問題:
- ISV、SI 和客戶自己的實(shí)現(xiàn)難以保證效果;
- 標(biāo)準(zhǔn)產(chǎn)品與定制開發(fā)要筑起柵欄,實(shí)施二開不能泄露核心代碼;
- 開發(fā)完成的前后端組件,需要結(jié)構(gòu)化沉淀成為可復(fù)用的二方庫(kù);
- 前后端組件往往無法直接復(fù)用,特別是業(yè)務(wù)級(jí)別組件;
- 產(chǎn)品化的程度、產(chǎn)品說明文檔的完善和易用;
- 開發(fā)一個(gè)產(chǎn)品的方法論、流程和平臺(tái);
To B 的產(chǎn)品能否成功,取決于生態(tài),生態(tài)取決于能否吸引到 ISV 和 SI,而吸引到 ISV 和 SI 的關(guān)鍵環(huán)節(jié),在于平臺(tái)能否滿足 ISV 和 SI 的需求。
落到更細(xì)節(jié)的技術(shù)方面,SI 與 ISV 需要什么?
靈活定制:前后端都提供靈活的二開機(jī)制,前端提供搭積木的自由組裝的能力;后端提供靈活的功能擴(kuò)展能力,能夠?qū)⒍ㄖ拼a與核心代碼完全分離;同時(shí)支持流程定制、元數(shù)據(jù)擴(kuò)展、服務(wù)編排。
快速交付:盡快產(chǎn)出原型(方便復(fù)用)、盡快交付產(chǎn)品(積木式、配置化地組合業(yè)務(wù),基于基線能力快速地?cái)U(kuò)展和定制能力)。
提高生產(chǎn)率:提供功能完整的應(yīng)用開發(fā)平臺(tái),并提供主流 IDE、Maven 插件來提升開發(fā)效率效率,基于 CICD 平臺(tái)來實(shí)現(xiàn)打包部署自動(dòng)化。To B 端常見的表單和列表的 CRUD,能夠直接根據(jù)視圖生成邏輯并映射到數(shù)據(jù)對(duì)象和物理表。
WORA:Write Once,Run Anywhere,前端一套代碼能夠在 PC、Mobile、小程序運(yùn)行(Electron、flutter、taro1.3 等框架提供了技術(shù)上的可行性)。
Hotpatch:以往比較成熟的方案是移動(dòng)端基于 jspatch、multiDex 等方案實(shí)現(xiàn) hotpatch,但由于 ios 管控及小程序生態(tài)的崛起,目前小程序化成為 hotpatch 的主流選擇。
運(yùn)行時(shí)態(tài)可配置:提供線上前后端的配置平臺(tái),實(shí)時(shí)生效。
使用門檻低:提供所見即所得的開發(fā) IDE,并且支持各種主流語言。
學(xué)習(xí)成本低:可視化開發(fā)平臺(tái);完備的文檔、Demo、視頻;使用引導(dǎo)和幫助;playground、官網(wǎng)或開發(fā)者社區(qū)。
可以看到,To B 的軟件開發(fā)考慮的維度要多于自有產(chǎn)品技術(shù)實(shí)施,它所面對(duì)的不僅僅是有和無的問題,關(guān)鍵在于平臺(tái)的整合建設(shè),這么說,未來 To B 戰(zhàn)場(chǎng)的,誰最先整合出領(lǐng)域技術(shù)平臺(tái),誰就能握有生態(tài),誰就能成為事實(shí)上的標(biāo)準(zhǔn)和規(guī)范。
2.3 解決難點(diǎn)要考慮的方面
要設(shè)計(jì)一個(gè)解決 ISV 和 SI 的痛點(diǎn)、滿足業(yè)務(wù)開發(fā)和擴(kuò)展的需要,具備靈活的二開能力,并且方便使用的 To B 應(yīng)用開發(fā)平臺(tái),需要考慮很多方面:
首先,從分層的角度來看,管理一個(gè) To B 的產(chǎn)品或解決方案,要有一個(gè)可視化的研發(fā)過程管理平臺(tái)
向 ISV 及 SI 提供統(tǒng)一的研發(fā)過程管理平臺(tái)、注入統(tǒng)一的開發(fā)流程和理念是非常有必要的,這不僅可以降低合作伙伴接入生態(tài)的難度,也可以增強(qiáng) ISV 和 SI 進(jìn)行項(xiàng)目開發(fā)的規(guī)范性;同時(shí)基于平臺(tái)對(duì)項(xiàng)目過程數(shù)據(jù)進(jìn)行結(jié)構(gòu)化地存儲(chǔ),以利于后續(xù)利用大數(shù)據(jù)進(jìn)行效率、利潤(rùn)、成本的核算。這個(gè)研發(fā)過程管理平臺(tái)包括項(xiàng)目管理功能,同時(shí)對(duì)接前端和后端平臺(tái)進(jìn)行開發(fā),并且提供質(zhì)量管理和人員管理的工具,最后可以方便對(duì)解決方案和項(xiàng)目進(jìn)行集成和發(fā)布。
其次,平臺(tái)整體架構(gòu)應(yīng)該如何分層,各層的數(shù)據(jù)模型應(yīng)該如何定義,數(shù)據(jù)模型之間如何進(jìn)行映射和轉(zhuǎn)化。比如前端與業(yè)務(wù)后端的銜接,定義一套標(biāo)準(zhǔn)的 View Object 對(duì)象(包括擴(kuò)展標(biāo)簽),由 API GW 進(jìn)行解耦,通過視圖 id 或 name 進(jìn)行數(shù)據(jù)操作。再次,ISV 與 SI 的客戶定制代碼與核心產(chǎn)品代碼如何完全隔離,這里涉及到兩個(gè)二方面:
- 首先說前端,前端架構(gòu)由傳統(tǒng)的 Page Route,改為 Component Route,Page 變?yōu)榧兇獾娜萜?,這樣帶來的巨大好處是,UI 組件與 Page 解耦,使得 UI 組件成為類似于微服務(wù)一樣的獨(dú)立實(shí)體,這樣,UI 組件就可以脫離 Page 實(shí)現(xiàn)任意的組合,這就是“積木式”,同時(shí),UI 組件,可以提供 Setter 擴(kuò)展方式來增強(qiáng)組件功能、展示、甚至綁定不同的后端 API,實(shí)現(xiàn)二開;
- 再來說后端,將基礎(chǔ)能力和業(yè)務(wù)定制能力分層,兩者提供不同的注解(@Domain 代表領(lǐng)域基本業(yè)務(wù),@Business 代表領(lǐng)域定制業(yè)務(wù)),行業(yè)定制基于基礎(chǔ)能力所暴露的 SPI 進(jìn)行定制開發(fā),在不修改基礎(chǔ)能力代碼的前提下,實(shí)現(xiàn)功能的定制,基礎(chǔ)能力和業(yè)務(wù)定制能力都支持通過 SPI 來定義服務(wù)的擴(kuò)展點(diǎn);數(shù)據(jù)層面,通過定義數(shù)據(jù)視圖,對(duì)不同元數(shù)據(jù)進(jìn)行聚類、組合,以實(shí)現(xiàn)運(yùn)算的目的,同時(shí)能夠以不同的形式對(duì)后端數(shù)據(jù)進(jìn)行展現(xiàn)。
然后,業(yè)務(wù)流程如何編排,這里業(yè)界有不同的做法,本文中推薦在前端基于組件實(shí)現(xiàn)可視化的業(yè)務(wù)流,在微服務(wù)的架構(gòu)下,前端組件一般 1v1 對(duì)應(yīng)后端接口,通過用可視化(組件之間的關(guān)系連線)方式定義前端組件之間的調(diào)用關(guān)系,間接建立后端功能流程的調(diào)用鏈。
再后,基于 API 網(wǎng)關(guān)實(shí)現(xiàn)前后端的分離,實(shí)現(xiàn)接口級(jí)別的熔斷、權(quán)限、安全、降級(jí)等策略;同時(shí)提供日志管理和異常監(jiān)控(包括穩(wěn)定性監(jiān)控和業(yè)務(wù)異常監(jiān)控)。
最后,基于 CICD 平臺(tái),能夠基于 yaml 將前后端應(yīng)用單個(gè)或整體快速拉起,以實(shí)現(xiàn)解決方案級(jí)別的快速部署和升級(jí)。同時(shí)自動(dòng)將產(chǎn)品的功能模塊沉淀回中臺(tái),并將項(xiàng)目過程數(shù)據(jù)作結(jié)構(gòu)化存儲(chǔ),作為二次開發(fā)的基礎(chǔ)能力。
3、應(yīng)用開發(fā)平臺(tái)的架構(gòu)設(shè)計(jì)
根據(jù) 2.3 的考慮,一個(gè)完整的 To B 應(yīng)用開發(fā)平臺(tái)架構(gòu)總體可以劃分為 5 個(gè)部分,分別是項(xiàng)目管理層、前端拼裝層、后端能力層、底層框架和 Runtime Infrastructure。
項(xiàng)目管理層主要是提供一個(gè)研發(fā)過程管理平臺(tái),方便 ISV 和 SI 可視化管理項(xiàng)目和需求,對(duì)接 Runtime Infrastructure,并提供前后端開發(fā)工具。
前端拼裝層分為二部分,基礎(chǔ)部分與 APIGW 對(duì)接,基于 VO 建模,可視化配置和綁定業(yè)務(wù)能力接口;拼裝部分基于可視化編輯器提供前端組件的積木式組裝。
后端能力層分為二部分,基礎(chǔ)能力封裝業(yè)務(wù)核心代碼,用于快速構(gòu)建基線能力;定制能力主要基于 SDK 進(jìn)行定制開發(fā),基于 SPI 擴(kuò)展點(diǎn),利用多態(tài)特性實(shí)現(xiàn)定制。
開發(fā)框架主要是提供 SDK(封裝注解及定義)方便定制開發(fā)、vs studio plugin 和 maven 插件用于打包發(fā)布。
Runtime Infrastructure 包括 CICD、日志、運(yùn)行監(jiān)控、自動(dòng)化測(cè)試等能力。
一、研發(fā)過程管理平臺(tái)的架構(gòu)設(shè)計(jì)方案
除了編碼采用線下開發(fā)(提供必要的 plugin、sdk,如果部署方式走 serverless,可以考慮集成 monaco 進(jìn)行定制,實(shí)現(xiàn)線上 coding->compile->test->deploy 一體化),其它包括項(xiàng)目管理、需求管理、版本管理、工程管理均可在該平臺(tái)上集成并進(jìn)行日常管理。同時(shí),研發(fā)過程管理平臺(tái)還可通過對(duì)接前端開發(fā)平臺(tái)、后端開發(fā)平臺(tái)、CICD 平臺(tái)、質(zhì)量管理平臺(tái)、帳戶體系形成一個(gè)完整的應(yīng)用開發(fā) studio。
二、前端業(yè)務(wù)組件拼裝的架構(gòu)設(shè)計(jì)方案
裝修編輯器:提供支持相對(duì)布局絕對(duì)布局的編輯器,提供包括頁(yè)面布局調(diào)整、樣式調(diào)整、組件拖拽展示、預(yù)覽、屬性設(shè)置在內(nèi)的所見即所得的功能體驗(yàn)。
復(fù)用沉淀機(jī)制:前端拼裝的基本粒度是業(yè)務(wù)組件,能完成具體業(yè)務(wù)動(dòng)作的,與后端能?連接的(可選)業(yè)務(wù)組件,? ?交互 / 基礎(chǔ)組件。舉例來說,商品列表、購(gòu)物車、買家訂單列表都是前端拼裝中的組件,? Button 、Input 、Toast 等屬于基礎(chǔ)組件(Base Component),不是前端拼裝會(huì)操作的組件級(jí)別。版本發(fā)布時(shí),新開發(fā)或修改的組件經(jīng)過 webpack 打包成 npm 包,上傳 npm 倉(cāng)庫(kù),用于下次開發(fā)復(fù)用。
業(yè)務(wù)流編輯器:用于描述前端組件之間關(guān)聯(lián)關(guān)系的編輯器(所謂關(guān)聯(lián)關(guān)系,目前可以淺顯地表現(xiàn)為組件跳轉(zhuǎn)顯示關(guān)系,實(shí)際上由于每個(gè)業(yè)務(wù)組件都與后端 API 關(guān)聯(lián),也代表了后端的調(diào)用流程),提供 4 種基礎(chǔ)概念元件,分別為 Process、Branch、Begin、End,每個(gè)概念元件均可以綁定特定業(yè)務(wù)組件,在編輯器上將概念元件連線,然后通過組件內(nèi)部實(shí)現(xiàn)的“出入口”機(jī)制,實(shí)現(xiàn)組件與組件之間的跳轉(zhuǎn)關(guān)系。
頁(yè)面管理:頁(yè)面在業(yè)務(wù)組件化的前端系統(tǒng)中,作為業(yè)務(wù)組件的容器,承載布局信息。
后端服務(wù)綁定:每個(gè)組件都能有選擇地綁定 1 到多個(gè)后端 API,當(dāng)點(diǎn)擊該組件中某個(gè)控件的響應(yīng)操作時(shí),會(huì)觸發(fā)對(duì)后端 API 的調(diào)用。這樣的好處是,解決方案部署的同時(shí)復(fù)用了前后端的功能和體驗(yàn),可以快速生成原型或交付件。
同時(shí),為了提升開發(fā)體驗(yàn)和效率,需要配套提供開發(fā) SDK、集成開發(fā)環(huán)境的插件(vsc plugin 等)、以及包括配置、告警、監(jiān)控、A/B Test 等在內(nèi)的公共基礎(chǔ)能力。
三、后端開放性架構(gòu)設(shè)計(jì)方案
由后端服務(wù)提供服務(wù) SDK,前端組件通過該 SDK 對(duì)后端網(wǎng)關(guān)暴露的 API 進(jìn)行綁定,事實(shí)上建立了業(yè)務(wù)組件與后端服務(wù)的關(guān)聯(lián)關(guān)系,這種綁定方式是去代碼化的,并且基于精巧設(shè)計(jì)的、對(duì)象化的、功能兼容的接口(例如 graphql)可以實(shí)現(xiàn)動(dòng)態(tài)切換(免代碼修改)。
Domain Service(領(lǐng)域服務(wù))通過對(duì)領(lǐng)域功能和流程進(jìn)行抽象,提供基線(標(biāo)準(zhǔn))功能,并對(duì)領(lǐng)域數(shù)據(jù)封裝原子級(jí)別的操作入口。
Business Service(業(yè)務(wù)服務(wù) / 定制服務(wù))基于 Domain Service 提供的擴(kuò)展點(diǎn)(SPI)實(shí)現(xiàn)功能和流程的定制。
Domain 和 Business 可以實(shí)現(xiàn)完全的代碼隔離,這對(duì)于生態(tài)的知識(shí)產(chǎn)權(quán)保護(hù)非常關(guān)鍵。
DB 和數(shù)據(jù)訪問層主要作用是對(duì) Domain 標(biāo)準(zhǔn)定義進(jìn)行領(lǐng)域數(shù)據(jù)建模,同時(shí)針對(duì)業(yè)務(wù)提供數(shù)據(jù)建模的擴(kuò)展能力,并且服務(wù)于 B 端,還需要充分考慮租戶間數(shù)據(jù)隔離和數(shù)據(jù)跨應(yīng)用聯(lián)通的方案。
3.1 前端的開放性設(shè)計(jì)
前端的開放性設(shè)計(jì)涉及到 4 個(gè)維度:業(yè)務(wù)組件、沉淀與復(fù)用、業(yè)務(wù)流、組件的擴(kuò)展。
3.1.1 組件業(yè)務(wù)化及跨平臺(tái)化
這里的業(yè)務(wù)組件,如前面所述,是能夠觸發(fā)或完成一個(gè)業(yè)務(wù)動(dòng)作、與后端能力連接的業(yè)務(wù)組件,??交互 / 基礎(chǔ)組件。這樣,一個(gè)業(yè)務(wù)組件實(shí)際上封裝了端到端的邏輯(前端的操作、體驗(yàn),后端的功能、數(shù)據(jù))。使用一個(gè)業(yè)務(wù)組件,實(shí)際上也使用了與其綁定的后端能力和數(shù)據(jù)
另外,由于 To B 市場(chǎng)在端側(cè)的多樣性,從成本的現(xiàn)實(shí)考慮,前端組件跨平臺(tái)的需求也非常常見,近幾年,由于 Electron、微信小程序、RNWeex 等技術(shù)的成熟,類 html css js 已經(jīng)成為事實(shí)上跨多端的首選技術(shù)。
PC 端與 Mobile 端由于體驗(yàn)的差異,組件往往不能共享,但通過一定的表現(xiàn)式語法抽象(suning DSL),通過提供 DSL parse sdk 對(duì)抽象語法解析,提供更高層次響應(yīng)式的解釋和適配(如,在 PC 端可以解釋渲染為 List,在 Mobile 端可以解釋渲染為 ListView),可以在一定條件下實(shí)現(xiàn) Write Once Run Anywhere。
3.1.2 沉淀與復(fù)用
前端工程在開發(fā)之初,定義 PRD(這種 PRD 是一種電子化的,可結(jié)構(gòu)化定義并存儲(chǔ)的 PRD),并在平臺(tái)上創(chuàng)建解決方案。
復(fù)用:新迭代或新應(yīng)用開發(fā)時(shí),根據(jù)業(yè)務(wù)需求,可以到業(yè)務(wù)組件倉(cāng)庫(kù)中尋找(類似于 AppStore),如果是已有且可復(fù)用能力,則由平臺(tái)直接添加 NPM 依賴到對(duì)應(yīng)開發(fā)工程中,對(duì)于不具備的能力,標(biāo)識(shí)為 todo。
沉淀:當(dāng)業(yè)務(wù)組件開發(fā)完成,通過在 CICD 平臺(tái)配置腳本,同時(shí)沉淀業(yè)務(wù)組件的 NPM 包,并更新 PRD,為下次復(fù)用準(zhǔn)備。
這種沉淀和復(fù)用機(jī)制,以業(yè)務(wù)功能維度進(jìn)行,實(shí)現(xiàn)了代碼的完全隔離,并依賴平臺(tái),可實(shí)現(xiàn)完全的自動(dòng)化。
3.1.3 業(yè)務(wù)流
單獨(dú)對(duì)組件粒度進(jìn)行復(fù)用依然會(huì)帶來不必要的重復(fù)工作量,同時(shí)組件間也需要?種機(jī)制進(jìn)行串聯(lián)。頁(yè)面組是?種?式,將?個(gè)高度相關(guān)的頁(yè)面做成?個(gè)頁(yè)面組,彼此通過相對(duì) url 串聯(lián)。但某些交叉頁(yè)面(例如商家后臺(tái)首頁(yè))可能會(huì)是多個(gè)業(yè)務(wù)行為的入口,包含多個(gè)業(yè)務(wù)組件,如果有關(guān)系的頁(yè)面都做成頁(yè)面組,那?個(gè)頁(yè)面組可能會(huì)包含很多個(gè)業(yè)務(wù)?為;如果將這種交叉頁(yè)面從頁(yè)面組中拿掉,?會(huì)導(dǎo)致頁(yè)面組本身不完整;后臺(tái)系統(tǒng)較少交叉頁(yè)面,而前臺(tái)系統(tǒng)會(huì)有很多。所以通過定義業(yè)務(wù)流(操作流),并定義等價(jià)組件(Equivalent Component),來解決上面的問題,使分解?個(gè)站點(diǎn)成為多個(gè)業(yè)務(wù)行為并再組合成為可能。
3.1.4 組件的擴(kuò)展
首先,通常的業(yè)務(wù)組件,其邊界是模糊的,并且與應(yīng)用頁(yè)面的緊密耦合,導(dǎo)致其無法被內(nèi)聚實(shí)現(xiàn),并進(jìn)行復(fù)用。其原因主要有兩點(diǎn):
1、應(yīng)?內(nèi)邏輯由 url 串聯(lián),url 屬于應(yīng)?全局的信息,但會(huì)出現(xiàn)在業(yè)務(wù)組件內(nèi)部;
2、使?全局狀態(tài)管理,組件間共享狀態(tài),但往往未經(jīng)過良好 設(shè)計(jì),導(dǎo)致組件間有隱式的互相依賴;
因此,需要將顯式的 url 從組件內(nèi)移除,引入出口概念,組件自定義出口(行為和參數(shù)),將出口行為和出口目標(biāo)分離,并提供業(yè)務(wù)組件級(jí)別的狀態(tài)管理,狀態(tài)可在業(yè)務(wù)組件內(nèi)的繼承組件間共享,但不可以在業(yè)務(wù)組件間共享。
其次,由于組件具有業(yè)務(wù)屬性,而業(yè)務(wù)之間往往存在一種固有的流程機(jī)制(如加車 ->下單 ->支付),通常的方案,是建立一組 Page 的集合(Page Group),彼此通過相對(duì) url 建立關(guān)聯(lián)。但某些 Page 包含多個(gè)業(yè)務(wù)行為的入口(如首頁(yè)樓層),如果有關(guān)系的 Page 都做成 Page Group,那一個(gè) Page Group 可能會(huì)包含很多個(gè)業(yè)務(wù)行為,無法復(fù)用;如果將這種場(chǎng)景排除掉,又會(huì)導(dǎo)致方案本身的不完整。因此,基于頁(yè)面來復(fù)用這種業(yè)務(wù)關(guān)聯(lián)是不合適的(如前所說,Page 只是一種容器)如果建立一種串聯(lián)機(jī)制,可以動(dòng)態(tài)地定義業(yè)務(wù)組件之間的關(guān)系,便可以脫離 Page 的限制,實(shí)現(xiàn)真正的解耦。
因此,可以引入業(yè)務(wù)流(操作流)的概念,動(dòng)態(tài)地定義組件之間的關(guān)聯(lián)關(guān)系,使復(fù)雜業(yè)務(wù)關(guān)系的復(fù)用和重組成為可能。
業(yè)務(wù)流(操作流)是一組具有關(guān)聯(lián)關(guān)系的業(yè)務(wù)組件的集合,通過數(shù)據(jù)結(jié)構(gòu)定義組件之間的關(guān)聯(lián)關(guān)系,通過這種方式將業(yè)務(wù)流觸發(fā)條件和行為封裝在操作流內(nèi)部,不再受 UI 變化的影響,也就規(guī)避了以往頁(yè)面變化時(shí),url 和調(diào)用方式需要重新實(shí)現(xiàn)的問題。
實(shí)現(xiàn)組件間跳轉(zhuǎn)的邏輯:
1、Component 描述出口方法和數(shù)據(jù)對(duì)象
2、在業(yè)務(wù)流(Business Unit)中獲取 SourceComponent 組件的出口 output 定義,執(zhí)行 output 方法,命中 TargetComponent。
3、獲取 TargetComponent 所在的 Page,匹配 output 或 URL,設(shè)定跳轉(zhuǎn)方式,并執(zhí)行跳轉(zhuǎn)。
最后,來講一下組件本身的擴(kuò)展。
UI 的實(shí)時(shí)響應(yīng)式擴(kuò)展:依賴于 ReactVueAngular 等響應(yīng)式前端框架,利用組件的單向 / 雙向數(shù)據(jù)綁定能力,當(dāng)組件的屬性發(fā)生變化時(shí),VDOM 會(huì)對(duì)變更部分進(jìn)行實(shí)時(shí)的局部渲染。利用這個(gè)特性,我們可以設(shè)計(jì)一種組件的 Setter 機(jī)制,這是一種屬性的注入器,利用 js 實(shí)現(xiàn),當(dāng)變更組件的某個(gè)屬性,比如背景色、分欄、圖片等,可以實(shí)時(shí)地對(duì)反饋到組件的展現(xiàn)部分。對(duì)于功能部分的擴(kuò)展:可以對(duì)組件現(xiàn)有能力進(jìn)行兼容或非兼容性升級(jí),重新發(fā)布到線上,并通過組件更新機(jī)制來實(shí)現(xiàn)功能擴(kuò)展。
3.2 后端的開放性設(shè)計(jì)
前端組件應(yīng)對(duì)了業(yè)務(wù)場(chǎng)景化需求,但這個(gè)復(fù)用顆粒度對(duì)于業(yè)務(wù)邏輯和數(shù)據(jù)而言仍然比較粗,因?yàn)榧词故遣煌膱?chǎng)景,內(nèi)部的邏輯和數(shù)據(jù)結(jié)構(gòu)依然可以復(fù)用。而且,后端大都采用了微服務(wù)架構(gòu),各系統(tǒng)提供了原子接口,不同的原子接口匯聚成一個(gè)個(gè)標(biāo)準(zhǔn)業(yè)務(wù)流程,但在 To B 的生態(tài)中,定制與擴(kuò)展的場(chǎng)景很常見,比如:
基線提供的業(yè)務(wù)流程,在交付給 A 和 B 的過程中,都有存在定制變更的可能性,當(dāng)然,對(duì)于這種場(chǎng)景,可以通過在基線中做個(gè)功能全集,然后定義不同的業(yè)務(wù)參數(shù)或配置來開關(guān),但還有些場(chǎng)景是開關(guān)和配置無法滿足的,比如互斥和擴(kuò)展的場(chǎng)景:
這個(gè)時(shí)候,要么拉分支自己改,但這樣做后續(xù)代碼分支多了很難合并收斂,增加運(yùn)維成本;如果讓 ISV 和 SI 維護(hù)分支,又冒著核心代碼公開的風(fēng)險(xiǎn)。
因此,如果能設(shè)計(jì)一種靈活二開的后端開發(fā)框架,由 ISV 和 SI 根據(jù)業(yè)務(wù)定制需求進(jìn)行擴(kuò)展,便有了必要性。
3.2.1 架構(gòu)和流程
將后端服務(wù)劃分為:網(wǎng)關(guān)、業(yè)務(wù)定制層和基礎(chǔ)能力層。其中網(wǎng)關(guān)主要作用是對(duì)外暴露 API,Business 和 Domain 的服務(wù)都負(fù)責(zé)各自領(lǐng)域的業(yè)務(wù)建模,包括自己的元數(shù)據(jù)建模和視圖建模,Business 和 Domain 都對(duì)外提供服務(wù),不同的是,Domain 提供提 SPI,是可復(fù)用、可擴(kuò)展的點(diǎn)。而 Business 可以提供 SPI,也可以提供 API,視具備策略而定。
上圖是一個(gè)二開的示意流程,在每個(gè)變更點(diǎn),添加待實(shí)現(xiàn)的 SPI,并在平臺(tái)結(jié)構(gòu)化落庫(kù)。在網(wǎng)關(guān)上添加(新增)或修改(現(xiàn)有)API,指向該 SPI,此時(shí),前端可以在平臺(tái)上查詢到該新增的 API。通過元數(shù)據(jù)建模和視圖建模,并結(jié)構(gòu)化存儲(chǔ)到平臺(tái)上,前端可通過平臺(tái)查詢到視圖信息,根據(jù)視圖的 schema 可以進(jìn)行前端開發(fā)。后端則實(shí)現(xiàn)該 SPI,并通過 CICD 發(fā)布沉淀到平臺(tái)中,用于交付及后續(xù)復(fù)用。
3.2.2 SPI
SPI 是后端框架實(shí)現(xiàn)開發(fā)性設(shè)計(jì)的關(guān)鍵元素,它由服務(wù)的提供者來定義,確定命名空間、方法名、出入?yún)ⅲ脚_(tái)上的 SPI 可以簡(jiǎn)單對(duì)應(yīng)到 java 世界中一個(gè)單方法的 interface。
Business 和 Domain 對(duì)外暴露 SPI(Business 可以暴露 API),通過對(duì) SPI 定義、迭代、調(diào)度、復(fù)用和沉淀實(shí)現(xiàn)能力的開放。
注解:
@BusinessSPI 業(yè)務(wù)應(yīng)用層 SPI 注解
@DomainSPI 領(lǐng)域中心層 SPI 注解
SPI 定義的步驟:
1、從平臺(tái)上創(chuàng)建的 git repo 上 clone 到可開發(fā)的 maven 工程
2、在工程目錄的對(duì)應(yīng)目錄中編寫 spi 定義,并加上 @SPI 注解
3、命名工程中提供的 maven 插件打包,插件會(huì)將 spi 信息抽取并提交到平臺(tái)。
4、平臺(tái)會(huì)生成實(shí)際可用的 jar 并發(fā)布到 maven 倉(cāng)庫(kù),返回操作成功與否等信息,開發(fā)者可以在編譯打印中查看。
SPI 定義的示例:
通過定義 SPI 對(duì)外暴露各類可定制點(diǎn),利用 java 的多態(tài)性,針對(duì)不同的業(yè)務(wù)場(chǎng)景定制不同的 Impl。在實(shí)際的使用中,框架還需要支持 version、多租戶等層面的信息,用于確保路由的正確性。
目前的二開,主要是通過 SPI 的機(jī)制,在現(xiàn)有產(chǎn)品和解決方案的 Domain 能力基礎(chǔ)上進(jìn)行覆寫或擴(kuò)展,實(shí)際使用中,可能存在以下幾種情況:
1、給定的 SPI 抽象準(zhǔn)確,現(xiàn)有的實(shí)現(xiàn)代碼滿足要求,則直接使用現(xiàn)有鏡像。
2、給定的 SPI 抽象準(zhǔn)確,現(xiàn)有的實(shí)現(xiàn)無法滿足要求,則重寫一個(gè)新實(shí)現(xiàn)。
3、給定的 SPI 抽象不準(zhǔn)確,邏輯無法滿足要求,則定義一個(gè)新的 SPI 并實(shí)現(xiàn)。實(shí)際使用場(chǎng)景中,@注解還可以細(xì)分成多種:
1)命令式申明注解 @BusinessCMDSPI、@DomainCMDSPI
2)查詢式申明注解 @BusinessQuerySPI、@DomainQuerySPI
3.2.3 元數(shù)據(jù)
元數(shù)據(jù)提供 @Entity 注解來申明定義。
元數(shù)據(jù)不支持嵌套(主要是因?yàn)閺?fù)雜,同時(shí)不是必要),一個(gè) Entity 內(nèi)部的成員變量不能是 Entity。
元數(shù)據(jù)參數(shù)存儲(chǔ)上支持字段擴(kuò)展,采用屬性值表設(shè)計(jì),原來應(yīng)用配置的數(shù)據(jù)源會(huì)退化為元數(shù)據(jù)后端的地址;元數(shù)據(jù)后端提供視圖映射功能,可以針對(duì)元數(shù)據(jù)直接做聚合查詢,并直接生成 SPI 及對(duì)應(yīng) SPI 的實(shí)現(xiàn)代碼。
Entity 定義后實(shí)際可能會(huì)映射到多張物理表,整體方案從技術(shù)上來說,主要難度在于事務(wù)處理上,目前來看短期內(nèi)沒法構(gòu)建一套可靠穩(wěn)定的方案,因此,操作內(nèi)部實(shí)現(xiàn)目前走 mapper 并直連數(shù)據(jù)源,但對(duì)外暴露統(tǒng)一的 load/save 方法。
定義及沉淀流程:
1、開發(fā)時(shí),定義 Entity 并申明 @Entity 注解,通過 IDE 插件解析注解,將本地元數(shù)據(jù)定義 DSL Push 到平臺(tái)服務(wù),平臺(tái)根據(jù)定義自動(dòng)識(shí)別變更、合法性,生成物理庫(kù)表。
2、IDE 插件提供一套類似 lombok 的編譯器修改抽象語法樹的機(jī)制,給元數(shù)據(jù)提供 load/save 等方法。
3、增加元數(shù)據(jù) save 擴(kuò)展點(diǎn)方便 handle 業(yè)務(wù)代碼插入。
4、運(yùn)行時(shí),具體的 load 和 save 方法會(huì)調(diào)用元數(shù)據(jù)后端提供的 RPC 服務(wù)。
5、發(fā)布時(shí),元數(shù)據(jù)地根據(jù) Application 類名,并變更自動(dòng)生成的版本號(hào)。
3.2.4. 視圖
在 To B 的應(yīng)用中,表單和列表占據(jù)半壁江山,可以針對(duì)典型的中后臺(tái)應(yīng)用表單進(jìn)行抽象,輸出一份通用 scheme,基于該 scheme 進(jìn)行視圖建模。
業(yè)務(wù)上很多場(chǎng)景化查詢需求,如果這部分實(shí)現(xiàn)全部落到 Domain 層,對(duì) Domain 層的穩(wěn)定性是個(gè)沖擊,視圖建模和視圖查詢主要應(yīng)對(duì)這些場(chǎng)景。
在后端平臺(tái)側(cè)提供視圖建模功能,可以自由搜索元數(shù)據(jù),選擇需要的字段,組合成新的視圖,開發(fā)人員需要給出元數(shù)據(jù)字段到視圖字段的 mapping 關(guān)系,以及指定視圖的 id 作為唯一標(biāo)識(shí),并進(jìn)行發(fā)布。
發(fā)布后,平臺(tái)自動(dòng)生成對(duì)應(yīng)的 @BusinessSPI 或 @BusinessQuerySPI 定義和實(shí)現(xiàn),package 成 jar,并 Push 到 maven,對(duì)應(yīng)視圖的查詢和簡(jiǎn)單的 CRUD 結(jié)果集便可自動(dòng)生成。
如果修改視圖,在平臺(tái)上修改視圖字段,平臺(tái)重新生成相關(guān)的查詢 SPI 和實(shí)現(xiàn),并自動(dòng)變更視圖 version。
在視圖關(guān)聯(lián)數(shù)據(jù)庫(kù)方面,如果采用的是物理庫(kù)表,則可能會(huì)出現(xiàn)一個(gè)視圖對(duì)應(yīng)關(guān)聯(lián)多個(gè)庫(kù)表聯(lián)合查詢的情況,這個(gè)邏輯比較復(fù)雜,考慮了 2 種方案:
1、落到 es 進(jìn)行查詢,走 mysql->canal->es 的方案
2、走邏輯大寬表方案
3.3 前后端的銜接設(shè)計(jì)
同步 VO 與根據(jù) VO 獲取數(shù)據(jù)進(jìn)行分離,由 API GW 進(jìn)行解耦,通過視圖 id 或 name 進(jìn)行數(shù)據(jù)操作。前端通過特定接口獲取到該應(yīng)用的所有 vo,并進(jìn)行列表展現(xiàn)。每個(gè) vo 都有對(duì)應(yīng)的 version,用于同步 VO 的變更。
前端平臺(tái)提供 loader 或 parser 解析視圖 VO,反向渲染生成組件。
后端平臺(tái)通過搜索元數(shù)據(jù),選擇需要的字段,組合成新的數(shù)據(jù)視圖 -DO,后端平臺(tái)自動(dòng)生成對(duì)應(yīng)的 @BusinessSPI 或 @BusinessQuerySPI 定義和實(shí)現(xiàn),package 成 jar,并 Push 到 maven,開發(fā)本地應(yīng)用。(對(duì)于某些 VO 和 DO 直接一對(duì)一映射的場(chǎng)景,前端也可以考慮直接使用 DO)
根據(jù)上圖,開發(fā)平臺(tái)的基本流程和各層功能為:
1、基本流程:數(shù)據(jù)對(duì)象 DO->SPI->API->展現(xiàn)視圖 VO->組件 ->UI,前端業(yè)務(wù)組件直接與后端 SPI 及數(shù)據(jù)對(duì)象進(jìn)行映射。
2、前端拼裝:
1) 提供編輯器,支持絕對(duì)布局和相對(duì)布局,可以由 VO 直接生成業(yè)務(wù)組件;也可以采用類 Axure 手工拼裝成組件,并綁定后端 API。
2) 支持基于現(xiàn)有業(yè)務(wù)組件,通過業(yè)務(wù)流(操作流)和 Setter 機(jī)制來擴(kuò)展組件能力。
3、后端能力:在 Business 和 Domain 都支持通過 SPI 來定義服務(wù)的擴(kuò)展點(diǎn),ISV 和 SI 可以在不修改原有邏輯的基礎(chǔ)上,通過替換 SPI 來實(shí)現(xiàn)功能的替換、升級(jí)和擴(kuò)展。
4、數(shù)據(jù)層面:通過將前端組件與后端 SPI 及數(shù)據(jù)對(duì)象進(jìn)行映射,若對(duì)元數(shù)據(jù)對(duì)象進(jìn)行新增或變更時(shí):
1)可以直接動(dòng)態(tài)變更 UI 的展現(xiàn)形式和內(nèi)容,無須修改前后端代碼
2)通過定義數(shù)據(jù)視圖,能夠根據(jù)業(yè)務(wù)訴求,對(duì)不同元數(shù)據(jù)進(jìn)行聚類、組合、以實(shí)現(xiàn)運(yùn)算的目的,同時(shí)能夠以不同的組件形式對(duì)后端數(shù)據(jù)進(jìn)行展現(xiàn)
4、結(jié)語
從云計(jì)算的發(fā)展趨勢(shì)來看,從 Iaas 開始,未來必將在 Saas 結(jié)束(Paas 因?yàn)榘ǜ鞣N標(biāo)準(zhǔn)化組織和開源社區(qū)的存在,未來少有溢價(jià)的可能)。而 Saas 也是議價(jià)空間和增值空間最多的地方,未來哪家企業(yè)能夠首先完成對(duì)各個(gè)行業(yè)和領(lǐng)域的在核心生產(chǎn)流程和業(yè)務(wù)抽象,整合更多更優(yōu)秀的 ISV 和 SI 資源、甚至社區(qū)的力量,誰就能成為事實(shí)上的標(biāo)準(zhǔn)。
對(duì)于 To B 領(lǐng)域的玩家,應(yīng)該走開放生態(tài)的道路,做生態(tài),就是做標(biāo)準(zhǔn);做平臺(tái),就是做信任;做開放,就是做共贏。
作者簡(jiǎn)介
榮多君,蘇寧科技集團(tuán) O2O 平臺(tái)研發(fā)中心副總監(jiān),多年 ICT 及互聯(lián)網(wǎng)工作經(jīng)驗(yàn),曾先后就職于華為、阿里巴巴,現(xiàn)在蘇寧從事 O2O 新零售業(yè)務(wù)及平臺(tái)的建設(shè),擅長(zhǎng)前后端主流技術(shù)、移動(dòng)互聯(lián)網(wǎng)平臺(tái)建設(shè)及服務(wù)治理、云原生及中臺(tái)技術(shù)。