Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 從零開始的Android新項目9 - 前端用後台接口設計

從零開始的Android新項目9 - 前端用後台接口設計

編輯:關於Android編程

這回來講講後台接口的設計。

可能有同學會覺得後台的接口和我們大前端開發有什麼關系?試想一下,在碰到一些不合理的接口設計的時候,你們開發是否覺得很別扭——需要為了坑爹的接口寫很多髒代碼引坑?甚至,這麼開發出來的頁面,體驗也會很差?我們不是說硬無理要求後端接口按照前端業務去封裝,而是說為了項目更好地發展,為了用戶能有更棒的體驗,應該有討論商量的空間。一些差勁的設計,應該被拒絕。

本文使用前端來指代 Android、iOS 以及 Web。

本文不是教大家撕逼的(趕緊撇清關系)。

全局

全局指所有接口統一的規范。

請求頭

應該使用http header來放置通用性的參數,比如:
- APPID(Android/iOS/H5)
- APPVER(版本號)
- APP-BUILD-NUM(內部小版本號)
- TOKEN
- NETWORK(網絡環境)
- LANGUAGE(語言)
- 等等

前端使用 POST 鍵值對方式提交給後端,可以使用 RawJSON 格式。
Content-Type 設為 application/x-www-form-urlencoded 或者 application/json。

全局響應格式

響應格式應該統一,方便前端做統一的處理,尤其是數據字段,應該統一放在一個map裡面。

名字 類型 詳細描述 status_no INT 狀態碼 status_msg STRING 狀態信息 data MAP 響應內容 time INT 響應時間戳

狀態碼

全局應該定義統一的狀態碼(status_code),而不應該每個接口單獨去定義。

具體規則可以自行定義,比如0為正確,負數為錯誤。

常見的錯誤狀態碼有
- 普通異常
- token不合法,需要重新登錄
- 重復登錄
- 需要完善個人信息
- 第三方賬號登陸,需要綁定官方賬號
- 請求頭不合法(版本號,APPID等)
- 數據解密錯誤

可以根據錯誤類型劃分使用的區域段,如登陸系列使用 -1000 到 -1999 區域。

如此定義後,前端可以進行全局的統一處理,如重復登陸則踢出用戶。

錯誤信息

除了特殊的錯誤信息——如重復登錄、token不合法這些狀態碼對應的,以及無網、沒數據這些,對於通用的異常,應該由後台返回錯誤信息。

統一data字段

data 字段應該統一放在一個 map 內,裡面存放具體的響應信息。

Scheme

全局定義統一的 scheme(Deeplink),方便前端進行跳轉。

前端只需要定義自己唯一的 Deeplink 並進行注冊即可(scheme 和 host)。

具體使用 REST 風格(如 markzhai://article/XXX),還是普通的 urlencode (如 markzhai://article/?id=XXX&redirect_url=XXX)可以根據自身需求定義。

使用 REST 風格的一個顧慮是可能 scheme 本身並不是基於資源的,而是基於類型、行為等,所以 urlencode 可能更通用,但相應地基於 Deeplink 的資源索引會希望你是無狀態的 REST 風格。

回傳 or 狀態碼

應該使用回傳還是狀態碼呢?比如點贊消息,是應該回傳一個 status_code,0則表示點贊成功,還是應該回傳現在的贊狀態呢?

其實這兩者對於後台的性能來說,是幾乎沒有影響的,因為取得的只是修改的字段的最後結果。但是對前端來說,差別就有了——需要維護狀態。

舉一個例子:
A 和 B 是兩個用戶,B 關注了 A,A 沒有關注 B。
A 看 B 的主頁的時候,顯示關系是 未關注,此時 A 點擊了關注,如果沒有回傳信息,那麼我們只能把關系刷新為 已關注,而沒有足夠的信息去刷新為 互相關注。否則就需要前端去做惡心的邏輯(後端一開始用戶關系就需要傳 B 關注了 A),根據原來的關系去做切換,還要在失敗的時候刷回原來的狀態。

一些有豐富經驗的後端會在這種接口使用回傳,因為他們知道區別。

模塊vs頁面

在後台的接口設計上,又分為了按頁面以及按模塊。

按頁面的接口盡可能讓前端一個頁面只請求一次,一次返回所需要的全部信息;按模塊的接口在後端定義自己的業務模塊如用戶、Feed、標簽、搜索等,並盡量避免模塊間的耦合。

從後端角度來說,按模塊當然是更好的(只需要劃分地夠細就好),到時候需求有什麼變更,讓前端自己去改變接口的組合就好,自己高枕無憂。但從前端的角度來說,接口的組合涉及到異步之間的關系,盡管RxJava這樣的響應式編程框架讓異步簡單了很多,但仍然希望可以避免,更嚴重的是,多次接口請求會讓前端的體驗變差,並行接口的影響稍小,而一些有前置後置關系的接口則麻煩比較大,一個接著一個請求,會讓用戶等很久。即便是並行接口,有時候頁面的渲染仍然需要所有接口數據返回後才可以進行。

但如果讓後端按照頁面去套,這樣在後端其實一樣有性能的損耗,需要一個頁面接口去單獨調用各個模塊的接口,然後進行組合。

究竟如何選擇呢?筆者認為在服務器性能足夠的前提下,後端應該盡量減少頁面請求次數,尤其是有依賴關系的串行請求。另一方面,在一些影響不那麼大的頁面,則可以由前端自行進行接口組合(比如上面是用戶主頁的用戶展示,下面是該用戶的 feed 列表)。

另外,如果你們有一個好的設計師,那麼他應該會貫徹一個地方只應該以一樣東西為主體,而不應該去把亂七八糟的東西拼湊在一起。

分頁信息

現代的前端交互上,已經很少會有頁碼顯示了,所以很多後端的列表頁接口中,就沒有帶上了分頁的信息,而改讓客戶端去維護請求的頁碼。

那麼,分頁信息在接口中,真的就沒有存在的必要了嗎?其實未必。

為什麼需要分頁信息

頁面大小(pageSize)可能改變(無論是前端自己的配置亦或是後台修改),如果僅由客戶端維護頁碼,那麼下次請求下一頁就會出錯,除非客戶端帶上自己上次的頁面大小。

如果客戶端不知道當前頁碼和總頁數,就無法在請求完判斷底部應該顯示上拉加載更多還是沒數據了,導致必須再請求一次,根據是否返回 list 以及數據是否為空去進行判斷。

另外,由後端返回頁碼也避免了客戶端修改頁碼出錯的可能。

但對後端來說,這些信息的獲取卻意味著更大的計算和I/O資源損耗。

折中辦法

折中地,可以讓後端返回一個 has_more 字段,這樣可以避免最後一次不必要的請求(尤其是數據都不夠顯示滿一頁的情況下),體驗會好很多。盡管這樣仍然無法避免頁面大小改變的問題。

配置

一些後台喜歡讓讓前端寫限制邏輯,比如搜索的關鍵字限制,各種過濾邏輯。

咱們先不提讓前端寫死這些邏輯的靈活性問題(客戶端和網頁不同,不能那麼方便地發版本,即便是網頁,改代碼發版本就不用測試了嗎?出了問題你背?)。前端的輸入真的可以信任嗎?且不談代碼可能寫的不夠嚴謹導致輸入跳過了檢查,用戶還能root、越獄,甚至可以反編譯客戶端或者直接模擬請求。

所以良好的配置檢查應該有兩種
- 後端下發配置字段,前端根據字段去做對應檢查。好處是減少後台壓力,壞處是無法保證安全性。
- 後端收到請求自行檢查過濾,如果出錯則返回錯誤信息給前端顯示。

毋庸置疑,後者更好。

另外,再說說靈活性。今天可能限制3個字,明天產品需求可能就是4個字,現在產品/運營說不會改,到時候難道就真的一定不會改嗎?

空字段

一些空字段,如果沒有,服務端應該返回一個空的默認字段 比如 String 用”“,int 用 0,Object 用 {},Array 用 [],這樣減小前端校驗某些校驗漏了出現錯誤的情況。

                    ---- 由三帥泥阿布補充

我個人認為這樣本身對流量損耗不大,且確實避免了很多可能的異常,是個很好的意見。當然了,正如後端不應該相信前端的輸入一樣,前端也不能相信後端數據的完備性,仍然還是需要悲劇地去校驗。

教訓

不要相信什麼以後重構,接口現在這麼說,以後他會告訴你,沒法兼容老版本所以只能這樣了(甚至搞出兩套規則讓你同時兼容)。

不是說後端就是老大。大家的目標都是為了項目能做好,而現在通常前端的壓力比後端更大(前端寫得頭昏腦花,後端網上東逛西逛),所以在不會很大影響性能的前提下,應該滿足前端的合理需求。體驗為先。(硬氣一點,老大應該挺你,甚至親自去撕逼,大不了找CTO)

接口的頻繁修改要向上反饋,測試數據不滿足要求也要及時提出。咱們不做背鍋俠。

靈活,靈活。做各種需求的時候,想一想,這兒會不會改變?就算現在不會變,以後就不會變嗎?比如抽屜裡的入口,是不是要做成可配置的?多問問,實現上盡量靈活。

總結

本篇講了很多通用的後端接口設計問題。幫助大家在面對一些不合理的接口設計時,能進行友善的討論(撕逼),讓項目能做得更好。歡迎各位在評論裡或者通過郵件([email protected])補充其他點,我會標注出來源。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved