我想要的是個(gè)什么樣的API

直奔主題~

命名

看一份API文檔的時(shí)候可能最先看的就是字段命名,常規(guī)的API文檔會(huì)逐個(gè)解釋一下每個(gè)字段的含義,但是最好不要用一些常用語言的關(guān)鍵字來命名一個(gè)對(duì)象的屬性,比如int,id。id的話盡量加上一個(gè)描述,比如uid。一來避免API使用者需要重新進(jìn)行映射關(guān)系調(diào)整。二來一個(gè)對(duì)象中可能會(huì)存在很多個(gè)id,避免混淆。當(dāng)然這種設(shè)計(jì)本身不是什么嚴(yán)重問題,可以算在可優(yōu)化之列。

類型

很多服務(wù)端Response一般采取JSON格式返回?cái)?shù)據(jù)。常用JSON類型一般分為Number,String,Boolean,Array,Object這幾種。一些服務(wù)端語言對(duì)類型并不敏感,尤其是腳本語言,內(nèi)部本身會(huì)對(duì)類型做一些轉(zhuǎn)化,比如js或者php。但是這并不代表這門語言沒有類型的概念。JSON中也是一樣,JSON本質(zhì)上就是JS的對(duì)象。
下面是不同類型的對(duì)象在JSON里的一些表現(xiàn)

Number  >>> {"value": 1}
String >>> {"value": "1"}
Boolean >>> {"value": true}
Array >>> {"value": []}
Object >>> {"value": {}}

因此,文檔上如果區(qū)分好不同字段的類型對(duì)于使用者和開發(fā)者都更加有意義。比如status表示狀態(tài),一般支持枚舉的語言都會(huì)把這種狀態(tài)轉(zhuǎn)換成枚舉類型,所以經(jīng)常我們會(huì)定義這種數(shù)據(jù)為Number型。再比如金額,數(shù)量,時(shí)間間隔這種可能會(huì)參與運(yùn)算的字段,我們一般也會(huì)定義成Number型。一些API會(huì)把所有的非容器字段都定義成String類型來表示,從實(shí)現(xiàn)的角度來說也可以的。只是服務(wù)端要把一些Number類型的先轉(zhuǎn)換成String(不管是隱式的還是顯式的)。客戶端也一樣,在需要這些字段需要作為數(shù)字類型參與運(yùn)算的時(shí)候也做一次轉(zhuǎn)換。然而這一步操作從設(shè)計(jì)上來講是可以避免的,減少了操作也意味著減少了問題出現(xiàn)的概率,何樂而不為。
另外,有的時(shí)候會(huì)出現(xiàn)這樣的情況,文檔上會(huì)寫:

name type
objectModelList Array

然后實(shí)際接口返回了

{
    "objectModelList":null
} 

or

{
    "objectModelList":[]
} 

明顯后面的更準(zhǔn)確Array就是Array,空的也應(yīng)該是個(gè)Array

層級(jí)

舉個(gè)例子,有個(gè)Area對(duì)象,下面對(duì)應(yīng)這AreaCoordinate以及AreaID和AreaDescription幾個(gè)屬性。然后有個(gè)Person對(duì)象,對(duì)象下面有一些其它類型的屬性和一個(gè)Area類型的屬性。例如:

class Area {
    var a_coordinate
    var a_id
    var a_description
}

class Person {
    var a_coordinate
    var a_id
    var a_description

   var p_name
   var p_gender
   ...
}

why not

class Person {
    var p_area
    var p_name
    var p_gender
    ...
}

無論服務(wù)端的json_encode還是客戶端的json_decode對(duì)于后面這一種數(shù)據(jù)結(jié)構(gòu)都能更容易的處理,而且整個(gè)的模型不會(huì)顯得流水賬,更有層次感。

data對(duì)象

{
    "status": 200,
    "data": {},
    "reason": ""
}

這是一個(gè)基本的返回結(jié)構(gòu),很多App的API也是使用了類似的結(jié)構(gòu)將數(shù)據(jù)返回給App。status一般用來表示這次請(qǐng)求的狀態(tài),在異常狀態(tài)時(shí)reason會(huì)拋出異常的原因用來給予開發(fā)人員調(diào)試用,還有些異常需要直接拋給用戶的可能還要再加一個(gè)tips的字段。data中返回正常邏輯的數(shù)據(jù)。那么對(duì)比一下下面兩組數(shù)據(jù)結(jié)構(gòu)

{
    "status": 200,
    "data": [
             "177*****383", 
             "177*****452",  
             "177*****383"
            ],
    "reason": ""
}

and

{
    "status": 200,
    "data": {
             "mobileList": [
                            "177*****383", 
                            "177*****452", 
                            "177*****383"
                           ],
            },
    "reason": ""
}

data被定義為返回的數(shù)據(jù)內(nèi)容,其本身應(yīng)該作為數(shù)據(jù)集合定義在了基本的數(shù)據(jù)接口中。作為客戶端來講非常希望data的數(shù)據(jù)類型能固定。原因之一,客戶端和服務(wù)端可以將data本身作為通用邏輯處理而不需要考慮對(duì)不同的類型做出不同的操作。原因之二,如果使用自動(dòng)化生成model類,后面一種json很容易推測(cè)出model的字段包括Model本身的名稱從而完全準(zhǔn)確的自動(dòng)生成Model類。如果是前面一種結(jié)構(gòu),無從推斷數(shù)組中的內(nèi)容是什么,自動(dòng)化也就無從談起了。

避免冗余

同樣的信息在一個(gè)API中不要通過兩個(gè)渠道傳遞例如:

請(qǐng)求參數(shù)

name type
uid number
token string

很多時(shí)候,客戶端在與服務(wù)端交互的時(shí)候是用token,cookie或者SessionID來完成對(duì)客戶端身份的驗(yàn)證的。服務(wù)端可以根據(jù)這些字段拿到對(duì)應(yīng)的用戶的所有信息,此時(shí)API要求用戶傳uid顯然就沒有什么必要了。相反,在兩個(gè)字段中傳入了相同的冗余數(shù)據(jù)這種操作至少增加了一種異常判斷,就是這兩個(gè)數(shù)據(jù)不匹配的話如何處理。沒有必要的增加異常邏輯無論是服務(wù)端還是客戶端都是非常不愿意看到的事。

版本

每個(gè)API都應(yīng)該有對(duì)應(yīng)的版本號(hào),API在做修改的時(shí)候,無論是增刪字段還是變更數(shù)據(jù)結(jié)構(gòu),都要在版本上體現(xiàn)出來。升級(jí)新版本的同時(shí)保持老版本的API存在一段時(shí)間是一個(gè)常用的做法。在APP發(fā)布時(shí),這個(gè)版本的APP對(duì)應(yīng)的API版本已經(jīng)固定了。所以,不要在APP發(fā)布后修改API,但是可以修改內(nèi)部實(shí)現(xiàn),文檔上的內(nèi)容無論是增加還是刪除,都可能對(duì)已經(jīng)發(fā)布的APP造成影響。如果有需求,可以再增加一個(gè)新的版本的API。這樣可以保證QA人員進(jìn)行測(cè)試時(shí)候的環(huán)境和后面生產(chǎn)的環(huán)境一致,不至于因此出現(xiàn)老版本的APP異常的問題。另外,最好在定義API的時(shí)候加入當(dāng)前API不再支持的異常狀態(tài),以便于在不支持老版本的時(shí)候,客戶端可以給用戶正確的提示。

安全性

目前市面上的很大一部分采用HTTP傳遞數(shù)據(jù)的APP是有安全風(fēng)險(xiǎn)的,詳情參見API安全-破譯HTTP傳遞的對(duì)稱加密密文

以上都是一些比較常見的問題,還有更多的問題文章中沒有提到,歸根到底,API的設(shè)計(jì)還是大道至簡(jiǎn)的原則,異常邏輯越少越有利于整個(gè)項(xiàng)目的穩(wěn)定運(yùn)行。設(shè)計(jì)上的問題對(duì)于很多團(tuán)隊(duì)來說后續(xù)是很難再修改的,可能因?yàn)闀r(shí)間等一些原因,產(chǎn)品可以用就不再優(yōu)化設(shè)計(jì)了。所以還是建議在最開始設(shè)計(jì)API的時(shí)候就對(duì)這些細(xì)節(jié)問題考慮進(jìn)去,根基深才得以筑高樓。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容