為什麼不應該在 REST API 中使用布林值? - geekculture

發表於2021-06-18

在 REST API 中使用布林值壞處:

  • 會阻礙API 可擴充套件性
  • 會遮蔽和混淆域清晰度
  • 會妨礙程式碼 可讀性和可維護性

讓我們深入研究這些領域並稽核布林值在 REST API 中的常用方式。

 

API 可擴充套件性

一個可擴充套件的 API應該讓未來的變化顯而易見並且易於實施。它不應引入複雜性或不必要的重複或破壞現有的消費者。

以Github 的 REST API為例,如果要建立新的儲存庫,開發人員private通過設定布林欄位(預設值:)來指定儲存庫是否成功。

HTTP Request: POST /user/repos
{
  "name": "Hello-World",
  "description": "This is your first repository",
  "private": false,
  ...
}

這個示例 POST 請求起初看起來很簡單。但是,當 Github 後來引入組織公司的儲存庫時,他們需要將訪問限制為僅限公司組織的成員。在這種情況下,布林欄位private不再足夠。因此,他們新增了一個visibility具有以下選項的新列舉:

  • internal — 僅限於組織成員
  • public— 可從網際網路公開訪問
  • private— 僅限於儲存庫建立者和合作者

有了這一變化,文件宣告當兩者都使用時visibility將覆蓋private。這導致了混淆文件和API中的重複的域概念。

 

領域清晰度

一個清晰的領域應該是有益的。它的元件應該可以通過無處不在的統一語言被發現。它應該通過清晰的邊界來封裝邏輯以避免下游錯誤。最後,它應該很難濫用其任何元件。

示例:付款 API — 傳送新付款

讓我們考慮一個金融服務行業的例子。大多數支付閘道器 API 將使用布林欄位響應isApproved支付請求。這是HTTP 資源 ( )的單一狀態指示器/payments。

HTTP Request: POST /payments
{
  "transactionId": "uniqueId",
  "paymentDetails": {...}
  "chargeAmount": 15.00,
  ...
}
HTTP Response:
{
  "isApproved": true,
  "approvedAmount": 15.00,
  ...
}

在這個 API 中,“部分批准”的概念是隱含的。API 消費者必須檢查 1) 付款isApproved和 2)approvedAmount少於初始chargeAmount. 這裡的隱含性質是域邏輯洩露給消費者的一種症狀。換句話說,這迫使消費者弄清楚“部分批准”的邏輯是什麼,而不是我們直接告訴他們。域邊界的這種不清晰也將消費者與域邏輯耦合在一起。

現在讓我們看看這個例子如何影響程式碼的可讀性和可維護性。

 

程式碼可讀性和可維護性

程式碼可讀性不僅僅是閱讀程式碼的功能。揭示程式碼的意圖很重要——為什麼程式碼會做它所做的事情。

在前面的示例中,API中“部分批准”的隱含性質促使 API 使用者編寫以下程式碼:

val (isApproved, approvedAmount, chargeAmount) = paymentResponse

if (isApproved && approvedAmount < chargeAmount) {
  var owedAmount = chargeAmount - approvedAmount
  //logic to re-display order total screen with owedAmount
}

不過,還有更好的方法。如果我們在 API 中明確引入“部分批准Partial Approvals”,我們就可以編寫反映領域普遍存在的語言的程式碼——清楚地揭示我們意圖的程式碼。以下是推薦的 API:

HTTP Request: POST /payments/
{
  "transactionId": "uniqueId",
  "paymentDetails": {...},
  "chargeAmount": 15.00,
  ...
}
HTTP Response:
{
  "paymentStatus": "PARTIALLY_APPROVED"
  "approvedAmount": 10.00,
  "remainingAmount": 5.00,
  ...
}

現在我們的 API 有一個paymentStatus列舉值為PARTIALLY_APPROVED。API 中的這種有意清晰促使開發人員編寫反映 API 語言的程式碼:

val (paymentStatus, remainingAmount) = paymentResponse

if (paymentStatus.PARTIALLY_APPROVED) {
  var owedAmount = remainingAmount
  //re-display order total screen with owedAmount
}

通過使用列舉,我們允許 API 使用者

  • 1) 通過 API 本身發現不同的值,從而瞭解有關域的更多資訊,以及
  • 2) 從其強型別值中受益,從而減少錯誤。

 布林值相比,列舉和陣列在 API 設計中為我們提供了更多的靈活性。

何時在 API 中使用布林值

在某些情況下,我們可以從 REST API 中布林值的嚴格性質中受益。但是,這些情況應該以領域本身的約束為指導。

  • API 需要在嚴格性和靈活性之間取得平衡。根據定義,布林值是限制性的。
  • API 應該具有指導意義。領域語言應該在他們的API合約發光。合約中每個欄位的可能值應該很容易被發現。

相關文章