【轉載】做者:曾健生,公衆號ID:appbackendjavascript
比目科技 Bmob後端雲php
app和後端的交互,通常都是經過後端提供的api實現。api的設計,估計不少剛進入app後端的小夥伴會一無頭緒,不知道怎麼入門。下面根據本身3年的app後端經驗,總結出下幾個api設計原則,給小夥伴參考:html
1. 什麼是api?前端
這個問題在之前發表的文章「7.app和app後端的通信」中其實已經回答了,這裏再重複一次。java
相信你們都用過銀行的櫃員機(ATM)的查詢餘額,轉賬,取款等操做。程序員
當在櫃員機取款的時候,咱們輸入要取款的金額,隔一會錢就出來了,若是由於有什麼問題不能取款(例如超過取款金額的限制),屏幕上也會顯示出錯誤的信息。web
在整個過程當中,咱們只要輸入金額,得到結果(取款成功或不成功),就好了,至於櫃員機內部是怎麼處理,咱們不須要理會。數據庫
櫃員機這種把內部的處理遮蔽的作法極大方便了咱們的使用。編程
一樣的,在後端,也只提供了一系列的功能給app使用,這系列的功能以api的形式提供。json
api的定義:API(Application Programming Interface,應用程序編程接口)是一些預先定義的函數,目的是提供應用程序與開發人員基於某軟件或硬件得以訪問一組例程的能力,而又無需訪問源碼,或理解內部工做機制的細節。
當app調用api的時候,只須要明確下面3點:
1.這個api是幹啥的(櫃員機例子中,是取款功能,仍是查詢餘額,仍是轉帳)
2.知道要輸入什麼(櫃員機例子中,取款要輸入金錢)
3.知道結果是什麼(櫃員機例子中,取款是成功仍是失敗)
至於api內部是怎麼處理的,app根本無需理會。
從這裏可看出,api能在最大程度遮蔽了app後端複雜性,極大提升了app前端的開發效率。
2. api設計的8點
(1)Restful設計原則
Restful風格:RESTfu設計原則,它被Roy Felding提出(在他的」基於網絡的軟件架構「論文中第五章)。而REST的核心原則是將你的API拆分爲邏輯上的資源。這些資源經過http被操做(GET ,POST,PUT,DELETE)。
在實際的開發過程當中發現,程序員因爲在web端養成的習慣,api操做中一般就只有兩種方式"POST""GET"。你們可看一下微博的api例子"statuses/destroy",這個很明顯是delete操做的api倒是用post方式提交。不是徹底遵照Restful風格的風格。
這個設計原則最簡單的應用就是根據object而不是頁面來設計api。最開始的時候,app的一個頁面須要什麼數據,api就返回什麼數據。結果隨着app的UI不斷改版,須要的數據不斷變化,不停地修改api,最後當api的改動會影響之前的版本的時候,只能寫一個新的api版本,最後弄得api中有不少V2,V3這樣的標誌,惡夢!
後來在網站的重構過程當中,就根據object來設計api,但根據object來設計,又有一個問題,一個大object可能包含不少小object,是一個api返回所有小object,仍是分爲多個api返回?根據業務和技術,帶寬等仔細考慮吧。
(2) api的命名
一看api名字就知道這個api是幹啥。在創業團隊中,通常就只有一兩我的負責後臺,當你要負責幾十甚至上百個api,你就知道不能「望名知api」是個什麼樣的痛苦。
api的命名,我是挺喜歡微博的命名風格,例如刪除微博的api "statuses/destroy",第一個是對象,第二個是對象的操做刪除
(3)api的安全性
這點會在之後的「怎麼保證app通信的安全性」一文中詳細論述。
(4) api返回數據
app客戶端的語言 java 和object-c都是強類型語言,因此怎麼處理空值顯得特別重要,不合理的設計很容易形成app的閃退。
從後臺的角度來講,api中返回的數據中,正確值和空值的類型必須同樣,舉例,用戶名的字段是「realname": "xxx」,若是用戶名爲空,則應該返回「realname": ""。若是返回值是一個array,空數據則返回一個空array,絕對禁止null值。
對於客戶端,必須用個全局的函數來處理全部api的返回數據,須要有一個機制:對於某個客戶端須要數據,若是api中缺失,客戶端自動補上並給予默認值。這個機制在咱們的實踐中大大減小了app的閃退。
同時,在數據庫設計的時候,一個合理的設計必須是全部字段都有默認值,不該該容許null值。null在大量的語言和數據庫中,會帶來無窮的問題。對於這個數據庫設計原則,我之前不太明白,如今經歷了一年的api設計後,終於懂得。
若是客戶端是php,還有一個問題,php中數組和字典都是array,但在java 和object-c中是不同,這個問題必定要注意。
(5)圖片的處理
在不一樣版本的app中,各類不一樣尺寸的手機中,同一張圖片顯示的尺寸多是不同,若是每次都須要用返回原圖,而後在客戶端處理,則極大浪費網絡資源。而若是是後臺處理好圖片才返回,則又是一個挑戰,怎麼有效保存和裁剪多種圖片尺寸呢
例如,一開始頭像只須要返回60*60的尺寸,後來在新的版本須要返回70*70, 又出了一個新版本,須要返回80*80, 每次增長一個新的尺寸,怎麼在數據庫上記錄下來。這個問題在一開始作api的時候沒考慮,後來不得不用了一個極端的方法,沒增長新的圖片尺寸,就在數據庫中增長一個新的字段,保存並生成新的圖片尺寸,結果最後數據庫的頭像字段有"avatar","avatar_60_60","avatar_70_70","avatar_80_80",這種極度惡虐的設計。
最後,針對圖片,咱們才用了這樣的策略:
(1)客戶端本地緩存圖片,只有沒有合適的圖片,纔去服務器取。
(2)當客戶端須要某種尺寸的圖片,由客戶端告訴服務端圖片的尺寸,服務端動態生成並緩存起來。
例如,客戶端須要圖片(http://www.baidu.com/img/bdlogo.gif)的80*80的尺寸,則在圖片的路徑加上寬和高的參數(相似於CDN的機制) http://www.baidu.com/img/bdlogo.gif?w=80&h=80, 則服務器就生成80*80的尺寸並返回。
採用了這樣的圖片處理機制,數據庫中只要有一個字段保存原圖就好了,其它尺寸就由客戶端告訴服務端動態生成。之後不管什麼尺寸的圖片,數據庫中都不須要記錄,數據庫只有原圖就好了。
注意,如今的文件雲存儲服務(例如七牛,又拍雲)等都提供了這個文件的縮放功能,並且能加速文件的上傳下載速度,極大提高了app的用戶體驗,強烈推薦使用。
(6)返回的提示信息
最科學的狀況,服務端只返回信息代碼,具體的文字提示由客戶端決定。
若是文字信息是由服務端返回,則最起碼要區分2種信息:提示用戶的信息,提示客戶端程序員的信息。這二者的區別:
1.提示用戶的信息是要在讓客戶知道的,提示客戶端程序員的信息不須要讓客戶知道的。
2. 提示用戶的信息文字很友好,客戶不須要專業基礎一看就知道是什麼,提示客戶端程序員的信息則很專業,例如告訴客戶端少傳了哪一個參數?哪一個參數有問題等等。
(7)在線api測試文檔
咱們網站的api在線測試文檔,是使用既是一份在線api文檔,也是一個在線測試工具,極大方便溝通和測試。每次客戶端程序員以爲某個api有什麼問題,咱們就是這個在線工具上討論溝通的。客戶端程序員最喜歡這個玩意了^-^。
這個api在線測試文檔,是使用了Swagger-UI搭建的。Swagger-UI簡單而一目瞭然。它可以純碎的基於html+javascript實現,只要稍微整合一下便能成爲方便的API在線測試工具。項目的設計架構中一直提倡使用TDD(測試驅動)原則來開發,swagger-ui在這方面更是能提供很大幫助。
下面是用Swagger-UI搭建的api文檔中的一個api的例子,可看到,整個api的提交方式,做用,參數都很是清晰明瞭。
當按了「測試」,就以post方式調用這個api,返回的結果以下:
全部的返回結果,一目瞭然,cool!!!
api返回的數據,是以json格式返回的。用json格式,最省流量,並且幾乎每種計算機語言都支持json格式。用xml的話,太耗費流量了,並且冗餘數據多,不適合移動端。
在"app後端"的qq羣,有個app創始人使用了這個api在線測試文檔後贊不決口,稱讚雖然前期的搭建須要花一段時間,但極大提升了app先後端工做的效率。之後有小夥伴問相關的問題,他都強烈推薦這個Swagger-UI。
(8)在app啓動時,調用一個初始化api獲取必要的信息
經過這個初始化api,獲取一下必要的信息,例如,最新的app版本。當發現本地app的版本已經低於最新的app版本,可提示用戶更新。固然了,這個提示版本更新的功能不少第三方sdk都提供。
3.如何處理api的版本升級
當app作了大改版後,可能會出現一個問題,發現如今的api已經不適了,就考慮到api的升級,同時爲了兼容已經發布的app,原來的api必需要保留。爲了不同一個app中調用不一樣版本的api,通常就會所有升級api的版本,例如:原來的是「test.com/v1/statuses/destroy」,升級爲「test.com/v2/statuses/destroy」。
在api的版本升級時,須要注意如下2點:
1. v2版本的api的controller必需要繼承v1版的controller,v2版本的api只重寫須要改動的api。
2. 在線api測試文檔中詳細標明返回內容,已做對比,方便客戶端人員的調試。