你想知道的前后端協作規范都在這了
一. 前言
你是否在為如何制定前后端協作規范而發愁?干貨來啦,一文帶你了解我們團隊內部沉淀并踐行已久的前后端協作規范,讀完本文,回去大膽拒絕你后端的不合理設計!
二. 為什么需要協作規范?
假如你要在團隊內部推一套規范,那么首先你得知道為什么需要制定協作規范呢?有規范會帶來什么好處呢?
隨著前后端分離開發模式大行其道,前端和后端已經在兩個方向上漸行漸遠,各自深耕細作、術業專攻。前端更加關注交互視覺體驗,而后端對高并發、高性能、高擴展上要求更高。這就導致大部分的前端和后端之間會存在所謂的"代溝",我不知道你的數據如何存儲,你不知道我的頁面如何渲染。
因此,很有必要制定前后端開發上的規范來抹平代溝,有了協作規范,便有了前后端開發默契,也因此達到了提高開發效率、降低溝通成本的作用。
三. 協作流程規范
首先是協作的流程規范,相信每個團隊在前后端協作中都有各自的開發模式和開發流程來保障效率和質量,我們團隊的前后端協作大致流程如下圖所示:
- 需求導入、交互視覺導入分析 :對產品導出的需求,參會各方包括產品、前端、后端、測試、UED,在對需求的認知上要達成一致,這是開發的第一步。
- 接口設計、前后端對接接口:后端給出接口,前后端要在接口字段設計上達成大致方向上的一致。
- 技術方案評審 :在開發之前進行技術方案評審,再次確保各方在需求的認知上統一,并且雙方就接口字段可行性上再次確認。
- 并行開發 、前后端自測:前后端并行開發,在此階段前端可以 mock 數據進行頁面渲染。
- 開發環境聯調:前后端自測完成之后在開發環境上完成接口聯調。
四. 如何做接口規范?
- 前置約定:
- 后端接口定義 URL、出入參之前,前后端需達成一致。
- 文檔規范:
- 接口注釋需要寫清楚:模塊、枚舉、必填/非必填、出參是否可能為 null
- 接口需要向下兼容,如果不兼容需要評估并且通知相應的業務方
- 接口文檔上面有變更需及時同步前端
- 后端需保證文檔上定義的參數,可以正常請求接口且功能正常穩定
- 位約定:
- 時間:統一使用 13 位時間戳
- 金額:統一為分 ,可根據業務情況選擇
- 接口 URL & 請求方式
- Post 接口不允許使用 Get 傳參方式
- Post 接口必須使用 application/json 模式
- 接口命名應盡量符合語義,接口命名不要過于相似,難區分,易混淆
- 入參
- 保證同一應用領域內,相同含義的字段,命名保持一致
- 業務編號 / ID 必須為字符串類型,JS 對最大數字有限制
- 同一個頁面不同 Tab,接口盡量保證一致
- 出參
- 接口出參格式要統一
- 接口不要返回類似 "服務器內部異常"、"網絡異常" 這種無法理解的錯誤信息,非線上環境可以返回錯誤堆棧,方便排查問題
- 前后端數據列表相關的接口,如果返回為空,則返回空數組 [] 或空集合 {},有利于數據層面上的協作更加高效,減少前端很多瑣碎的 null 值判斷,特殊情況特殊分析
- 接口出參根據頁面需求返回有效字段,避免吐出過多無用字段
- 枚舉值盡量返回中文和英文描述
五. 協作中的 Bad Case
以下總結了我們團隊內部在協作中遇到的比較典型的 Bad Case 以及解決方案,我相信大家在開發過程中也遇到過類似的痛點經歷:
類型 1:前端過多的條件邏輯判斷
【現象】
- 按鈕、組件顯示與否,前端要通過大量的字段進行條件邏輯判斷;同一頁面不同場景前端調用的接口不一樣:
// 按鈕文案、顯示邏輯
{((record.state === 'RESULT_CONFIRM' && isCurrentUserCreate) ||(record.state === 'RESULT_CHECK' && isCurrentUserCreate && currentUserCanCheck )) && <Button>確認</Button>}
{['DREFT', 'AUDIT_FAILD', 'REVOKE'].includes(record.state) && isCurrentUserCreate && <Button>修改</Button>}
// A 場景調用接口 1,B 場景調用接口 2,C 場景調用接口 3 和 4
if (id) {
this.operation = '修改';
const res = await this.fetchInfo(id);
} else if (source) {
const res = await this.fetchSourceInfo(id: source);
} else {
const res = await this.fetchBasicInfo();
}
【解決】
- 控制前端顯示邏輯判定都放在后端去做處理,前端盡可能減少字段判定。
注:如果功能簡單,前端也可以做判斷,如何鑒定是否簡單?從代碼層面比如 If 判斷中超過 2 個條件,按鈕顯示超過 2 個條件,可視作復雜邏輯,邏輯移到后端處理。建議一開始就視作復雜去處理,這樣后期就不用再調整。
// 按鈕展示
前后端約定好 按鈕的顯示返回一個數組,數組具體返回哪些邏輯寫在后端。
[
{ name:'確認',type:'resultConfirm'},
{ name:'修改',type:'edit' },
]
【好處】
- 將邏輯收斂到后端,出現問題或者更改邏輯時只需一方排查或修改。即能一端完成的,絕不讓兩個端干, 兩個就可能會出現不一致的問題。
類型 2:前端二次數據加工過多
【現象】
- 頁面上同一個表格展示的數據是兩個接口拼接而成
- 接口數據返回格式不符合前端渲染邏輯,需要二次加工
【解決】
1、后端做好數據的整合,避免數據在前端的重組。
2、Tree 數據展示的場景,如果數據不大后端全量返回,如果數據量過大異步返回,但異步返回存在后續的回顯和搜索展示方面問題。
3、同一個業務功能,一個接口搞定,不要分接口進行,后端業務考慮復用可包裝新接口或原接口加參數兼容。
【好處】
減少前后端數據處理的成本,提高性能和用戶體驗
類型 3:枚舉值、下拉框數據由前端維護
【現象】
- 列表頁單據狀態由前端維護枚舉值,如果新增枚舉都需要前后端更改,可能導致最終顯示狀態不統一
// 狀態值映射
const getStatusName = (status) => {
switch(status) {
case 0:
return '草稿';
case 1:
return '待部門審批';
case 2:
return '待財務審核';
case 3:
return '待單位審核';
case 4:
return '審核中';
default:
break;
}
}
【解決】
- 確保狀態可擴展,后端已經做了枚舉的情況下,前端不需維護狀態值,以后端提供接口為準。
如果是狀態定死的情況下譬如:選項為【是、否】可無需后端返回。
// 由后端接口返回下拉框選項
{
result: [{
code: string
name: string
}]
}
【好處】
- 枚舉值變動時,只需后端更新,也避免了迭代過程中出現的前后端不一致的情況
類型 4:PC 端數據結構不適用 App 端
【現象】
- App 端的布局樣式 是較 PC 端略復雜的,如果 App 端一味采用 PC 端的接口數據,是需要前端做特殊處理的。比如,同一時間的單據 App 端放在同一張卡片內,卡片內部的標題、內容、按鈕展示也做了情況區分。
【解決】
- 判斷前端處理工作量,后端需新增接口實現 App 不同的功能。
【好處】
- 減少前端處理邏輯的成本,提高 App 上的用戶體驗
類型 5:同一業務領域同一含義的接口字段命名不統一
【現象】
- 關于返回結果:response.data、 response.result
- 關于時間:createAt、queryEffectStartingBeginTime、penaltyBeginTime
- 關于名稱:punishedInstitutionName、responderName、penaltyObjectName
- 關于 Id: punishedOrganizationId,penaltyObjectId
【解決】
- 前后端共同維護一份字段詞典,保持同一業務領域下命名一致,避免不必要的字段轉換。
類型 6:金額計算結果由前端提交給后端并入庫
【現象】
- 前端頁面中,輸入支付金額并除以總額,然后計算出支付比例,最后點擊保存按鈕將數據提交給后端接口;
【解決】
- 對于金額的計算:以是否入庫為界限,非入庫純展示可前端計算,入庫的統一由后端計算。
類型 7:前端維護業務配置類型的代碼
【現象】
- 由多個表單項(下拉框、輸入框、單選框等)的值作為條件判斷某一表單項(附件、單選框、輸入框等)是否必填、顯示或隱藏。因此,前端需要寫很多動態校驗邏輯,并且涉及到每個區劃的動態校驗邏輯還不一樣,有的校驗條件還是寫死的。
【解決】
- 配置校驗規則的頁面可根據區劃配置后生成標識碼,然后后端可提供一個通用的校驗接口,前端把值傳給后端,然后返回校驗結果是否通過。
// 入參:
{
code: '99900', // 區劃代碼
identity: '11111', // 標識碼
datas:[ // 數據
{
key: 'catalog',
value: 'A07',
},
{
key: 'assetApproval',
value: 0,
}
]
}
// 返回值:
{
result: true
}
類型 8:前端直接調用其它業務線后端的接口
【現象】
- 業務線 A 列表頁面,點擊新建按鈕,彈框調用業務線 B那邊的接口。
由于 A 和 B 是不同業務線后端,接口對接以及后期的溝通維護成本會比較高。例如該接口發生改動,需要跨業務線通知到對應的前端(該后端還不一定知道前端是哪位);并且接口返回的大量字段前端都用不到。
【解決】
- 后臺業務耦合的情況下需要自己業務線后端整合數據;如果只是為了展示非自己業務的數據后端不處理
類型 9:后端分頁接口的數據返回格式不統一
【現象】
- 目前分頁接口的數據返回格式不統一,已有如下幾種形式:
// 形式一:
{
result: {
data: [],
total: 0,
}
}
// 形式二:
{
result: {
data: [],
pagination: {
total: 0,
pageSize: 10,
pageNo: 1
},
}
}
// 形式三:
{
result: {
data: [],
total: 0,
pageSize: 10,
pageNo: 1
}
}
【解決】
- 建議后端接口統一格式如形式三。
類型 10:后端一個接口拆分多個
【現象】
- 一個表單頁,在提交之前調用三個不同的校驗接口。三個校驗接口入參也不一樣,前端需要組裝各種類型的數據。
【解決】
- 多個校驗接口和提交接口合并成一個提交接口。
- 校驗不通過時,接口返回值里區分阻塞式和提醒式
- 阻塞式:彈框告警,用戶只能關閉彈框
- 提醒式:彈框詢問,在用戶點擊"繼續提交"后,繼續調用提交接口,此時增加入參標識跳過此步校驗
六. 效果
基于一套合理可行的協作規范,前后端從開發到上線的各個階段都能夠看到諸多成效:
- 降低溝通成本,減少不必要的扯皮, 加快開發進度;
- 縮短聯調時間,減少聯調階段的代碼調整,保證了開發效率;
- 減少測試階段的排查問題歸屬,加快測試進度,保證質量;
- 方便線上問題排查及修復。
七. 總結
一言以蔽之:如果你發現前端在處理大量的邏輯,那么就是協作規范存在問題啦!前端更多的是關注交互、渲染上的邏輯,應盡量避免復雜的業務邏輯處理。萬事開頭難!推一套規范是需要時間去沉淀的,前端和后端同學都應多些耐心,多些理解。