<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Modeling on Tarragon</title><link>https://tarrragon.github.io/blog/tags/modeling/</link><description>Recent content in Modeling on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Fri, 03 Jul 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/modeling/index.xml" rel="self" type="application/rss+xml"/><item><title>11.3 資源建模與操作語意</title><link>https://tarrragon.github.io/blog/backend/11-api-design/resource-modeling-operation-semantics/</link><pubDate>Fri, 03 Jul 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/backend/11-api-design/resource-modeling-operation-semantics/</guid><description>&lt;p>資源建模的核心決策是把業務操作對映成介面詞彙的方式。同一個「取消訂單」、可以建模成資源狀態的變更（&lt;code>PATCH /orders/{id}&lt;/code> 帶 &lt;code>status: cancelled&lt;/code>）、子資源的建立（&lt;code>POST /orders/{id}/cancellation&lt;/code>）、或動作端點（&lt;code>POST /orders/{id}/cancel&lt;/code>）— 三種寫法都在真實 API 裡大量存在、差異在演進空間、快取語意、跟消費者的心智模型。本章給建模決策的判準；本章的來源偏論證型（定義與判別法）、企業建模實作的公開案例在案例庫標為缺口、操作層展開以通用工程知識補充。&lt;/p>
&lt;h2 id="資源與表徵是兩層">資源與表徵是兩層&lt;/h2>
&lt;p>資源建模的第一個概念區分是資源（resource）與表徵（representation）：資源是被命名的概念實體、表徵是它在某次回應裡的具體格式。這個區分出自 REST 論文的 uniform interface 子約束 manipulation through representations — client 透過表徵操作資源（約束清單見 &lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/cases/rest-fielding-dissertation-ch5/" data-link-title="11.C1 Fielding 論文第 5 章：REST 是約束推導的架構風格" data-link-desc="REST 由六個約束從 null style 推導而來、uniform interface 以效率換一般性；所有 REST 論爭的定義基準">11.C1&lt;/a>、定義展開依論文原文）。工程意義：同一個資源可以有多種表徵（完整版、列表精簡版、不同版本的形狀）、表徵的形狀可以演進而資源身分不變 — URL 命名的是資源、欄位設計的是表徵、兩層的變更紀律不同。把這兩層混在一起的常見症狀是「加一個欄位要開一個新 endpoint」。&lt;/p>
&lt;h2 id="資源導向與動作導向的取捨">資源導向與動作導向的取捨&lt;/h2>
&lt;p>兩種建模方向各有成立情境、判準是操作的語意複雜度與演進預期。&lt;/p>
&lt;p>資源導向把業務操作收斂成「對某個名詞的狀態操作」：建立、讀取、更新、刪除、加上狀態欄位變更。收益是介面詞彙統一 — 消費者學會一個資源的操作方式、就會操作所有資源；快取、權限、審計都能按資源粒度統一處理。成本是有些操作硬塞進名詞會失真：「重算報表」「合併帳號」「試算價格」這類操作沒有自然的資源對應。&lt;/p>
&lt;p>動作導向（RPC 式端點）直接命名操作。收益是語意直白、參數自由；成本是介面詞彙發散 — 每個動作都是新詞彙、消費者要逐個學、橫切能力（快取、重試語意、權限）要逐個處理。&lt;/p>
&lt;p>務實的判準是混用、但混用要有規則：預設資源導向、動作導向保留給「狀態機轉換有業務儀式」的操作（下單、退款、發布）、且動作端點的回應仍回到資源表徵（回訂單、不回裸 ack）。這條規則讓橫切能力至少在回應側保持統一。跨資源的操作（轉帳、合併）建議建模成獨立資源（transfer、merge job）— 操作本身有生命週期、有查詢需求、有失敗狀態時、它就值得一個名詞。&lt;/p>
&lt;h2 id="http-method-與-status-是承諾不只是慣例">HTTP method 與 status 是承諾、不只是慣例&lt;/h2>
&lt;p>method 與 status 的選用向中介層與消費者承諾了行為性質、選錯的代價由基礎設施收取。GET 承諾安全（無副作用）— proxy 與瀏覽器會據此重試、預取、快取；PUT 承諾冪等 — client 可以直接重送、無需判斷前次結果；POST 兩者都沒承諾、所以需要冪等鍵機制補強（&lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/api-idempotency-design/" data-link-title="11.8 API 層冪等設計" data-link-desc="idempotency key 誰生成、存多久、replay 回什麼、衝突怎麼回 — 對外冪等契約的條款設計與無標準現況">11.8 API 層冪等設計&lt;/a> 主寫）。status 同理：2xx 對監控承諾成功、4xx 承諾「錯在請求、重試無用」（限流的 429 是明確例外、可重試但要等、見 &lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/external-traffic-semantics/" data-link-title="11.9 對外流量語意" data-link-desc="rate limit 對消費者承諾什麼、429 與 Retry-After 怎麼設計、配額 header 該不該信 — 限流作為契約的語意設計">11.9&lt;/a>）、5xx 承諾「錯在服務、可以重試」— 把業務失敗包在 200 裡回傳、等於對整條觀測與重試鏈說謊、錯誤率圖表從此失真。錯誤語意的完整設計是 &lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/error-model-design/" data-link-title="11.4 錯誤模型設計" data-link-desc="錯誤該分幾類、格式怎麼定才有演化空間、機器判讀跟人類訊息怎麼分工 — 錯誤作為契約一級公民的設計判準">11.4 錯誤模型設計&lt;/a> 的主題、本章只立「status 是給機器的承諾」這條判準。&lt;/p>
&lt;h2 id="available-actions-由誰計算">Available actions 由誰計算&lt;/h2>
&lt;p>資源當下可做什麼操作、有兩種回答方式 — 這是 hypermedia 爭論落到建模層的具體形式。htmx 的 HATEOAS essay 用透支帳戶做對照：HTML 表徵在透支時只回 deposit 連結、業務狀態直接編碼在可用操作裡、client 零業務知識；JSON 表徵回 &lt;code>status: &amp;quot;overdrawn&amp;quot;&lt;/code> 欄位、client 靠文件理解語意跟下一步（見 &lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/cases/rest-htmx-hateoas-html-necessity/" data-link-title="11.C5 htmx HATEOAS essay：透支帳戶的兩種表徵對照" data-link-desc="同一個 domain 狀態的 HTML 與 JSON 表徵耦合差異、HATEOAS 有無的操作型判別法">11.C5&lt;/a>）。由此得到的操作型判別法：&lt;strong>available actions 由 server 算完放進 response、還是 client 讀狀態欄位自己算&lt;/strong> — 前者是 hypermedia 路線、後者是業界主流的 JSON API 路線。&lt;/p>
&lt;p>判準層的建議：machine-to-machine 的 JSON API 走 client 自算是務實預設（消費者是程式、本來就要讀文件寫死邏輯）；但「狀態欄位 + 文件」的組合要把狀態機明文化 — 狀態列舉、每個狀態下的合法操作、非法操作回什麼錯誤。hypermedia 路線的完整論證與反方立場、收在 &lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/styles/rest/hypermedia-hateoas-revival/" data-link-title="Hypermedia 與 HATEOAS 復興" data-link-desc="復興派的論證本體：uniform client 前提、語意漂移史、格式標準化的失敗現實、反方的收益假設拆解 — 與 hypermedia 的適用邊界">Hypermedia 與 HATEOAS 復興&lt;/a>。&lt;/p>
&lt;p>Richardson 成熟度模型可以當這個決策的定位工具：Level 1（資源化）、Level 2（method 與 status 語意正確）、Level 3（hypermedia controls）。一手來源自己標注它是理解工具、非 REST 認證（見 &lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/cases/rest-fowler-richardson-maturity-model/" data-link-title="11.C3 Richardson 成熟度模型：分級階梯與它的自我聲明" data-link-desc="RMM 四級是理解 REST 元素的思考工具、一手來源自己警告它不是 REST 分級定義；業界停在 Level 2 的參照系">11.C3&lt;/a>）。用它描述「我們的 API 在哪、要不要往上」是合法用法、拿它當合規檢查表是誤用 — 完整的實用讀法與誤用邊界、主寫在 &lt;a href="https://tarrragon.github.io/blog/backend/11-api-design/styles/rest/richardson-maturity-practical-reading/" data-link-title="Richardson 成熟度的實用讀法" data-link-desc="RMM 四級當定位與溝通工具的用法、每一級的工程意義、以及把它當合規認證或升級路線圖的誤用邊界">Richardson 成熟度的實用讀法&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>資源建模的核心決策是把業務操作對映成介面詞彙的方式。同一個「取消訂單」、可以建模成資源狀態的變更（<code>PATCH /orders/{id}</code> 帶 <code>status: cancelled</code>）、子資源的建立（<code>POST /orders/{id}/cancellation</code>）、或動作端點（<code>POST /orders/{id}/cancel</code>）— 三種寫法都在真實 API 裡大量存在、差異在演進空間、快取語意、跟消費者的心智模型。本章給建模決策的判準；本章的來源偏論證型（定義與判別法）、企業建模實作的公開案例在案例庫標為缺口、操作層展開以通用工程知識補充。</p>
<h2 id="資源與表徵是兩層">資源與表徵是兩層</h2>
<p>資源建模的第一個概念區分是資源（resource）與表徵（representation）：資源是被命名的概念實體、表徵是它在某次回應裡的具體格式。這個區分出自 REST 論文的 uniform interface 子約束 manipulation through representations — client 透過表徵操作資源（約束清單見 <a href="/blog/backend/11-api-design/cases/rest-fielding-dissertation-ch5/" data-link-title="11.C1 Fielding 論文第 5 章：REST 是約束推導的架構風格" data-link-desc="REST 由六個約束從 null style 推導而來、uniform interface 以效率換一般性；所有 REST 論爭的定義基準">11.C1</a>、定義展開依論文原文）。工程意義：同一個資源可以有多種表徵（完整版、列表精簡版、不同版本的形狀）、表徵的形狀可以演進而資源身分不變 — URL 命名的是資源、欄位設計的是表徵、兩層的變更紀律不同。把這兩層混在一起的常見症狀是「加一個欄位要開一個新 endpoint」。</p>
<h2 id="資源導向與動作導向的取捨">資源導向與動作導向的取捨</h2>
<p>兩種建模方向各有成立情境、判準是操作的語意複雜度與演進預期。</p>
<p>資源導向把業務操作收斂成「對某個名詞的狀態操作」：建立、讀取、更新、刪除、加上狀態欄位變更。收益是介面詞彙統一 — 消費者學會一個資源的操作方式、就會操作所有資源；快取、權限、審計都能按資源粒度統一處理。成本是有些操作硬塞進名詞會失真：「重算報表」「合併帳號」「試算價格」這類操作沒有自然的資源對應。</p>
<p>動作導向（RPC 式端點）直接命名操作。收益是語意直白、參數自由；成本是介面詞彙發散 — 每個動作都是新詞彙、消費者要逐個學、橫切能力（快取、重試語意、權限）要逐個處理。</p>
<p>務實的判準是混用、但混用要有規則：預設資源導向、動作導向保留給「狀態機轉換有業務儀式」的操作（下單、退款、發布）、且動作端點的回應仍回到資源表徵（回訂單、不回裸 ack）。這條規則讓橫切能力至少在回應側保持統一。跨資源的操作（轉帳、合併）建議建模成獨立資源（transfer、merge job）— 操作本身有生命週期、有查詢需求、有失敗狀態時、它就值得一個名詞。</p>
<h2 id="http-method-與-status-是承諾不只是慣例">HTTP method 與 status 是承諾、不只是慣例</h2>
<p>method 與 status 的選用向中介層與消費者承諾了行為性質、選錯的代價由基礎設施收取。GET 承諾安全（無副作用）— proxy 與瀏覽器會據此重試、預取、快取；PUT 承諾冪等 — client 可以直接重送、無需判斷前次結果；POST 兩者都沒承諾、所以需要冪等鍵機制補強（<a href="/blog/backend/11-api-design/api-idempotency-design/" data-link-title="11.8 API 層冪等設計" data-link-desc="idempotency key 誰生成、存多久、replay 回什麼、衝突怎麼回 — 對外冪等契約的條款設計與無標準現況">11.8 API 層冪等設計</a> 主寫）。status 同理：2xx 對監控承諾成功、4xx 承諾「錯在請求、重試無用」（限流的 429 是明確例外、可重試但要等、見 <a href="/blog/backend/11-api-design/external-traffic-semantics/" data-link-title="11.9 對外流量語意" data-link-desc="rate limit 對消費者承諾什麼、429 與 Retry-After 怎麼設計、配額 header 該不該信 — 限流作為契約的語意設計">11.9</a>）、5xx 承諾「錯在服務、可以重試」— 把業務失敗包在 200 裡回傳、等於對整條觀測與重試鏈說謊、錯誤率圖表從此失真。錯誤語意的完整設計是 <a href="/blog/backend/11-api-design/error-model-design/" data-link-title="11.4 錯誤模型設計" data-link-desc="錯誤該分幾類、格式怎麼定才有演化空間、機器判讀跟人類訊息怎麼分工 — 錯誤作為契約一級公民的設計判準">11.4 錯誤模型設計</a> 的主題、本章只立「status 是給機器的承諾」這條判準。</p>
<h2 id="available-actions-由誰計算">Available actions 由誰計算</h2>
<p>資源當下可做什麼操作、有兩種回答方式 — 這是 hypermedia 爭論落到建模層的具體形式。htmx 的 HATEOAS essay 用透支帳戶做對照：HTML 表徵在透支時只回 deposit 連結、業務狀態直接編碼在可用操作裡、client 零業務知識；JSON 表徵回 <code>status: &quot;overdrawn&quot;</code> 欄位、client 靠文件理解語意跟下一步（見 <a href="/blog/backend/11-api-design/cases/rest-htmx-hateoas-html-necessity/" data-link-title="11.C5 htmx HATEOAS essay：透支帳戶的兩種表徵對照" data-link-desc="同一個 domain 狀態的 HTML 與 JSON 表徵耦合差異、HATEOAS 有無的操作型判別法">11.C5</a>）。由此得到的操作型判別法：<strong>available actions 由 server 算完放進 response、還是 client 讀狀態欄位自己算</strong> — 前者是 hypermedia 路線、後者是業界主流的 JSON API 路線。</p>
<p>判準層的建議：machine-to-machine 的 JSON API 走 client 自算是務實預設（消費者是程式、本來就要讀文件寫死邏輯）；但「狀態欄位 + 文件」的組合要把狀態機明文化 — 狀態列舉、每個狀態下的合法操作、非法操作回什麼錯誤。hypermedia 路線的完整論證與反方立場、收在 <a href="/blog/backend/11-api-design/styles/rest/hypermedia-hateoas-revival/" data-link-title="Hypermedia 與 HATEOAS 復興" data-link-desc="復興派的論證本體：uniform client 前提、語意漂移史、格式標準化的失敗現實、反方的收益假設拆解 — 與 hypermedia 的適用邊界">Hypermedia 與 HATEOAS 復興</a>。</p>
<p>Richardson 成熟度模型可以當這個決策的定位工具：Level 1（資源化）、Level 2（method 與 status 語意正確）、Level 3（hypermedia controls）。一手來源自己標注它是理解工具、非 REST 認證（見 <a href="/blog/backend/11-api-design/cases/rest-fowler-richardson-maturity-model/" data-link-title="11.C3 Richardson 成熟度模型：分級階梯與它的自我聲明" data-link-desc="RMM 四級是理解 REST 元素的思考工具、一手來源自己警告它不是 REST 分級定義；業界停在 Level 2 的參照系">11.C3</a>）。用它描述「我們的 API 在哪、要不要往上」是合法用法、拿它當合規檢查表是誤用 — 完整的實用讀法與誤用邊界、主寫在 <a href="/blog/backend/11-api-design/styles/rest/richardson-maturity-practical-reading/" data-link-title="Richardson 成熟度的實用讀法" data-link-desc="RMM 四級當定位與溝通工具的用法、每一級的工程意義、以及把它當合規認證或升級路線圖的誤用邊界">Richardson 成熟度的實用讀法</a>。</p>
<h2 id="判讀訊號">判讀訊號</h2>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>判讀</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>新功能反覆長出 <code>/doSomething</code> 端點</td>
          <td>缺混用規則、動作導向變成預設、橫切能力開始發散</td>
      </tr>
      <tr>
          <td>業務失敗回 200 + <code>success: false</code></td>
          <td>status 承諾失效、觀測與重試鏈失真、往錯誤模型章修</td>
      </tr>
      <tr>
          <td>消費者問「這個狀態下能不能呼叫 X」</td>
          <td>狀態機沒明文化、補狀態 × 操作對照表、比加欄位優先</td>
      </tr>
      <tr>
          <td>GET 端點被發現有副作用</td>
          <td>method 承諾違約、中介層重試會放大傷害、最高優先修</td>
      </tr>
  </tbody>
</table>
<p>四個訊號的損害半徑不同、排查順序從半徑最大的開始：GET 副作用會被中介層自動放大、屬立即修；200 包業務失敗污染整條觀測鏈、次之；端點增生與狀態機未明文是設計債、按迭代節奏收。</p>
<h2 id="邊界">邊界</h2>
<p>本章的建模判準以 HTTP+JSON 風格為主要語境。gRPC 與 GraphQL 的建模單位（service/method、type/field）有各自的紀律、收在對應流派層；事件式介面的建模（event schema）屬 <a href="/blog/backend/03-message-queue/" data-link-title="模組三：訊息佇列與事件傳遞" data-link-desc="整理 durable queue、broker、retry、outbox 與 idempotency 的後端實務">03 訊息佇列</a> 的範圍。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>資料層的結構設計：<a href="/blog/backend/01-database/schema-design/" data-link-title="1.2 Schema Design 與資料建模" data-link-desc="整理 table、index、key、partition、denormalization 與命名規則">1.2 Schema 設計</a>（資源表徵與資料表是兩層、交接處看這篇）</li>
<li>風格還沒定、先回：<a href="/blog/backend/11-api-design/api-style-selection/" data-link-title="11.2 風格選型總覽" data-link-desc="REST 式 HTTP&#43;JSON、GraphQL、gRPC、tRPC、JSON-RPC、event 之間選哪個 — 用消費者形狀、演進成本、操作可及性三軸判讀">11.2 風格選型總覽</a></li>
<li>承諾框架：<a href="/blog/backend/11-api-design/api-boundary-responsibility/" data-link-title="11.1 API 作為服務邊界的責任" data-link-desc="介面變更該由誰付成本、哪些介面性質算對外承諾、承諾違約有哪些模式 — 動手設計 endpoint 前的責任框架">11.1 API 作為服務邊界的責任</a></li>
<li>名詞層：<a href="/blog/backend/knowledge-cards/request-response-protocol/" data-link-title="Request/Response Protocol" data-link-desc="說明同步請求如何在 client 與 service 之間對齊互動規則">Request-Response Protocol</a>、<a href="/blog/backend/knowledge-cards/api-contract/" data-link-title="API Contract" data-link-desc="說明 request / response 邊界如何維持相容與可驗證">API Contract</a> 知識卡</li>
<li>案例原文：<a href="/blog/backend/11-api-design/cases/" data-link-title="模組十一案例庫：API 設計與對外契約" data-link-desc="API 風格流派、版本與相容、介面語意、規範治理的已驗證公開案例集；含反例與覆蓋缺口標明">模組十一案例庫</a></li>
</ul>
]]></content:encoded></item></channel></rss>