你想知道的前後端協作規範都在這了
一. 前言
你是否在爲如何制定前後端協作規範而發愁?乾貨來啦,一文帶你瞭解我們團隊內部沉澱並踐行已久的前後端協作規範,讀完本文,回去大膽拒絕你後端的不合理設計!
二. 爲什麼需要協作規範?
假如你要在團隊內部推一套規範,那麼首先你得知道爲什麼需要制定協作規範呢?有規範會帶來什麼好處呢?
隨着前後端分離開發模式大行其道,前端和後端已經在兩個方向上漸行漸遠,各自深耕細作、術業專攻。前端更加關注交互視覺體驗,而後端對高併發、高性能、高擴展上要求更高。這就導致大部分的前端和後端之間會存在所謂的 "代溝",我不知道你的數據如何存儲,你不知道我的頁面如何渲染。
因此,很有必要制定前後端開發上的規範來抹平代溝,有了協作規範,便有了前後端開發默契,也因此達到了提高開發效率、降低溝通成本的作用。
三. 協作流程規範
首先是協作的流程規範,相信每個團隊在前後端協作中都有各自的開發模式和開發流程來保障效率和質量,我們團隊的前後端協作大致流程如下圖所示:
-
需求導入、交互視覺導入分析 :對產品導出的需求,參會各方包括產品、前端、後端、測試、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:後端一個接口拆分多個
【現象】
- 一個表單頁,在提交之前調用三個不同的校驗接口。三個校驗接口入參也不一樣,前端需要組裝各種類型的數據。
【解決】
-
多個校驗接口和提交接口合併成一個提交接口。
-
校驗不通過時,接口返回值裏區分阻塞式和提醒式
-
阻塞式:彈框告警,用戶只能關閉彈框
-
提醒式:彈框詢問,在用戶點擊 "繼續提交" 後,繼續調用提交接口,此時增加入參標識跳過此步校驗
六. 效果
基於一套合理可行的協作規範,前後端從開發到上線的各個階段都能夠看到諸多成效:
-
降低溝通成本,減少不必要的扯皮, 加快開發進度;
-
縮短聯調時間,減少聯調階段的代碼調整,保證了開發效率;
-
減少測試階段的排查問題歸屬,加快測試進度,保證質量;
-
方便線上問題排查及修復。
七. 總結
一言以蔽之:如果你發現前端在處理大量的邏輯,那麼就是協作規範存在問題啦!前端更多的是關注交互、渲染上的邏輯,應儘量避免複雜的業務邏輯處理。萬事開頭難!推一套規範是需要時間去沉澱的,前端和後端同學都應多些耐心,多些理解。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/NjX2be78BlHrXF5hlKlA8A