WEBAPI設計原則

WebAPI設計原則

API擁有『永久性』的特性,好壞的設計都會伴隨著,不管未來改版與否,舊版本依然很難拿掉,請謹慎設計。

API設計優先

設計api千萬不要孤軍奮戰

千萬記得跟技術/非技術的人參與討論,懂技術的規劃一定不平衡不健全

  1. 探索:確認API的需求以及確認是否現有的API已經能滿足用戶需求
  2. 設計:因應客戶需求規劃API設計,或改善現有設計
  3. 製作原型:製作原型API(Prototype API) 或擬真API(Mock API) 供大家使用,加速取得反饋並加以改進
  4. 交付:根據圓形與設計、測試、文件三項工作同時開發.不追求一次性完成,而是迭代優化循環,才可以逐步完成交付進度。
  5. 上線:讓內外部用戶使用API進行串接,良好的客戶支援此階段中最重要。

200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則.png|800

Domain Model 轉為 Web API 設計 (ADDR)

API設計會經歷四個階段,使用七個步驟來進行

目的

四個階段

  1. Align(對齊):確保商業、產品、技術團隊對產品範圍與目的都有共同且一致的認知
  2. Define(定義):將商業與客戶需求轉成對應的數位能力,成為API實作的基礎
  3. Design(設計):依照特定的步驟制定API社既文件,並選定適合的API風格
  4. Refine(優化):根據用戶回饋優化API設計、文件、原型、測試

七個步驟

  1. 鑑別數位能力:釐清用呼需求,定義出能解決需求的數位能力
  2. 產生活動與步驟:從用戶的動機、需求、與情境中找出具體的步驟並將步驟所對應的數位能力納入API設計中
  3. 界定API邊界:將API依照相關性分們別類,以及確認是否可以用計有API滿足客戶需求,縮短交付時間
  4. 建立API模型:建立API模型,產出API Profile作為後續高階設計的基礎
  5. 高階設計:選擇適合的API實現風格,製作高階設計文件
  6. 優化設計:蒐集API用戶反饋改進產品
  7. 撰寫API文件:包括API歸格文件與入門指南,方便用戶進行串接

200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-1.png

第三章

鑑別數位能力

企業組織提供自動化機制的能力模型

商業能力往往用KPI或OKR等指標來追蹤,但數位能力重視的是成果的產出,以期為了獲得商業能力所必要的行動。
商業能力表示的是組織的「What」,而數位能力表示的是組織的「How」。

JTBD (Job to be done)

原則二:api設計是目標導向

藉由目標導向API才是真正對用戶有意義。

Job Story

挑戰一:太多細節

故事主要在於抽象的行動,細節可以用「附加細節區」,跟寫程式的抽象、介面的方法一樣,找出相同的動作而不是實作細節。

200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-2.png|800

挑戰二:太偏向功能面

一樣要抽象,不要專注在功能面

200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-3.png

200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-4.png

200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-5.png

第四章

產生活動與步驟

從第三章的上圖第4點,「找到一兩本想買的書、下單、買到他然後等收貨」 是一個比較抽象的說法,但要如何把他拆解出來變成「產生活動」?

200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-6.png

200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-7.png
200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-8.png

對於不熟悉的領域,我們需要尋求外部的協助,這時候就需要利用事件風暴找出共識

利用事件風暴求出共識

這是一個團體活動,將一個未知的各個層面的商業流程、需求、事件等已具象化的方式呈現,透過一系列活動凝聚成員共識。主要增進的事我們對於特定領域的知識與共識,讓團隊具備通同的知識後,再帶回到各自的API之中。

事件風暴如何進行

這邊描述的應該有的幾個步驟、該如何進行、誰要參加、最終成果,但這個後續再來玩,太有趣了。

成立一次事件風暴

界定API邊界

API的反例

超級多合一API反模式

超肥的API讓開發者感到疑惑與挫折,太過於細碎也會有一樣的狀況。這就太過於極端不會犯這種錯誤.

超載API 反模式

一隻超完美的Accounts API 提供完整的帳戶資訊,或一隻完美的Customer API提供用戶完整資訊,理想很豐滿、現實很骨感,這種完美個API都不會有好下場。

重要觀念

書其實就是產品「Product」,應該區分用於分類使用、商品呈現使用、出貨用、訂單用,都各有自己的重要使命。這樣的API區分出來以後,可預見分類或是產品、購物車用的API的Request需求大於訂單跟出貨,又可以把它拆解出來。

200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-9.png

用事件風暴界定邊界

跟之前學習到的DDD 一樣把這些行為模式列舉出來之後,就會找到很多相關詞,把這些相關詞列出來之後,就可以找到他的邊界

這邊提供兩個方法來界定他的邊界

使用共同詞彙

200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-10.png

使用聚合作為邊界

要注意使用聚合作爲依據可能會因為範圍的顆粒度不同,導致每個API的精細度不同,所以要注意

200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-11.png

200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-12.png

200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-13.png

200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-14.png

第六章 建立API模型

好的API設計來自於 API模型,API模型協助制訂一個API的範圍與用途、搞懂與驗證Client端與外部開發者的需求,跟畫面的Prototype不一樣(滿足客戶),API模型滿足開發者Client的操作感受盡管兩者的需求是共同的但還是會有些差異,透過API建模的過程,能找出差異並建立解決方案,避免在錯誤的基礎上蓋房子。

建模API的素材來自於前面幾張,活動、步驟、工作故事,彙整過後就是API Profile。API Profile 包含 一切特性,有名稱範圍事件,有API模型的存在有機會告早在模型中發現問題並加以修正,相較於重構的成本真的太划算了。

API Profile 結構

一份典型的 API Profile包含有以下項目

建議是可以共同協作的線上文件、Wiki...等等

200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-16.png

為何不使用OpenAPI(SWagger)來當作API模型文件?

他是屬於讀取程式碼的REST或gRPC的規格書,他用途是API技術參考文件與範例程式,但是他會是後續建立API profile的好的素材。

第一步:建立 API profile概要

定義基本資料,包括名稱說明範圍(internal、public、partner)等等,命名方式建議使用 lowerCamelCase,這對後續的時序圖會有幫助。

200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-15.png

第二步:找出相關資源

找出跟PAI操作有關的事物,API的每個操作都會調動到的事物,聽起來很抽象,但其實之前我們已經對齊(Align)很定義(Define)階段就已經整理過了。

其中的Books、Cart, 這些之前就已經定義清楚了。

注意

標示資源為何不直接拿DB的欄位作為對應?

  • 資料庫設計注重結構與效能設計(正規化/反正規化),API層注重的是用戶導向並不是讀寫的效能,因此不建議拿DB Table作為對應資源
  • 思考應該由高至低,如果從Table 開始會太多細節在裡面。

200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-17.png

200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-18.png

第三部:定義資源階層

資源間的層級關係(taxonomy)制定出來,所謂的taxonomy是一個分類與組織事務的術語,用來表示階層資源間彼此的層次與關聯性。

資源關係有三種表達方式:

  1. Independent(獨立的):資料獨立存在,與其他資源不互相依賴
  2. Dependent(依賴的):一個資源必須依賴其他資源才能存在,父子概念(子無法單獨存在)。(依賴跟參考是不同的概念:如果兩個獨立的(Independent)互相參照並不表示他有依賴性,他們仍然是各自獨立)(如下圖範例)
  3. Associative(關聯的):兩個獨立的資源,而兩者間又需要建立起關係才能完整表達事務的全貌,這種狀況或加入一個中介資源來捕捉他們的關係,這種結構下那兩個互相獨立的資源的關係稱為associative。

下圖 Book資源Book Author 資源 是各自獨立的,但又可以互相參考讓事情全貌更完整。

200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-19.png

上圖中有一個書籍的數量該放哪呢?,就如下圖,當一本書被放進購物車那書的數量金額應該怎麼放呢? 引入另一個資源CartItem來存放這些購物車的閔項細節。

200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-20.png

因為引入CartItem,為了讓名稱一致,原本操作addBookToCart()改成 AddItemToCart()removeBookFromCart()改為removeItemCart()

200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-21.png

加入事件操作

確認階層過後補完每個API操作具有的事件,API操作發送出的事件可以為API客戶端所使用,例如資料分析、客戶端收到事件後也能在對API發起別的請求

此處的事件可以參考 事件風暴中的那些事件,做事件風暴的時候有定義有哪些事件,如果你未曾使用事件風暴,也可以用之前建模時所設定的那些事件。

事件的命名請使用過去式,除此之外如果組織內既有的命名原則應該遵循

200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-22.png

補充細節

我們將填入每一個操作的參數細節,包括他的

200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-23.png

Source:200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/WEBAPI設計原則

ShoppingAPI.profile完整範例

Shopping API

  • Supports the book browsing experience and cart management
  • Scope: Public
Operation Name Description Participants Resource(s) Emitted Events Operation Details Traits
listBooks() List books by category or release date Customer, Call Center Book, Book Author Books.Listed Request Parameters: categoryId, releaseDate Returns: Books[] safe / synchronous
searchBooks() Search for books by author, title Customer, Call Center Book Books.Searched Request Parameters: searchQuery Returns: Books[] safe / synchronous
addItemToCart() Add a book to the customer's cart Customer, Call Center Cart Item, Cart Cart.ItemAdded Request Parameters: cartId, bookId, quantity Returns: Cart unsafe / synchronous
removeItemFromCart() Remove a book from the customer's cart Customer, Call Center Cart Item, Cart Cart.ItemRemoved Request Parameters: cartItemId Returns: Cart idempotent / synchronous
clearCart() Remove all books from the customer's cart Customer, Call Center Cart Cart.Cleared Request Parameters: cartId Returns: Cart safe / synchronous
viewCart() View the current cart and total Customer, Call Center Cart Cart.Viewed Request Parameters: cartId Returns: Cart safe / synchronous

用時序圖驗證API模型

確保API作業如預期,我們使用時序圖來驗證並且拿此圖來跟大家討論API作業的意見。

確認API profile的特性是否跟工作故事的特性一致、沒有做歪。不是畫圖就結束,我們要邊畫邊模擬真實的互動情境,設想每個操作,資源是不是符合預期,中間是否有缺漏,如果有請回到建模步驟再次補完。

驗證完畢後將API模型分享給大家,包括技術非技術外部專家早期用戶等,徵求反饋,進入設計階段前,務必要確保目前的成果是大家一致認可的。

sequenceDiagram
    participant Customer
    participant Shopping API
    participant Order Creation API
    participant Payment Processing API

    Customer->>Shopping API: listBooks()
    Shopping API-->>Customer: Books[]
    Customer->>Shopping API: addBookToCart(bookId)
    Shopping API-->>Customer: Cart
    Customer->>Shopping API: removeBookFromCart(bookId)

    Customer->>Shopping API: searchBooks(searchQuery)
    Shopping API-->>Customer: Books[]
    Customer->>Shopping API: addBookToCart(bookId)
    Shopping API-->>Customer: Cart

    Customer->>Shopping API: viewCart()
    Shopping API-->>Customer: Cart
    Customer->>Order Creation API: createOrderFromCart(cartId)
    Order Creation API-->>Customer: Order

    Customer->>Payment Processing API: payForOrder(orderId)
    Payment Processing API-->>Customer: PaymentDetails

評估API優先順序與重用性

  1. 評估API提供的商業與市場價值,試問自己幾個問題

以上答案皆非,那不用做了,如果有正面的肯定答案就表示可以做了。

  1. 再來評估每隻API的難度,API的難度可以用在事件風暴所產生的步驟來估計,越多步驟、複雜、時間,難度就越高,反之亦然,可區分 低、中、高。
  2. 看看現有的資源是否有可以拿來使用修改,不需要自己重新造輪子

200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-24.png

總結

了解整體核心價值後,可以把非核心業務由外部API處理(或初階工程師),或沿用現有的,找到平衡點。

第七章 REST API

REST 被設計適用於粗顆粒度的訊息交換,儘管這是Web最普遍的形式,但對於其他形式,REST就不是最佳解。
REST是一來一往的過程,並不能像 RPC可以達到非同步也沒有結構性約束,頁面上的操作往往是比較粗的呈現(適用REST),想要更細的操作(RPC這類就不錯)
沒有特別需要細粒度的需求,一班都會選擇REST作為主要API風格

提示

REST從來就不是CRUD + JSON,是一系列的架構性約束與約定,這些約束與約定制定了一個系統的模組間該如何有效的工作與互動

REST的架構性約束給系統更好的靈活性(flexibility)與進化性(evolvability)

衡量RESTAPI的成熟度(RMM)

REST API 設計流程

第一步:設計資源的URL路徑

根據6.7的圖片,已經列出所有資源路徑

200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-20.png

!200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-29.png

對於關聯式資料庫熟悉的人可會傾向用資料庫的角度去規劃資源的相關性,這可能導致資源關聯性過於複雜,大原則還是用戶導向,不影響API用戶認知的前提下,盡可能讓URL精簡,只留下較具有顯著意義的關聯資源。

!200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-30.png

傾向複數表示某種資源的集合

!200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-32.png

第二步:將API操作對應到HTTP方法

根據 API Profile 跟 HTTP 方法安全特性 如下圖,可以結合出每項操作的HTTP方法

!200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-31.png

!200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-33.png

!200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-35.png

設定回應碼

200:成功,或與成功相關
400:失敗,意味著客戶端必須修正他的請求並載次嘗試
500:服務端異常,或因為客戶端導致的服務端異常

不要發明回應碼,尊重業界慣例,下圖是加上回應碼後的表格。

!200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-40.png

第四步:撰寫 REST API 設計文件

!200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-38.png

可以是用自己喜歡的方式,本書用 Swagger Editor 作為範例 Swagger Editor

在Swagger Editor中,以API Profile內的資料為基礎,填入API名稱等基本資訊,在Description中寫入API的用途、功能、說明、操作等端點資訊,並註明和本API相關的其他API資料,但不要寫到API內部運作細節,細節應該由Wiki工人調閱。

!200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-41.png

!200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-42.png

!200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-44.png

!200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-45.png

接著用時序圖模擬真實的互動狀況,驗證目前的設計有無背離當初的作故事與事件風暴的規劃,驗證的時序圖如下,展示了用戶購物情境

!200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-46.png

第五步:分享並獲得回饋

將設計分享出去,可以分享給團隊內的同事,盡早分享給早期用戶並蒐集他們的反饋。

因為API發佈出去就覆水難收,端點操作、參數都難以在改變,串好的應用也不可能接受破壞性的改變唯一能做的只有追加新功能或新特性,在發佈API前務必檢討再檢討,分享出去給成員們請求協助審閱,找出問題,鼓勵回饋意見,讓API發佈前就已經過千錘百鍊,而不是亡羊補牢。

除此之外也可以利用Mock API 讓人們去測試API實際行為,也可以驗證資料的正確性,相較於眼睛看,手動可以獲得更好的體驗。

決定API的表現格式

格式選擇原則不要三心二意,一定決定後就盡量不要更改,讓每一套都一致減少後面不必要的複雜度。

隨著時間眼鏡難免需要提供別得格式來回應市場需求,為了避免破壞現有串接,格式的遷移應該是漸進式的,如果要同事供應多種格式,那需要利用HTTP的內容協商機制,他讓客戶端可以指定回應的格式,API再據此回應之。

下表格是循序漸進的,從最基本的序列化開始,逐漸加上jypermedia等其他特性,當然複雜度也隨之增高

!200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-47.png

資源序列化

說白就是JSON、XML、YAML這邊沒什麼好說的,反而是後面的說明觀察它的變化比較是關注的要點

!200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-49.png

序列化加 Hypermedia

Hypermedia的序列化與前面的資源序列化類似,只不過加上hypermedia的額外資訊,除了用連結表示,也可以把其他資源直接置入回應中,這種模式稱為內嵌資源(embedded resource)

可以用一個格式 HAL(Hypertext Application Language)的格式作為hypermedia的序列化格式,但實際HAL也是基於JSON的基礎再去語意擴充的格式,這樣好處是改版挾帶hypermedia也不會影響原有的客戶端串接

!200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-50.png

支援Hypermedia的通用訊息格式

Hypermedia在互動訊息方面,尋求統一個標準語法或結構的格式,該格式必須要能夠用於傳達所需要的資源、屬性、連結等資訊,才能讓用戶端能以更通用的方式解析這些資訊。

有統一互動格式,前後端才有共同語言像是打通任督二脈

hypermedia的序列化格式有JSON:APISiren他們都符合標準化的語法跟結構。

語意化的通用訊息格式

語意化(semantic) 是個牽涉廣泛議題,主流採用Schema.org的方案,以下示範立,雖然變胖了但是換來讓客戶端讀懂內容,例如提供更有效率的UI/UX、更動態的頁面元素、頁面跳轉、更輕量化的客戶端....等等。

!200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-53.png

!200-Areas/230-知識擴展/讀書筆記/WEBAPI設計原則/resource/WEBAPI設計原則-52.png