<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          API設(shè)計的幾條原則 | IDCF

          共 3828字,需瀏覽 8分鐘

           ·

          2020-08-23 11:05


          內(nèi)容來源:ThoughtWorks洞見
          作者:少個分號

          API 設(shè)計是微服務(wù)設(shè)計中非常重要的環(huán)節(jié),代表服務(wù)之間交互的方式,會影響服務(wù)之間的集成。通常來說,一個好的 API 設(shè)計需要滿足兩個主要的目的。

          API 本身的含義指應(yīng)用程序接口,包括所依賴的庫、平臺、操作系統(tǒng)提供的能力都可以叫做 API。我們在討論微服務(wù)場景下的 API 設(shè)計都是指 WEB API,一般的實現(xiàn)有 RESTful、RPC等。API 代表了一個微服務(wù)實例對外提供的能力,因此 API 的傳輸格式(XML、JSON)對我們在設(shè)計 API 時的影響并不大。

          API 設(shè)計是微服務(wù)設(shè)計中非常重要的環(huán)節(jié),代表服務(wù)之間交互的方式,會影響服務(wù)之間的集成。通常來說,一個好的 API 設(shè)計需要滿足兩個主要的目的:

          • 平臺獨(dú)立性。任何客戶端都能消費(fèi) API,而不需要關(guān)注系統(tǒng)內(nèi)部實現(xiàn)。API 應(yīng)該使用標(biāo)準(zhǔn)的協(xié)議和消息格式對外部提供服務(wù)。傳輸協(xié)議和傳輸格式不應(yīng)該侵入到業(yè)務(wù)邏輯中,也就是系統(tǒng)應(yīng)該具備隨時支持不同傳輸協(xié)議和消息格式的能力。
          • 系統(tǒng)可靠性。在 API 已經(jīng)被發(fā)布和非 API 版本改變的情況下,API 應(yīng)該對契約負(fù)責(zé),不應(yīng)該導(dǎo)致數(shù)據(jù)格式發(fā)生破壞性的修改。在 API 需要重大更新時,使用版本升級的方式修改,并對舊版本預(yù)留下線時間窗口。

          實踐中發(fā)現(xiàn),API 設(shè)計是一件很難的事情,同時也很難衡量設(shè)計是否優(yōu)秀。根據(jù)系統(tǒng)設(shè)計和消費(fèi)者的角度,給出了一些簡單的設(shè)計原則。


          使用成熟度合適的 RESTful API



          RESTful 風(fēng)格的 API 具有一些天然的優(yōu)勢,例如通過 HTTP 協(xié)議降低了客戶端的耦合,具有極好的開放性。因此越來越多的開發(fā)者使用 RESTful 這種風(fēng)格設(shè)計 API,但是 RESTful 只能算是一個設(shè)計思想或理念,不是一個 API 規(guī)范,沒有一些具體的約束條件。

          因此在設(shè)計 RESTful 風(fēng)格的 API 時候,需要參考 RESTful 成熟度模型。

          根據(jù)自己的應(yīng)用場景選擇對應(yīng)的成熟度模型,一般來說系統(tǒng)成熟度模型在 Level 2左右。


          避免簡單封裝



          API應(yīng)該服務(wù)業(yè)務(wù)能力的封裝,避免簡單封裝讓API徹底變成了數(shù)據(jù)庫操作接口。例如標(biāo)記訂單狀態(tài)為已支付,應(yīng)該提供形如POST /orders/1/pay這樣的API。而非PATCH /orders/1,然后通過具體的字段更新訂單。

          因為訂單支付是有具體的業(yè)務(wù)邏輯,可能涉及到大量復(fù)雜的操作,使用簡單的更新操作將業(yè)務(wù)邏輯泄漏到系統(tǒng)之外。同時系統(tǒng)外也需要知道訂單狀態(tài)這個內(nèi)部使用的字段。
          更重要的是,破壞了業(yè)務(wù)邏輯的封裝,同時也會影響其他非功能需求。例如,權(quán)限控制、日志記錄、通知等。

          關(guān)注點(diǎn)分離



          好的接口應(yīng)該做到不多東西,不少東西。怎么理解呢?在用戶修改密碼和修改個人資料的場景中,這兩個操作看起來很類似,然后設(shè)計API的時候使用了一個通用的/users/1/updateURI。
          然后定義了一個對象,這個對象可能直接使用了User這個類:
          {
          "username": "用戶名",
          "password": "密碼"
          }

          這個對象在修改用戶名的時候,password是不必要的,但是在修改密碼的操作中,一個password字段卻不夠用了,可能還需要confirmPassword

          于是這個接口變成:
          {
          "username": "用戶名",
          "password":"密碼",
          "confirmPassword":"重復(fù)密碼"
          }
          這種類的復(fù)用會給后續(xù)維護(hù)的開發(fā)者帶來困惑,同時對消費(fèi)者也非常不友好。合理的設(shè)計應(yīng)該是兩個分離的 API:
          // POST /users/{userId}/password

          {
          "password":"密碼",
          "confirmPassword":"重復(fù)密碼"
          }
          // PATCH /users/{userId}

          {
          "username":"用戶名",
          "xxxx":"其他可更新的字段"
          }
          對應(yīng)的實現(xiàn),在 Java 中需要定義兩個 DTO,分別處理不同的接口。這也體現(xiàn)了面向?qū)ο笏枷胫械年P(guān)注點(diǎn)分離。

          完全窮盡,彼此獨(dú)立



          API 之間盡量遵守完全窮盡,彼此獨(dú)立 (MECE) 原則,不應(yīng)該提供相互疊加的 API。例如訂單和訂單項這兩個資源,如果提供了形如PUT /orders/1/order-items/1這樣的接口去修改訂單項,接口PUT /orders/1就不應(yīng)該具備處理某一個order-item的能力。
          這樣的好處是不會存在重復(fù)的 API,造成維護(hù)和理解上的復(fù)雜性。如何做到完全窮盡和彼此獨(dú)立呢?
          簡單的方法是使用一個表格設(shè)計 API,標(biāo)出每個 URI 具備的能力。
          資源 URL 設(shè)計來源于 DDD 領(lǐng)域建模就非常簡單了,聚合根作為根 URL,實體作為二級 URI 設(shè)計。聚合根之間應(yīng)該徹底沒有任何聯(lián)系,實體和聚合根之間的責(zé)任應(yīng)該明確。
          產(chǎn)生這類問題的根源還是缺乏合理的抽象。如果存在 API 中可以通過用戶組操作用戶,通過用戶的 URI 操作用戶屬于的用戶組,這其中的問題是缺少了成員這一概念。用戶組下面的本質(zhì)上并不是用戶,而是用戶和用戶組的關(guān)系,即成員。

          版本化



          一個對外開放的服務(wù),極大的概率會發(fā)生變化。業(yè)務(wù)變化可能修改 API 參數(shù)或響應(yīng)數(shù)據(jù)結(jié)構(gòu),以及資源之間的關(guān)系。一般來說,字段的增加不會影響舊的客戶端運(yùn)行。但是當(dāng)存在一些破壞性修改時,就需要使用新的版本將數(shù)據(jù)導(dǎo)向到新的資源地址。
          版本信息的傳輸,可以通過下面幾種方式
          • URI 前綴
          • Header
          • Query

          比較推薦的做法是使用 URI 前綴,例如/v1/users/表達(dá)獲取 v1 版本下的用戶列表。

          常見的反模式是通過增加 URI 后綴來實現(xiàn)的,例如/users/1/updateV2。這樣做的缺陷是版本信息侵入到業(yè)務(wù)邏輯中,對路由的統(tǒng)一管理帶來不便。
          使用 Header 和 Query 發(fā)送版本信息則較為相似,不同之處在于,使用 URI 前綴在 MVC 框架中實現(xiàn)相對簡單,只需要定義好路由即可。使用 Header 和 Query 還需要編寫額外的攔截器。

          合理命名



          設(shè)計 API 時候的命名涉及多個地方:URI、請求參數(shù)、響應(yīng)數(shù)據(jù)等。通常來說最主要,也是最難的一個是全局命名統(tǒng)一。
          其次,命名需要注意這些:
          • 盡可能和領(lǐng)域名詞保持一致,例如聚合根、實體、事件等
          • RESTful 設(shè)計的 URI 中使用名詞復(fù)數(shù)
          • 盡可能不要過度簡寫,例如將 user 簡寫成usr
          • 盡可能使用不需要編碼的字符

          用領(lǐng)域名詞來對 API 設(shè)計命名不是一件特別難的事情。識別出的領(lǐng)域名詞可以直接作為 URI 來使用。如果存在多個單詞的連接可以使用中橫線,例如/orders/1/order-items


          安全



          安全是任何一項軟件設(shè)計都必須要考慮的事情,對于 API 設(shè)計來說,暴露給內(nèi)部系統(tǒng)的 API 和開放給外部系統(tǒng)的 API 略有不同。
          內(nèi)部系統(tǒng),更多的是考慮是否足夠健壯。對接收的數(shù)據(jù)有足夠的驗證,并給出錯誤信息,而不是什么信息都接收,然后內(nèi)部業(yè)務(wù)邏輯應(yīng)該邊界值的影響變得莫名其妙。
          對于外部系統(tǒng)的 API 則有更多的挑戰(zhàn)。
          • 錯誤的調(diào)用方式
          • 接口濫用
          • 瀏覽器消費(fèi) API 時因安全漏洞導(dǎo)致的非法訪問
          所以設(shè)計 API 時應(yīng)該考慮響應(yīng)的應(yīng)對措施。針對錯誤的調(diào)用方式,API 不應(yīng)該進(jìn)入業(yè)務(wù)處理流程,及時給出錯誤信息;對于接口濫用的情況,需要做一些限速的方案;對于一些瀏覽器消費(fèi)者的問題,可以在讓 API 返回一些安全增強(qiáng)頭部,例如:X-XSS-Protection、Content-Security-Policy 等。

          API設(shè)計評審清單



          • URI 命名是否通過聚合根和實體統(tǒng)一
          • URI 命名是否采用名詞復(fù)數(shù)和連接線
          • URI 命名是否都是單詞小寫
          • URI 是否暴露了不必要的信息,例如/cgi-bin
          • URI 規(guī)則是否統(tǒng)一

          • 資源提供的能力是否彼此獨(dú)立

          • URI 是否存在需要編碼的字符

          • 請求和返回的參數(shù)是否不多不少

          • 資源的 ID 參數(shù)是否通過 PATH 參數(shù)傳遞

          • 認(rèn)證和授權(quán)信息是否暴露到 query 參數(shù)中

          • 參數(shù)是否使用奇怪的縮寫

          • 參數(shù)和響應(yīng)數(shù)據(jù)中的字段命名統(tǒng)一

          • 是否存在無意義的對象包裝 例如{"data":{}'}

          • 出錯時是否破壞約定的數(shù)據(jù)結(jié)構(gòu)

          • 是否使用合適的狀態(tài)碼

          • 是否使用合適的媒體類型

          • 響應(yīng)數(shù)據(jù)的單復(fù)是否和數(shù)據(jù)內(nèi)容一致

          • 響應(yīng)頭中是否有緩存信息

          • 是否進(jìn)行了版本管理

          • 版本信息是否作為 URI 的前綴存在

          • 是否提供 API 服務(wù)期限

          • 是否提供了 API 返回所有 API 的索引

          • 是否進(jìn)行了認(rèn)證和授權(quán)

          • 是否采用 HTTPS

          • 是否檢查了非法參數(shù)

          • 是否增加安全性的頭部

          • 是否有限流策略

          • 是否支持 CORS

          • 響應(yīng)中的時間格式是否采用ISO 8601標(biāo)準(zhǔn)

          • 是否存在越權(quán)訪問


          八月,乘風(fēng)破浪。IDCF【冬哥有話說】8月特別邀請到四位美女,帶來四個主題分享,分別從組織建設(shè)、績效考核、品牌營銷,以及技術(shù)卓越等不同角度,圍繞“數(shù)字化”展開,這也體現(xiàn)了IDCF一直秉承的理念“培養(yǎng)端到端的人才”,我們希望可以通過本系列的分享,給你不同的視角去看待一個企業(yè),從單純的技術(shù)視角跳出來,去盡可能的看到一個更加完整的全貌。
          識別下圖二維碼,回復(fù)“乘風(fēng)破浪”即可獲取直播地址。


          瀏覽 65
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  毛片基地操逼视频 | 一区二区自拍偷拍0519 | 天天爽天天撸 | 婷婷伊人綜合中文字幕小说 | 北条麻妃 无码 在线 视频 |