如何設計優雅的API[轉]

一、設計優美的 Web API

設計優美的 Web API 的重要性



本文的主題是討論如何設計優美的 Web API 。這裡“優美”一詞的含義同 “代碼之美”中“美”的含義相同,指的是進行了周密的斟酌、淺顯易懂的整理,並 剔除了無用之處等,它體現了完成度的高低。但是,這裡不免要問為什麼 Web API非要設計得優美不可呢?簡而言之,就好比問為什麼代碼非要寫得優美一樣,每個編寫代碼的開發人員估計都有各自的答案,接下來讓我們就這個話題進行深入的探究。

首先列舉一下 Web API 需要設計得優美的幾個理由:

  • 設計優美的 Web API 易於使用
  • 設計優美的 Web API 便於更改
  • 設計優美的 Web API 健壯性好
  • 設計優美的 Web API 不怕公之於眾

下面讓我們逐一闡述。

設計優美的 Web API 易於使用

首先,很多情況下設計 Web API 並非只是為了自己使用。且不說廣泛公開的Web API,即使是某些移動應用的 API,服務器端和客戶端分別由不同開發人員負 責的情況也很多。在這種情況下,根據 Web API 設計的好壞,API 的易用性也會大 相徑庭,而這對開發週期、開發人員在開發期間所承受的壓力大小等都會帶來巨大影響。

設計 API 的目的原本是讓更多的用戶能夠簡單地使用,如果公開了難以使用的API,那麼公開 API 的意義也就不大了。

設計優美的 Web API 便於更改

Web 服務以及 Web 系統幾乎是每時每刻都在變化的,也就是說,保持公開時的 狀態連續使用兩三年的情況非常罕見。因此,當我們的服務發生變化時,作為其接口的 API 顯然也不得不隨之改變。

但是,公開的 API 在很多情況下會被與自己無關的第三方調用,如果這時突然 變更 API 的設計規範,很有可能造成這些第三方開發的系統、服務等一下子變得不可用。這無疑是 API 提供者需要極力避免的情況。

移動應用的情況下,什麼時候更新應用往往由用戶自己掌控,即使將客戶端應 用更新到最新版本,也依然存在使用老版本的用戶。此時如果突然變更 API 的設計規範,就會使得老版本的應用突然無法使用。而“設計優美的 API”的含義中就包括了更改 API 時儘量不影響正在使用的用戶 這一層意思。

設計優美的 Web API 健壯性好

同普通的 Web 站點一樣,Web API 在很多情況下也通過網絡提供服務,由於誰 都能夠訪問 Web API,因此必然會涉及安全問題。由於 Web API 同 Web 站點一樣使 用了 HTTP 協議,因此會面臨同 Web 站點一樣的安全問題,除此之外,開發人員還 需考慮 API 特有的安全問題。只有充分應對了以上這些問題,才能稱得上是設計優美的 API。

設計優美的 Web API 不怕公之於眾

Web API 同一般的 Web 站點、Web 服務不同,主要面向開發人員。眾所周知, 開發人員往往喜歡評價其他開發人員寫的代碼、接口等成果,因此,如果公開的API 在其他開發人員眼中顯得醜陋、沒有美感的話,該服務提供者的技術水平也會受到質疑。

當然,如果所提供的服務魅力無窮,或者讓人不得不使用的話,即使 API 設計 得再醜,可能也會有人使用,但醜陋的 API 設計會給其他不相關的地方帶來影響。 例如優秀的開發人員一般不太願意加入技術水平較差的公司或者團隊,所以很有可能只是因為 API 設計得差而導致公司無法招到優秀的技術人員。優秀的服務背後一般都需要有出色的技術團隊支撐(但這並不意味著擁有了出色的技術團隊就一定會有優秀的服務),而如果沒有出色的技術團隊,長此以往就可能導致公司發展缺乏後勁,始終無法創造出優秀的服務。

二、開發方便更改設計的 Web API

Web API 和普通的 Web 服務一樣,並不是說發佈後所有工作便就此結束了,而 是必須始終保持公開狀態,否則就沒有意義。在持續公開API 的過程中,我們可能會遇到發佈之初沒有想到的 API 使用方法,或不得不為其增添新的功能等,有時甚至還會因為某些原因而不得不終止公開API。接下來我們就來討論一下與 API 更改及廢除相關的各種問題。

方便更改設計的重要性

Web API 承擔著應用程序接口的角色。應用發佈後,往往難以保持一成不變。 隨著時間的推移,應用會根據各種情況不停地發生變更,比如強化某些功能、修正bug,或者廢除某些功能等。這時,Web API 作為應用面向其他應用的接口,有時也 必須隨之進行相應的變更。當然,如果在線服務只是外觀上發生少許變化,或者變 化只對內容有影響但沒有影響數據格式,也就沒有必要去更新 API 了。但如果是數 據格式發生了變化,或者需要在信息檢索時添加新的查詢參數等,就必須對 API 進 行相應的變更。

比如,當以文本形式返回的數據內容變得更加詳細時,或由於內部算法的更新 使得搜索精度提高時,雖然訪問 API 得到的數據內容發生了變化(大多數情況下會 有所改善),但數據格式卻沒有改變,這時就沒有必要更改 API 的設計規範了。在 Web 服務運營的過程中,類似這種數據格式沒有變化但內容卻有所改善的情形每天都在上演。

另一方面,在數據格式自身發生變化時,比如原本以數值形式公開的 ID 信息變為了字符串形式,廢棄了以往返回數據中包含的“關聯信息推薦”,原來分別輸出年 月日信息的方式變成了合併為一個整體輸出等,API 響應數據的格式就一定會更改。 另外,在獲取數據時,如果從使用字符串指定分類的方式變成了使用 ID 來指定,或 者在搜索時增加了性別條件,亦或用戶註冊時的郵箱地址變成了可選項等,這時就 必須更改 API 的請求參數。如果發現 API 的設計存在安全漏洞等致命問題,或許還 需要修改 API 的內容。

但是,類似這種 API 的變更非常棘手,因為這會給使用 API 的外部系統或服務 帶來巨大影響,而且很難評估影響究竟有多大。

通過版本信息來管理 API

最容易想到的方法是儘量不去修改已公開發布的 API,但這樣就很難進行在線 服務的改善工作,所以實際上這一方法是行不通的。新 API 只需通過某種新的訪問 方式公開即可,比如使用不同的端點,或使用添加了其他參數的 URI 等。

換言之,對於使用舊方式訪問的客戶端,和之前一樣發送數據即可;而對於使 用新方式訪問的客戶端,則要返回更新後的數據。也就是說,我們可以同時提供多個版本的 API。

如圖:新 API 以新形式對外發布,舊 API 依然予以保留

讓新舊兩個版本以上的 API 共存的方法有很多,其中最容易理解的實現方式是使用完全不同的 URI 來發布,如下所示:

❖舊的 URI

http://api.example.com/users/123

❖新的 URI

http://newapi.example.com/users/123

如此一來,那些使用早期發佈的舊版本 API 的用戶就可以忽視 API 的更新,從 而繼續使用之前版本的 API,並在合適的時機向新版本遷移,而新用戶則可以從一 開始就直接使用新版本的 API。以上示例作為例子來說非常容易理解,但如果是實際的 URI,這樣的實現方式則難以奏效(只能作為例子展示),而且這裡使用 new 來命名也很有問題。因為只有在剛發佈的階段才能稱為“新”,倘若未來出現了更新的 版本,那麼又該如何命名呢?日本有很多以“新”來命名的案例,如新快速、新千歲 機場等,雖然它們就現在而言已經不新了,但名稱裡依然帶有“新”字。API 的情況 也同樣如此,當需要更新其版本時,該使用怎樣的 URI 來標識最新版本的 API 呢?

和軟件的版本管理一樣,我們也可以使用版本信息來對 API 的版本進行管理, 這是最容易理解的一種方式。當客戶端訪問 API 時,服務器端通過某種方式告知其API 的版本信息,就可以做到讓多個版本的 API 共存。如此一來,版本 2 新於版本 1就不言自明瞭。當後續又有新版本發佈時,只需使用版本 3 來公開即可。

在 URI 中嵌入版本編號

首先看一個在 URI 中嵌入版本編號的範例。

❖ Tumblr

http://api.tumblr.com/v2/blog/good.tumblr.com/info

上面是 Tumblr 的 API。該 API 的路徑開頭有一個 v2,這便是 API 的版本編號,從中不難得知該 API 是版本 2。Tumblr 曾 發佈過版本 1 的 API (http://www.tumblr.com/docs/en/) 但該版本的 API 現在已 被廢除

❖ Tumblr 版本 1

http://www.davidslog.com/api/read

我們發現版本 1 的 URI 裡並沒有添加版本編號。雖然 Tumblr 在 2012 年公開的 版本 2 的 API 中使用了在 URI 裡嵌入版本編號的方式,但早期發佈的版本 1 並沒有 遵循這一慣例。在公開發布的 API 中,類似 Tumblr 這樣從某個版本開始引入版本 編號的情況並不少見,比如 Twitter 的 API 從版本 1.0 升級至 1.1 時,就在新版本的URI 裡添加了版本編號(下表)。另外,在 API 升級後,1.1 版本的 API 所使用的 端點也不同於之前的版本 1(舊版本 API 端點在短期內仍可繼續使用)。

在 URI 路徑的開頭嵌入 API 版本編號這一方法最為常見,也最為易懂。

但是在具體處理時,Twitter 和 Tumblr 則略有不同:Tumblr 在版本信息前添加 了字母 v,並使用了 1、2 這樣的主版本(Major Version)編號;而 Twitter 卻使用了 類似 1.1 這樣包含次版本(Minor Version)編號的版本命名方式。

那麼哪種方式最易懂呢?讓我們來看一下其他幾個 API 的示例(如下表)。

可以發現,根據為 API 添加版本編號時是否使用字母 v,可以將以上示例大致 分為兩類。具體哪種方式更好只是個人偏好的問題,筆者個人比較喜歡添加字母 v的方式。因為 v 表示版本,添加 v 之後可以讓人一目瞭然,易於理解。還有些服務 採用了特立獨行的方式來描述 API 的版本信息,如 Gnavi、CrunchBase 等。雖然這 麼做問題不大,但如果沒有特殊的偏好,則沒有必要使用這樣的方式

終止提供 API

通過版本來區分 API,這樣在提供新版本 API 時就不會給那些依然在使用舊版 本的用戶帶來巨大影響,不過持續維護多個版本無疑會增加整個服務的運營成本。 即使你已決定不再繼續更新舊版本的 API,一旦發現安全問題等,也不得不進行更新。 另外,隨著後端功能的更新(如數據庫 schema 的更改等),為了保持前端接口不變, 有時也不得不更新與之相關的 API 代碼。

如前所述,為了減輕維護負擔,應儘可能地不去頻繁升級 API 版本,而是要在 確保向下兼容的同時進行相應的更改。但隨著在線服務長年累月地運營,難以保持 向下兼容的更改會越來越多。考慮到成本問題,繼續維護和支持多個版本的 API 是 不現實的,這種情況下就需要考慮選擇適當時機去廢除舊版本的 API。

另外,當舊版本的 API 在結構上存在安全隱患(如個人信息沒有經過加密直接 被髮送、能夠獲取他人的信息等)等問題時,有時也需要儘快結束舊版本 API 的公開。

當需要終止對外提供舊版本的 API 時,如果不進行任何通告就突然終止,無疑 會導致依然在用舊版本 API 的用戶忽然變得無法訪問,進一步將會導致應用程序出 錯或部分 Web 頁面(或全部)無法顯示等問題,後果非常嚴重。

因此,在終止 API 服務時,尤其是在終止那些已被廣泛使用的 API 時,我們需 要事先公佈預計終止的時間等信息,以便用戶在此之前採取應對措施。這項工程非 常複雜,但對 API 的公開及運營來說非常重要。

案例學習:Twitter 廢除舊版本的 API

Twitter 於 2012 年公開發布了版本 1.1 的 API,與此同時開始了廢除版本 1.0 的 工作。Twitter 廢除舊版本 API 的做法很有參考價值,下面就讓我們按時間順序來回 顧一下整個事件的經過。

首先,Twitter 在 2012 年 8 月宣佈即將發佈版本 1.1 的 API。當時 Twitter 稱會 在幾周後發佈版本 1.1,並在 6 個月內廢除版本 1.0。2012 年 9 月,版本 1.1 的 API正式發佈。2012 年 10 月,Twitter 更新了版本 1.0 的端點信息,要求用戶訪問時必 須使用嵌入了版本編號的新 URI,不然將無法正確訪問。

2013 年 3 月,Twitter 舉行了名為 Blackout Test 的測試,暫停提供版本 1.0 的API,使用戶無法訪問。這項測試陸續進行了多次,直到舊版本的 API 被廢除。

Twitter 於 2013 年 3 月宣佈將在 5 月 7 日正式廢除版本 1.0 的 API ,但隨後因 為再次追加了 Blackout Test,廢除日期延遲到了 6 月 11 日 。最終 Twitter 於 6 月 11日廢除了版本 1.0。

由於 Twitter 用戶眾多,在正式廢除版本 1.0 的 API 之前,很多博客及新聞媒體 都對此進行了相關報道,可謂做到了廣而告之。另外,像這種持續通告及 Blackout Test 的做法等都非常具有參考價值。

三、設計優雅API的一些經驗要點總結

  • 如果尚未公開 Web API,則應立刻考慮公開。
  • 設計優美的 Web API。
  • 不用過分拘泥於 REST 一詞。
  • 最大限度地減少 API 版本的更新頻率,注意向下兼容性。
  • 在 URI 中嵌入 API 版本的主版本編號。
  • 停止提供 API 服務時不能立刻終止,至少需要繼續公開 6 個月。
  • 最大程度地利用 HTTP 協議規範,最小程度地使用私有規範。
  • 使用合適的狀態碼。
  • 返回恰當的、儘可能通用的媒體類型。
  • 返回便於客戶端執行恰當的緩存的信息。
  • 使用 JSON 或者和目的一致的數據格式。
  • 不要進行不必要的封裝。
  • 響應數據儘可能使用扁平化結構。
  • 各個數據的名稱應簡潔易懂,並恰當地使用單複數。
  • 錯誤格式應統一,使客戶端能夠機械地理解錯誤的詳細信息
  • 設計容易記憶、功能一目瞭然的端點。
  • 使用合適的 HTTP 方法。
  • 選擇合適的英語單詞,注意單詞的單複數形式。
  • 使用 OAuth 2.0 進行認證。


原文地址:https://www.juhe.cn/news/index/id/2318


分享到:


相關文章: