api怎么写_月薪几十K 的人是怎么设计REST API
前言
作為一名優(yōu)秀的后端程序員,你照著產(chǎn)品需求設(shè)計(jì)好了模型,設(shè)計(jì)好了關(guān)聯(lián)關(guān)系。
把這些模型和關(guān)系一再打磨了一番之后,你想是時(shí)候把API設(shè)計(jì)出來(lái),與前端溝通了。
這時(shí)候問(wèn)題來(lái)了:
一旦 API 進(jìn)入前端 APP 代碼,或者是被你的顧客廣泛使用的話,再來(lái)大改就非常麻煩了。比如說(shuō),如果 APP 版本 1.0 用了一個(gè)接口 A,這個(gè)接口 A 如果要進(jìn)行大改,那么必須將 A 維持至所有用戶升級(jí)過(guò) APP 1.0 后。
那么怎么樣避免 API 發(fā)布之后大改呢?有沒(méi)有一些提前可以注意到的設(shè)計(jì)準(zhǔn)則可以幫我們避開 API 設(shè)計(jì)中的各種坑?
答案是有的。網(wǎng)上充滿了各種對(duì) API 設(shè)計(jì)的建議,而這篇文章里我們結(jié)合卡拉搜索設(shè)計(jì) API 的經(jīng)驗(yàn),把? REST API 的最佳實(shí)踐和常見的坑都總結(jié)出來(lái),做成一個(gè)教程,希望可以在幫到正在設(shè)計(jì)/使用 API 的你。
REST API 是什么 - 程序員與服務(wù)之間溝通的語(yǔ)言
任何語(yǔ)言的本質(zhì)都是一套規(guī)則的合集。比如說(shuō),中文里要求句子要有主謂賓,而作為母語(yǔ)為中文的我們,一旦有人說(shuō)了一句缺少主語(yǔ)的話,我們會(huì)直覺性地感覺很奇怪。
比如說(shuō),如果有人對(duì)你說(shuō)“是一個(gè)神人”。
你會(huì)直覺地問(wèn):究竟誰(shuí)是一個(gè)神人?
同樣的,在各個(gè)程序的溝通中,或者各個(gè)服務(wù)的溝通中,我們也需要類似“語(yǔ)言”的東西,讓我們可以不需要太多的上下文,就可以前端理解后端、后端也理解前端。
設(shè)想一下,有多少次你跟前端一起需要前后端聯(lián)調(diào)?有多少次前端覺得你定義的 API 不夠方便直觀,一定要你多返回一個(gè)參數(shù)或者改一下端點(diǎn)路徑?
其實(shí)本質(zhì)上,你們?cè)?strong>聯(lián)調(diào)時(shí)就是在嘗試設(shè)計(jì)一個(gè)"語(yǔ)言",以方便互相可以更容易地理解對(duì)方。
比如說(shuō),后端會(huì)要求前端說(shuō),你調(diào)用POST /user/abc就可以創(chuàng)建一個(gè)名為 abc用戶了。
短線來(lái)講這當(dāng)然沒(méi)問(wèn)題,你們可以幾乎任意地定義 API 端點(diǎn),任意地調(diào)整傳遞的參數(shù)。但是一旦項(xiàng)目開始變復(fù)雜,問(wèn)題就開始出現(xiàn)了。
首先大家有不同的經(jīng)驗(yàn)和喜好,對(duì) API 的定義可能千差萬(wàn)別,所謂眾口難調(diào)
系統(tǒng)開始復(fù)雜后,各個(gè)系統(tǒng)之間的 API 因?yàn)槎x的人的不同,會(huì)開始出現(xiàn)不一致,導(dǎo)致每個(gè)端口調(diào)用前需要詳細(xì)閱讀文檔(如果有的話)或者與 API 設(shè)計(jì)者無(wú)窮無(wú)盡地討論和會(huì)議
如果你的 API 是面向客戶的,比如如果你是一家軟件服務(wù)公司,那么你自定義的 API 會(huì)增加客戶接入的成本
等等等等
因此,要是有一套人類通用的"語(yǔ)言“或者”規(guī)范“,來(lái)指導(dǎo)大家定義 API 的方式,那樣該多好?
REST API 就是這樣一種規(guī)范,它是目前整個(gè)互聯(lián)網(wǎng)應(yīng)用最廣泛的 API 規(guī)范。有意思的是,REST是由它的提出者 Roy Fielding 在他讀書期間,寫的博士論文里提出的。
總結(jié)一下,REST API 有一套 API 設(shè)計(jì)的準(zhǔn)則,它規(guī)范了 API 設(shè)計(jì)的框架,使得服務(wù)間、程序員之間有一個(gè)通用的溝通語(yǔ)言。
REST API 內(nèi)具體規(guī)定了什么
REST API 規(guī)范了 API 設(shè)計(jì)的兩大核心原則
API應(yīng)該作用于 Resource(資源)上
對(duì)資源的操作應(yīng)使用對(duì)應(yīng)語(yǔ)義的幾種操作,包括:GET, POST, PUT, PATCH, DELETE
我們來(lái)詳細(xì)解釋一下這兩點(diǎn)
什么是 REST API 里的 Resource(即資源)
這里的資源是指你的 API 用戶可操作的邏輯對(duì)象,舉個(gè)例子
如果你的 API 中允許調(diào)用者對(duì)用戶進(jìn)行操作,比如說(shuō)用戶注冊(cè),那么 API 類似于POST /users在這里,資源即為 users。在很多情況下,API 中的資源與你的數(shù)據(jù)模型(也就是數(shù)據(jù)庫(kù)的表)是一一對(duì)應(yīng)的。當(dāng)然也有例外情況,比如說(shuō)你的數(shù)據(jù)庫(kù)中存有用戶,但是你現(xiàn)在想要讓調(diào)用者可以創(chuàng)建"管理員",那么 API 可能是POST /admins然而,你的表中并沒(méi)有admins這個(gè)表,而是否是 admin 是 Users 表中的一個(gè)屬性,比如role=admin。
請(qǐng)注意,REST API中的資源一定需要是名詞,即一定是一個(gè)實(shí)在存在的概念比如 用戶, 帳號(hào), 車票等,或一個(gè)抽象的概念比如 權(quán)限 等。如果你需要提供一個(gè)創(chuàng)建某種資源的API接口,上述則可以表述為POST /indexes,POST /accounts,POST /docs等等。
通常對(duì)于資源的命名,我們建議統(tǒng)一命名為為英文的復(fù)數(shù)。比如說(shuō) users 而不是 user。同時(shí)請(qǐng)注意保持一致性,在所有地方用一樣的復(fù)數(shù)。
什么是 REST API 里的操作
一旦你定義了資源,接下來(lái)你需要定義允許調(diào)用者在這些資源上做什么操作。
比如說(shuō),以攜程搶車票網(wǎng)站為例,我們可能允許調(diào)用者進(jìn)行以下操作
GET /tickets - 列出所有車票
GET /tickets/9839 - 列出 id 為 9839 這張車票的信息
POST /tickets?- 創(chuàng)建一張車票
PUT /tickets/9839?- 更新 9839 這張車票的信息
PATCH /tickets/9839?- 部分修改 9839 這張車票的信息,比如只修改車票價(jià)格
DELETE /tickets/9839?- 刪掉 9839 這張車票
請(qǐng)注意,到這里為止,你應(yīng)該可以總結(jié)出來(lái)REST的大致設(shè)計(jì)思路了。它由兩部分組成,第一部分是操作,第二部分是可操作的資源。比如上文中的 GET /tickets,操作是 GET,可操作的資源是車票。
那么讀到這里,如果你嚴(yán)格遵循了REST的設(shè)計(jì)準(zhǔn)則,以及你的調(diào)用者也了解 REST 的準(zhǔn)則的話,那么對(duì)于很多 API 調(diào)用,你們不用再參考互相寫的文檔了。如果需要調(diào)用一張車票的信息,你的調(diào)用者自然會(huì)知道應(yīng)該用GET去查看一個(gè)車票資源的信息,即 GET /tickets/:ticketId。這樣就極大降低了溝通成本和出錯(cuò)成本,提升效率。
如何在 API 中表示實(shí)體(數(shù)據(jù)庫(kù)表)間關(guān)系
在后端設(shè)計(jì)中,有的資源邏輯上無(wú)法獨(dú)立存在。比如說(shuō),在卡拉搜索的例子里,用戶的文檔是無(wú)法獨(dú)立于索引存在的。那么自然地,我們用GET /indexes/index_abc/docs/1來(lái)表達(dá)獲取索引 index_abc 中編號(hào)為 1?的文檔。因此,對(duì)于所有資源需要依賴于另一個(gè)資源存在時(shí),我們就按順序在端點(diǎn)中將資源列出來(lái)。對(duì)于卡拉搜索中,索引和文檔的關(guān)系,我們有以下接口
GET /indexes/index_abc/docs/1 - 獲取index id為index_abc下的id為 1的文檔
GET /indexes/index_abc/docs?- 獲取index id為 index_abc 下的所有文檔
POST /indexes/index_abc/docs? - 在index id為 index_abc 的索引中,添加文檔...
如果一個(gè)資源可以獨(dú)立于另一個(gè)資源存在,并且你期望你的API調(diào)用者頻繁調(diào)用,那么可以考慮直接提供子端點(diǎn)。比如說(shuō),如果一個(gè)寵物店主人和寵物信息分別都常常被同時(shí)調(diào)用,那么你可以考慮
GET /owners/ - 獲取所有主人信息GET /owners/1/pets/ 獲取 id 為 1 的主人的所有寵物
GET /pets/ - 獲取所有寵物信息(寵物店所有寵物)
GET /pets/13 - 直接獲取 id 為 13 的寵物
REST API中如何表示一個(gè)動(dòng)作
有時(shí)候,當(dāng)我們?cè)噲D表達(dá)一些接口時(shí),會(huì)發(fā)現(xiàn)REST的準(zhǔn)則很難直接應(yīng)用。比如說(shuō),當(dāng)你需要一個(gè)接口讓用戶登錄時(shí)POST /users/signin但要注意,這里的 signin 即登錄,是一個(gè)動(dòng)詞。這里是采用REST準(zhǔn)則時(shí)需要考慮的地方,你有三個(gè)選擇
如果你希望嚴(yán)格地遵循 REST 原則,那么你需要找一個(gè)替代動(dòng)詞的名詞。比如說(shuō),這里的signin可以替換為login。或者,如果你是以 token 密鑰的方式登錄的話,也許可以改為POST /users/token,即創(chuàng)建一個(gè) user token(也就是登錄了)
?在某些實(shí)在困難的地方,放棄嚴(yán)格的REST原則
參考一些成功的 REST API 并尋找類似的 API,參考他們的命名設(shè)計(jì)
對(duì)于3,我強(qiáng)烈建議你參考 github 的 API,原因不光是其極為規(guī)范,還有它覆蓋了極多的 API 調(diào)用的情景,因此大概率你可以找到個(gè)類似的命名參考。
比如說(shuō),在 github 上,如果讓你來(lái)設(shè)計(jì)加星這個(gè)操作,你會(huì)把端點(diǎn)被設(shè)計(jì)成什么樣?
Github把加星端點(diǎn)設(shè)計(jì)為PUT /gists/:id/star,把取消加星設(shè)計(jì)為DELETE /gitsts/:id/star。這樣就完美地遵循了 REST 名詞作為資源的準(zhǔn)則,把動(dòng)詞"加星“完美地用PUT/DELETE兩個(gè)操作,清晰地表達(dá)了出來(lái)。
REST API 設(shè)計(jì)常見問(wèn)題和建議
上面我們描述了 REST 設(shè)計(jì)的準(zhǔn)則,而在準(zhǔn)則中并不包括其它”最佳實(shí)踐“。
這里的最佳實(shí)踐,其實(shí)并沒(méi)有什么客觀標(biāo)準(zhǔn),只是軟件工程和架構(gòu)經(jīng)過(guò)多年的發(fā)展,REST API ?的設(shè)計(jì)也從十幾年前簡(jiǎn)單的web 應(yīng)用,到應(yīng)用到現(xiàn)在越來(lái)越復(fù)雜企業(yè)級(jí)軟件中。因此,如果你剛剛開始學(xué)習(xí) REST API 的設(shè)計(jì),參考這些實(shí)踐經(jīng)驗(yàn)將會(huì)有非常大的幫助,可以幫你少走不少繞路。
REST API 如何區(qū)分版本
在設(shè)計(jì) REST API 時(shí),你應(yīng)該時(shí)刻準(zhǔn)備好不斷更新 API。想要把 API穩(wěn)定后再一次發(fā)布多數(shù)情況下是不實(shí)際的——老板要催進(jìn)度,用戶要催功能。因此,在設(shè)計(jì) API 的時(shí)候就應(yīng)該把支持 API 改動(dòng)設(shè)計(jì)到API本身中。
多數(shù)情況下,在一版 API 已經(jīng)成熟的前提下,可以提前發(fā)布,同時(shí)開始進(jìn)行下一版的開發(fā)。而你只需要在URL中區(qū)分好 API 的版本即可。
比如說(shuō),如果在大致將 v1 開發(fā)完畢后,v1 前綴的 API 就應(yīng)該穩(wěn)定下來(lái),所有的改動(dòng)進(jìn)入 v2。同時(shí)你應(yīng)該開始通知所有使用 v1 的用戶,給他們幾周到幾個(gè)月的時(shí)間,幫助他們平滑遷移到 v2
帶有版本前綴的 API 示例如下
GET /v1/indexes/GET /v1/indexes/abc/
POST /v1/indexes/
REST API 應(yīng)該返回什么
作為一個(gè)通則,我們建議 REST API 永遠(yuǎn)返回 JSON 格式的結(jié)果。
原因有幾個(gè):
首先,JSON 作為互聯(lián)網(wǎng)上使用最廣泛的格式,在幾乎任何語(yǔ)言的任何框架中都有廣泛的支持。
同時(shí),由于其高度的可讀性,如果需要閱讀返回內(nèi)容,JSON 會(huì)讓你的調(diào)用者閱讀起來(lái)方便很多。
最后,JSON 的高壓縮率可以在需要時(shí)方便地幫你提升傳輸效率和速度。
為什么要給你的 API 編寫文檔
寫代碼時(shí),遇到稍復(fù)雜的邏輯,我們會(huì)發(fā)現(xiàn)如果沒(méi)有注釋,一個(gè)月后回來(lái)發(fā)現(xiàn)自己當(dāng)時(shí)寫的代碼根本不像自己親生的。再試圖熟悉時(shí),可能幾個(gè)小時(shí)就過(guò)去了。
同樣,對(duì)于 API 來(lái)說(shuō),如果你不寫文檔,那么在集成時(shí),你的調(diào)用者肯定一邊罵,一邊嘗試各種參數(shù)組合。為了讓你的調(diào)用者有更順滑的接入體驗(yàn),每個(gè) API 的設(shè)計(jì)者都應(yīng)該把 API 文檔作為與 API 的代碼一樣重要的模塊。
好的 API 文檔不光可以方便調(diào)用者的接入,更可以方便讓你把 API 更改等信息傳遞出去,而不是一個(gè)一個(gè)單獨(dú)通知你的用戶。同時(shí)在編寫文檔時(shí),你也會(huì)嘗試著以你描述地方式接入,間接做了一次"dog food"自測(cè)。
如果你是面向開發(fā)者的 API 的話,優(yōu)秀的 API 文檔還可以作為強(qiáng)大的品牌宣傳。在卡拉搜索我們花大力氣維護(hù)我們的文檔,同時(shí)我們也參考和致敬其它我們用過(guò)或者覺得值得夸獎(jiǎng)的 API 文檔:
卡拉搜索 API 文檔 - 用 API 實(shí)現(xiàn)搜索引擎(https://kalasearch.cn/docs)
Leancloud API文檔(https://leancloud.cn/docs/rest_api.html)
Github API 文檔(https://developer.github.com/v3/)
默認(rèn)開啟 Gzip
在返回你的 REST API 結(jié)果時(shí),我們建議打開 Gzip 這個(gè)選項(xiàng)。
打開 Gzip
Gzip 非常好理解,在目前的普通手機(jī)算力已經(jīng)接近十幾年前的頂配計(jì)算機(jī)的前提下,CPU 不再是運(yùn)算的瓶頸。而網(wǎng)絡(luò)帶寬的擴(kuò)寬速度則遠(yuǎn)沒(méi)有追上 CPU 變快的速度。因此,如果有可能的話,用 CPU 的時(shí)間換取網(wǎng)絡(luò)的傳輸時(shí)間是非常值得的。這也就是說(shuō),打開默認(rèn) Gzip 壓縮,會(huì)讓你的 JSON 結(jié)果耗費(fèi)少量的服務(wù)器 CPU,但卻能大大加快傳輸速度。
因此我們建議默認(rèn)將 Gzip 打開。
總結(jié)
API是程序員與程序員溝通的語(yǔ)言,一個(gè)優(yōu)秀的API不光可以讓你維護(hù)起來(lái)更輕松,也會(huì)讓你的調(diào)用者在使用時(shí)更得心應(yīng)手。遵循 REST 準(zhǔn)則設(shè)計(jì)出來(lái)的優(yōu)秀的 API,可以減少你與調(diào)用者之間的溝通成本,讓你可以用更多的時(shí)間專注在其它更重要的事情上。
本文中我們從 REST 的設(shè)計(jì)準(zhǔn)則開始講起,用例子說(shuō)明如何設(shè)計(jì)出更出色的 API。本文將長(zhǎng)期更新,將我們?cè)诳ɡ阉?API 設(shè)計(jì)的最佳實(shí)踐拿出來(lái)與大家分享。
請(qǐng)持續(xù)關(guān)注我們的公眾號(hào),我們會(huì)持續(xù)分享技術(shù)心得和感悟。
來(lái)源:kalasearch.cn
長(zhǎng)按識(shí)別
喜歡就點(diǎn)個(gè)在看再走吧總結(jié)
以上是生活随笔為你收集整理的api怎么写_月薪几十K 的人是怎么设计REST API的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Python爬取网站用户手机号_设计师的
- 下一篇: 正则不等于一个字符串_更正一个观念:“积