---
# System prepended metadata

title: Ch 06. 建立 API 模型
tags: [Book, Web API 設計原則：API與微服務傳遞價值之道]

---

# Ch 06. 建立 API 模型 

## 什麼是 API 模型?

:::success
本章的 API 可以用服務的角度來理解，不適合用單支 API 的角度來理解
:::

我們可以用 API 模型來制定 API 的範圍與用途；API 模型需同時兼顧開發者與終端用戶的操作感受，透過 API 建模的過程，可以幫助我們找出差異並且建立解決方案
API 模型 aka API Profile，他會彙整前幾章產生的成果，後續開發時，**我們會以 API Profile 為基礎，產生各種 API 風格的設計，如 Restful、GraphQL、gRPC 等等**

### API Profile 結構

* 名稱與說明
* 存取範圍(internal 內部、public 公開、partner 夥伴, etc)
* 操作(ex. 操作其實比較可以理解為每一支 API (Controller > Action))及輸出入(ex. Request / Response)的詳細參數與格式
* 操作的可存取人員名單 (不確定是指 "驗證 Tokne 的權限" 還是 "真的只提供給特定人員" 之類的)
* 資源，可以理解為，當調用這支 API 時，我們可以取得的        資訊　(書上沒提到，但後續產生的表格有提到)
* API 操作所代表的事件 (Event Storming 的事件)
* (Optional) 額外的標準或規範要求，例如 SLA 之類的

> 讀到後面突然覺得，操作其實比較可以理解為每一支 API (Controller > Action)，而不是單指 HttpVerb


![](https://i.imgur.com/Spc8hSU.png)

:::info
書上有提到為何不使用 OpenAPI 來當模型文件?
因為通常 OpenAPI 會被用來當作 Restful 或 gRPC 的 API 參考文件，因此他必須要有明確的 URL 等等，但 API Profile 建立完畢時，尚未定義完整的 URL，因此不好使用 OpenAPI 當作模型文件
:::


## API 建模流程

API 建模流程的目的是為了替每個服務產生 API Profile，總共可以分為 5 個步驟：
1. 建立 API Profile 概要
2. 找出相關資源
3. 定義資源階層
4. 加入操作事件
5. 補充操作細節

### 1. 建立 API Profile 概要
建立 API 的基本資料，包括名稱、說明、範圍等等的，這些資訊來自前幾章產出的成果

![](https://i.imgur.com/ShLU05P.png)

### 2. 找出相關資源
資源指的是與 API 操作有關聯的事物，API 的每個操作都有自己會調動到的事物，在前面幾章有整理出來；以 Shopping API 為例，**書** 及 **購物車**就是與其有關的資源

根據圈選起來的部分，我們可以看出來，**書** 及 **購物車**就是 Shopping API 所需的資源
而 **作者** 這個資源的來源是，一本書可能會有多個作者，一個作者也可能有多本書，因此把作者也視為一個資源

![](https://i.imgur.com/g1luo3S.png)

![](https://i.imgur.com/e4dr5oL.png)

:::info
有時候我們會覺得可以把資料表的 schema 直接當作資源，但我們不該把資料表直接當作資源來看待，因為資料表可能是以讀寫的效能來進行設計的，這樣可能會導致定義出難以閱讀且也無法滿足用戶需求的資源
書上也提到，如果剛好資源跟資料庫的 schema 一樣，只能當作是運氣好XD
:::

### 3. 定義資源階層
我們透過定義階層來表示資源間的層次及關連性，資源間的關係有 3 種方式表達

1. Independent (獨立的)
    資源獨立存在，與其他資源互不依賴，一個資源裡面的某些屬性可以參照其他獨立或是依賴中的資源
    > 書上寫可以參照其他資源，感覺應該是單指特定屬性可以跟其他資源依賴，而不是整個資源
2. Dependent (依賴的)
    一個資源必須依賴其他的資源才能存在，父資源可以沒有子資源，但子資源沒有父資源則無法存在
    依賴與參照是不同的事，2 個獨立資源可以互相參照，不代表他們有依賴性，他們仍然各自獨立
3. Associative (關聯的)
    2 個互相獨立的資源，中間需要建立起關係才能完整表達事物的全貌，此時會在這 2 個資源中間加入 1 個中介資源來補足關係，這 2 個資源間的關係就叫做 Associative

前面定義出來的資源們，彼此間的關係如下 (自己的認知)：
1. **書** 及 **作者** 是獨立的資源，**書** 參照 **作者**，但並不依賴於 **書**
2. **購物車** 依賴 **書**，因為 **購物車** 如果沒有 **書** 則沒有 **購物車** 的存在必要
3. 而因為 **購物車** 裡的每本 **書** 需要有數量及總價，因此產生了另一個資源 **CartItem** 來存放這些東西
4. 而也因為加入了 CartItem，前面所定義的操作，**購物車** 裡面的 **書** 也改名為 **Item**
5. 目前變成 **購物車** 依賴 **CartItem**，而 **CartItem** 依賴書，則 **購物車** 跟 **書** 之間的關係變成 **關聯的**

:::danger
書上說 **購物車** 依賴 **CartItem**，但 **CartItem** 跟 **書** 之間的關係是獨立的，這件事感覺很怪
購物車沒有 CartItem 不能存在，但 CartItem 沒有書卻可以存在?
:::

![](https://i.imgur.com/xOxmF3d.png)

![](https://i.imgur.com/wsg4Li8.png)

### 4. 加入操作事件
此處的事件可以參考 Event Storming 所產生的事件，每個操作發生後可以會產生一個、多個或零個事件

### 5. 補充操作細節
1. 增加每個操作的參數細節，包含輸入或輸出之類的，但不需要完整寫完細節
2. 同步或非同步，同步是指單次的 Request 及 Response，非同步則是指送出後會進入背景執行
3. 安全性，不同的 Http Verb 會有不同的安全性，代表資源的被異動可能性

Http Verb 的安全性有以下 3 種：
1. Safe 安全的
    不會對資源造成異動，通常是 Get
2. Idempotent 冪等的
    會對資源造成異動，但重複完全一樣的操作時，不會改變資源的狀態，可以安全 retry 而不用擔心資料有問題，通常是指 Put 及 Delete
    因為 Put 通常是整筆資源更新，理論上更新過後，Input 不變的話，資源的結果不會被改動到，Delete 也是，因為資源被刪除後，不該可以再被刪除第二次
3. Unsafe 不安全的
    會改變資源的狀態，重複的操作無法保證資源的狀態維持一致，通常是 Post 及 Patch
    Post 會新增一個資源，而 Patch 傳送的是一個指令，可能會多次改變同一個資源
 
Patch 冪等性的部分可參考下面連結 
Ref. https://ihower.tw/blog/archives/6483
Ref. https://juejin.cn/post/6844903813799739399

![](https://i.imgur.com/YgAno63.jpg)

## 用時序圖驗證 API 模型

如果在畫時序圖的過程中發現，設計出來的 API Profile 無法符合 Event Storming，則需要重新回到建模的部分

![](https://i.imgur.com/mie6u1k.jpg)

## 評估 API 優先度與重用性

可以評估 API 能否帶來優點，如果沒有就可以先不用急著做
或是可以發現外部的替代方案可以取代這個 API，然後更省錢或更省時間之類的

* API 在市場上是否有競爭力?
* API 能取代既有的浪費時間或成本的方式嗎?
* API 能否增加新的收益管道?
* API 帶來的自動化效益能否讓組織的相關聯業務做得更多更好?


###### tags: `Web API 設計原則：API與微服務傳遞價值之道` `Book`