1. 程式人生 > 其它 >一個“爆款”成功的API,都離不開這8條設計準則

一個“爆款”成功的API,都離不開這8條設計準則

我已經看過很多API設計相關的文章和優秀的REST API設計教程。他們通常討論的是適當的編碼技巧和如何在給定的語言中暴露介面。儘管那些是很有用也是很需要的,但是他們經常忽略了一些能讓API工作得更好的想法。

1. 相容性與跨平臺

這裡就要求讓API設計得是可預測的。按照這種方式寫出所有介面和介面所需要的引數。現在就要確保命名是一致的,介面所需的引數順序也是一致的。你現在應該有products,orders和customers的資料吧?,它們應該都存在含有id和name的表中。那麼不要讓一個介面僅傳ID而另一個僅傳name還有的兩個都要傳。也不要讓一個介面按照/product/ID傳參而另一個介面按/ID/customer

這樣傳參。因為作為一個API的使用者我希望以相同的方式訪問兩個不同的資源。

另外一個保證相容性的技巧是觀察你的引數值型別。如果一個介面的ID引數求為整型,那麼不要讓另一個介面的ID引數為字串型。因為作為一個API的使用者我不想去猜每個介面的每個引數值型別。

除了需要考慮你的介面如何訪問資料以外,你也應該好好想一下你的API如何返回資料以及返回資料格式的統一性。目前在我最近使用的API中就存在一個很大的問題。當開發中用到一個返回資料的介面時,我很驚奇的發現返回結果裡面的每個元素都本該都含有一個特定的屬性。然而結果是一些元素有那個屬性而另一些卻沒有。我寧願那個屬性是一個空值也不願意看到完全沒有那個屬性。原因是如果我遍歷每個元素來尋找這個屬性,我希望至少能找到它,即使它沒有值。然而現在就像是從資料庫查出幾條記錄然後發現有幾條資料裡面沒有某個欄位而其他幾條卻有。然後這就開始讓你懷疑查詢出來的結果併產生了一個疑問“那些消失的屬性是被我弄丟的嗎?”

2.簡單明瞭

你應該有過打電話給別人讓他幫你做一件事時對方很爽快地回覆一個“好!”的經歷吧?通常這時你會躊躇一下然後去問“你確定會幫我做吧?”。優秀的API不僅會做你想要它執行的操作而且還會額外返回有關它剛執行的操作的相關資訊。如果你的某個API是負責建立一個product的,那麼就讓它執行完建立操作後返回一些有關剛剛建立的product的相關資訊,而不是去要求客戶端再去傳送一個請求來獲取你剛剛建立的product的相關資訊。因為那樣就顯得你很沒腦子。但是你還是會驚奇地發現有很多API執行完操作後只返回一點像200 OK那樣的資訊。所以只需要讓你的API給客戶端返回一些有用而且明顯需要的關於剛剛執行的操作的相關資訊就可以讓它變得直爽。

3. 讓API很容易去完成一個請求

你通常是不是更願意這麼做:讓別人開車載你去幹洗店或者直接讓別人開車去幹洗店,下車後開啟店門走進乾洗店,找店員拿完你的衣服然後離開乾洗店再開車回到你這兒。所以你的API不要讓客戶端呼叫多次只是為了去做一個通常都需要執行的子任務!你可以通過提供預設引數值而且允許客戶端可以根據特定請求去覆蓋你的任意一個預設引數值來解決這個問題。

我目前一直在用的一個API就讓我感到很痛苦而且還很費事時。它本應該設計成只需一個簡單的請求就可以建立一個預定產品,而且耗時只需要耗時300-500ms,然而它卻設計成需要你去傳送7個往返都需要300-500ms的請求。這便使得本來只要300-500ms的程序要花費好幾秒!而且這些增加的時間都會被使用這個API預定產品的消費者注意到。

4. 響應迅速

這條建議是建立在前幾條之上的。如果請求的操作處理成功了,返回了一個成功像200 OK這樣的狀態碼。如果請求的操作處理失敗了,給出適當的像404500等這樣的狀態碼來表明處理失敗了。因為我們想要實現的是客戶端在使用API時首先能根據返回的狀態碼來決定接來下如何去處理具體的返回內容。我現在用的一個API確實是會返回給我一個200 OK的狀態碼但是他緊接的返回內容是一個處理失敗的報錯資訊。以至於,儘管我知道請求成功了但是我不得不去檢查我請求的操作是否真的處理成功了。所以請不要像這樣設計。你只需要在一開始就返回一個恰當的狀態碼後接下來就知道該如何處理了。

5. 多考慮效能問題

優秀的API都是能夠很快地處理大量的請求。你處理完一個請求後取得的結果可以直接返回給那些完全相同的請求而不需要重複處理。換句話說,你應該儘可能地使用像伺服器端快取那樣的技術。如果一個使用者請求product1的資訊,然後過幾秒又有另一個人也請求product1的資訊,這時你就可以將返回給第一次請求的結果同樣返回給後來的請求。不需要再次查詢僅僅是為了返回你剛才已經查出來過的相同資料。同時也要確保給快取一個過期時間以免讓快取內容變得過時。

Chargify在這方面就做得很好。我向他們請求一個預定產品時他們能夠在200ms左右回覆我結果。這是相當快的。而且如果我在一分鐘之後再次請求這個預定產品時他們會在97ms內返回給我同樣的結果。同時要知道並不是所有的介面和查詢都可以像那樣設計,但是如果你的資料是不變的或者不經常變,那麼就要考慮在你的API使用快取來加速請求的處理。你的客戶端將會因為這愛上你。如果客戶端將響應結果快取在它們自己的客戶端快取裡那就能讓他們更滿意了。

6. 用帶有SSL的Basic Auth

你現在有很多種方法來保障API的安全性,例如:Basic Auth(基本認證),Digest Auth(摘要認證 ),OAuth(開放認證),no auth等。當你考慮用哪種方法的時候需要考慮的是認證方法的效能和易用性(像上面的建議5和建議3所說的)。如果你用了SSL的話,我建議你採用Basic Auth方法,因為它很容易部署,而且只需要請求一次而不需要多次(Digest Auth通常都需要至少兩次以上的請求才能完成認證)所以效能相對來說也會高些。顯然如果你不使用SSL,那麼就建議你用Digest Auth或者OAuth等其他的安全的認證方法。

7. 給你的API制定版本

恭喜你!你的API設計的很成功而且在被很多使用者使用。現在他們的很多產品和專案開始依賴於你的API。但是你現在需要考慮的是如何在不影響他們使用的情況下去更新你的API。如果你能讓不同版本的API相互獨立開來,我建議你將版本號作為一個引數或者API命名的一部分。例如:GET /v1/product/id或者 GET /v2/product/id 或者 GET /product/id?v=1。你也可以選擇將版本號部署進HTTP請求頭,但是無論你採用哪種方法都要確保所有的版本都採用同一種方法。

通過將API用版本號區分開可以讓使用者一直使用某個版本的API直到恰當的時候再遷移到新版的API。你也可以隨時關掉某個版本API而不需要對現有版本的API做任何處理。

8. 使用JSON而不要使用XML

第8條建議是根據我個人偏好提出的。我工作到現在用過很多API,JSON格式和XML格式都有。我會告訴你我覺得JSON格式的更好用。JSON格式通常是更為簡潔的(以至於傳輸的資料量更小),也更容易展現複雜的物件(精確)而且能執行得像其他格式一樣好(以至於現在每個人都在用JSON)。XML通常都是很冗餘的,還不容易展現複雜的元素而且還需要一個DTD來驗證它。所以我將會用JSON格式,如果你想用XML的話那就隨便吧。不管怎樣,我認為只要你開始用JSON你就會很明顯得發現XML的缺點。

總結

API正在改變我們和整合系統的互動方式,所以它的質量就變得尤為重要了。如果你設計API時考慮到了終端使用者,那麼你就要考慮如何讓他們更容易使用,這樣你的API才會變得更成功。如果使用者用別的API也能完成你的API能完成的事,但是別人的API更容易使用、響應速度更快,使用者自然就會去用別人的而不是你的。

所以不要犯這些嚴重的錯誤:傳參格式不一致,只做簡單的響應,對剛剛處理的結果隻字不提(不健談)而且響應得很慢。那將毀了你整個API。