標籤:個數 進入 array 詳細 友好 也會 qq群 不用 驅動
部落格:44037011
app和後端的互動,一般都是通過後端提供的api實現。api的設計,估計很多剛進入app後端的小夥伴會一無頭緒,不知道怎麼入門。下面根據自己3年的app後端經驗,總結出下幾個api設計原則,給小夥伴參考。
1. 什麼是api?
這個問題在以前發表的文章“7.app和app後端的通訊”中其實已經回答了,這裡再重複一次。
相信大家都用過銀行的櫃員機(ATM)的查詢餘額,轉帳,取款等操作。
當在櫃員機取款的時候,我們輸入要取款的金額,隔一會錢就出來了,如果因為有什麼問題不能取款(例如超過取款金額的限制),螢幕上也會顯示出錯誤的資訊。
在整個過程中,我們只要輸入金額,獲得結果(取款成功或不成功),就行了,至於櫃員機內部是怎麼處理,我們不需要理會。
櫃員機這種把內部的處理遮蔽的做法極大方便了我們的使用。
同樣的,在後端,也只提供了一系列的功能給app使用,這系列的功能以api的形式提供。
api的定義:API(Application Programming Interface,API)是一些預先定義的函數,目的是提供應用程式與開發人員基於某軟體或硬體得以訪問一組常式的能力,而又無需訪問源碼,或理解內部工作機制的細節。
當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測試文檔中詳細標明返回內容,已作對比,方便用戶端人員的調試。
app後端api設計【轉】