如何構(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í)很容易陷入到無(wú)邊界的陷阱中,從技術(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 解決方案無(wú)論是在公有云還是專有云上,和自有技術(shù)產(chǎn)品實(shí)施相比,存在很多差異和問題:
- ISV、SI 和客戶自己的實(shí)現(xiàn)難以保證效果;
- 標(biāo)準(zhǔn)產(chǎn)品與定制開發(fā)要筑起柵欄,實(shí)施二開不能泄露核心代碼;
- 開發(fā)完成的前后端組件,需要結(jié)構(gòu)化沉淀成為可復(fù)用的二方庫(kù);
- 前后端組件往往無(wú)法直接復(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,并且支持各種主流語(yǔ)言。
學(xué)習(xí)成本低:可視化開發(fā)平臺(tái);完備的文檔、Demo、視頻;使用引導(dǎo)和幫助;playground、官網(wǎng)或開發(fā)者社區(qū)。
可以看到,To B 的軟件開發(fā)考慮的維度要多于自有產(chǎn)品技術(shù)實(shí)施,它所面對(duì)的不僅僅是有和無(wú)的問題,關(guān)鍵在于平臺(tái)的整合建設(shè),這么說,未來 To B 戰(zhàn)場(chǎng)的,誰(shuí)最先整合出領(lǐng)域技術(shù)平臺(tái),誰(shuí)就能握有生態(tài),誰(shuí)就能成為事實(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)式語(yǔ)法抽象(suning DSL),通過提供 DSL parse sdk 對(duì)抽象語(yǔ)法解析,提供更高層次響應(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)致其無(wú)法被內(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ù)行為,無(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)和配置無(wú)法滿足的,比如互斥和擴(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)無(wú)法滿足要求,則重寫一個(gè)新實(shí)現(xiàn)。
3、給定的 SPI 抽象不準(zhǔn)確,邏輯無(wú)法滿足要求,則定義一個(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 的編譯器修改抽象語(yǔ)法樹的機(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)容,無(wú)須修改前后端代碼
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é)語(yǔ)
從云計(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ū)的力量,誰(shuí)就能成為事實(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ù)。