<?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/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/">
  <channel>
    <title>單元測試｜林鼎淵 Dean Lin</title>
    <link>https://deanlin.net/tags/%E5%96%AE%E5%85%83%E6%B8%AC%E8%A9%A6/</link>
    <image><url>https://deanlin.net/images/author_hu_aa256fc934e9a932.jpg</url><title>單元測試｜林鼎淵 Dean Lin</title><link>https://deanlin.net/tags/%E5%96%AE%E5%85%83%E6%B8%AC%E8%A9%A6/</link><width>144</width><height>144</height></image>
    <description>林鼎淵（Dean Lin）的部落格：生成式 AI 企業內訓講師、外商資安公司軟體專家、7 本書作者。400 多篇文章用白話分享生成式 AI 實戰、Claude Code 與 Vibe Coding 教學、團隊合作與職場成長。</description>
    <generator>Hugo</generator>
    <language>zh-tw</language>
    <copyright>© 2020–2026 林鼎淵 Dean Lin</copyright>
    <lastBuildDate>Fri, 01 Oct 2021 08:46:39 +0800</lastBuildDate>
    <atom:link href="https://deanlin.net/tags/%E5%96%AE%E5%85%83%E6%B8%AC%E8%A9%A6/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>[面試][後端]設計 API 時會考慮哪些點？</title>
      <link>https://deanlin.net/blog/202110/fullstack-career-notes-day-16/</link>
      <pubDate>Fri, 01 Oct 2021 08:46:39 +0800</pubDate>
      <guid>https://deanlin.net/blog/202110/fullstack-career-notes-day-16/</guid>
      <dc:creator>林鼎淵</dc:creator>
      <category>職涯成長</category>
      <description>既然 Junoir 跟 Senior 的後端工程師都能寫出可以運作的 API；那公司為什麼要多花錢請一個比較貴的工程師呢？</description>
      <media:content url="https://deanlin.net/blog/202110/fullstack-career-notes-day-16/images/cover_hu_7e037945b929f204.jpg" medium="image" type="image/jpeg" width="1200" height="675" />
      <content:encoded><![CDATA[<blockquote>
<p>你設計的 API 除了跑的動以外，它安全穩定嗎？</p>
</blockquote>
<p>既然 Junoir 跟 Senior 的後端工程師都能寫出可以運作的 API；那公司為什麼要多花錢請一個比較貴的工程師呢？</p>
<p>不僅面試官會問這個問題，你也要時常反問自己：「<mark>我憑什麼可以開出更高的薪水？我跟其他的工程師有哪裡不一樣？</mark>」</p>
<h2 id="大綱">大綱<a class="h-anchor" href="#%e5%a4%a7%e7%b6%b1" aria-label="這個段落的連結"></a></h2>
<ol>
<li><strong>設計 API 時會考慮哪些點？</strong>
<ul>
<li>1.1 面試官為什麼會問？</li>
<li>1.2 面試官想從答案確認什麼？</li>
<li>1.3 筆者提供的簡答</li>
</ul>
</li>
<li><strong>回答問題所需具備的知識</strong>
<ul>
<li>2.1 驗證 Client 端身份</li>
<li>2.2 了解後端驗證的重要性，並認識常見的 Validation Rule</li>
<li>2.3 優化後端的常見方法</li>
<li>2.4 淺談 Unit Test（單元測試）</li>
</ul>
</li>
<li><strong>衍伸問題</strong>
<ul>
<li>3.1 你知道 PUT &amp; PATCH 的差異嗎？</li>
<li>3.2 請舉例 RESTful api 的命名原則</li>
<li>3.3 GraphQL 跟 RESTful API 的差異在哪裡？</li>
</ul>
</li>
</ol>
<hr>
<h2 class="h-nomark" id="1-設計-api-時會考慮哪些點">1. 設計 API 時會考慮哪些點？<a class="h-anchor" href="#1-%e8%a8%ad%e8%a8%88-api-%e6%99%82%e6%9c%83%e8%80%83%e6%85%ae%e5%93%aa%e4%ba%9b%e9%bb%9e" aria-label="這個段落的連結"></a></h2>
<h3 class="h-nomark" id="11-面試官為什麼會問">1.1 面試官為什麼會問？<a class="h-anchor" href="#11-%e9%9d%a2%e8%a9%a6%e5%ae%98%e7%82%ba%e4%bb%80%e9%ba%bc%e6%9c%83%e5%95%8f" aria-label="這個段落的連結"></a></h3>
<p>能依照需求規格書寫好 API 只是對後端工程師的基礎要求；但這個 API 考慮的是否周全就看每個工程師的經驗了。</p>
<p>這算是<mark>常見面試題</mark>，面試官想從回答中了解你後端的實作經驗與基本功，並判斷你在進入團隊後是否需要花更多時間訓練才能成為有效戰力。</p>
<hr>
<h3 class="h-nomark" id="12-面試官想從答案確認什麼">1.2 面試官想從答案確認什麼？<a class="h-anchor" href="#12-%e9%9d%a2%e8%a9%a6%e5%ae%98%e6%83%b3%e5%be%9e%e7%ad%94%e6%a1%88%e7%a2%ba%e8%aa%8d%e4%bb%80%e9%ba%bc" aria-label="這個段落的連結"></a></h3>
<ul>
<li>你設計的 API 是否有防護的機制</li>
<li>當 Client 端傳入不符規範的參數及型態時，你的 API 是否有成為防線</li>
<li>你有用什麼方法保證 API 的穩定性</li>
<li>是否有思考過 API 的優化</li>
</ul>
<hr>
<h3 class="h-nomark" id="13-筆者提供的簡答">1.3 筆者提供的簡答<a class="h-anchor" href="#13-%e7%ad%86%e8%80%85%e6%8f%90%e4%be%9b%e7%9a%84%e7%b0%a1%e7%ad%94" aria-label="這個段落的連結"></a></h3>
<p>以過去設計的內部管理系統來說，Client 端在登入後會取得 JWT，之後在存取 API 前會用這個 <mark>JWT 來驗證是否有存取的權限</mark>；為了避免 Client 端使用不符規範的參數，我會先<mark>驗證每個傳入參數的格式</mark>，並撰寫 <code>Unit Test</code> 確保這隻 API 在不同情境下的 Response 都符合期待；再確認 API 的穩定性後，我會去思考還有什麼地方可以優化，讓 Client 端有更好的體驗。</p>
<hr>
<h2 class="h-nomark" id="2-回答問題所需具備的知識">2. 回答問題所需具備的知識<a class="h-anchor" href="#2-%e5%9b%9e%e7%ad%94%e5%95%8f%e9%a1%8c%e6%89%80%e9%9c%80%e5%85%b7%e5%82%99%e7%9a%84%e7%9f%a5%e8%ad%98" aria-label="這個段落的連結"></a></h2>
<h3 class="h-nomark" id="21-驗證-client-端身份">2.1 驗證 Client 端身份<a class="h-anchor" href="#21-%e9%a9%97%e8%ad%89-client-%e7%ab%af%e8%ba%ab%e4%bb%bd" aria-label="這個段落的連結"></a></h3>
<p>這邊帶讀者瞭解兩種主流驗證機制，大部分的框架都有提供對應的方案供開發人員使用。</p>
<ul>
<li><strong>Session 與 Cookie</strong><br>當 Client 端登入後，Server 會產生一筆 Session 並記錄（可能存在資料庫或記憶體），同時將可以識別身份的 SessionID 送回 Client 端儲存於 Cookie；此後 Client 端的請求，Server 只需要根據 Cookie 中的 SessionID 尋找 Session 來驗證使用者即可。
<ul>
<li><strong>使用 Session 要考量的問題</strong>
<ol>
<li>因為 Session 的資料存在 Server 中，需考慮同時有<mark>很多使用者上線時要面對的效能或是記憶體問題</mark>。
<ul>
<li><strong>解決方案</strong>：定期清理過期 Session。</li>
</ul>
</li>
<li>如果採取 Cluster 部署，就要考慮<mark>不同 Server 的 Session 共享問題</mark>。
<ul>
<li><strong>解決方案</strong>：Server 需設計 Session 同步機制（Replication）。</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
<li><strong>JSON Web Token（JWT）</strong><br>當 Client 端登入成功後，Server 會回傳一個 JWT，Client 端通常會將 JWT 儲存於 localstorage；當 Client 端打算訪問受保護的資源時，需要在 Header 的 Authorization 使用 Bearer 模式添加 JWT，如果驗證通過即可存取相關資源。
<ul>
<li><strong>使用 JWT 要考量的問題</strong>
<ol>
<li>在 Client 端取得 JWT 後，在 JWT 有效期內他都能夠使用；即使我們直接把使用者帳號刪除，這個 JWT 依舊可以訪問受保護的資源。
<ul>
<li><strong>解決方案</strong>：設計黑名單機制，使用記憶體資料庫維護一份黑名單，如果想讓某個 JWT 失效，把它加入黑名單就好了。</li>
</ul>
</li>
<li><mark>不要為了方便把 JWT 的有效期限設定太長</mark>，不然這個 JWT 洩露出去後，任何人都可以拿它來幹大事。
<ul>
<li><strong>解決方案</strong>：JWT 有效期限不要太長，同時使用 HTTPS 來減少盜用。</li>
</ul>
</li>
</ol>
</li>
</ul>
</li>
</ul>
<hr>
<h3 class="h-nomark" id="22-了解後端驗證的重要性並認識常見的-validation-rule">2.2 了解後端驗證的重要性，並認識常見的 Validation Rule<a class="h-anchor" href="#22-%e4%ba%86%e8%a7%a3%e5%be%8c%e7%ab%af%e9%a9%97%e8%ad%89%e7%9a%84%e9%87%8d%e8%a6%81%e6%80%a7%e4%b8%a6%e8%aa%8d%e8%ad%98%e5%b8%b8%e8%a6%8b%e7%9a%84-validation-rule" aria-label="這個段落的連結"></a></h3>
<p><mark>無論前端驗證做得多完美，後端驗證都是必須存在的</mark>；因為想攻擊系統的人不一定會從前端執行，直接 Call API 嘗試所有可能性的效率快多了；<mark>前端驗證可以大幅減少不必要的 Request 產生，後端驗證則是保護資料的最終防線</mark>。</p>
<ul>
<li><strong>為什麼要了解 Validation Rule？</strong>
<ul>
<li>你可以節省非常多親手撰寫 Function 的時間（自己寫的效能跟穩定度未必好，還很佔版面）。</li>
<li>這些不符規範的資料並不會進入後端運算的邏輯層面。</li>
<li>驗證發現錯誤就 Response Error，減少 Client 端等待時間。</li>
</ul>
</li>
</ul>
<p>接下來用情境來介紹幾個常見的 Validation Rule，不同框架的名字可能略有不同，我這邊以 <a href="https://laravel.tw/docs/5.0/validation#available-validation-rules">Laravel</a> 的為主。</p>
<ul>
<li><strong>驗證使用者註冊系統時填寫的參數</strong>
<ul>
<li>
<p>此為 Laravel 驗證傳入參數的程式，下方依據參數進行解說。</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-php" data-lang="php"><span style="display:flex;"><span><span style="color:#79c0ff">$validator</span> <span style="color:#ff7b72;font-weight:bold">=</span> Validator<span style="color:#ff7b72;font-weight:bold">::</span>make(<span style="color:#79c0ff">$request</span><span style="color:#ff7b72;font-weight:bold">-&gt;</span>all(), [
</span></span><span style="display:flex;"><span>  <span style="color:#a5d6ff">&#39;email&#39;</span> <span style="color:#ff7b72;font-weight:bold">=&gt;</span>  [<span style="color:#a5d6ff">&#39;required&#39;</span>, <span style="color:#a5d6ff">&#39;email&#39;</span>, <span style="color:#a5d6ff">&#39;string&#39;</span>, <span style="color:#a5d6ff">&#39;max:255&#39;</span>, <span style="color:#a5d6ff">&#39;unique:users&#39;</span>],
</span></span><span style="display:flex;"><span>  <span style="color:#a5d6ff">&#39;name&#39;</span> <span style="color:#ff7b72;font-weight:bold">=&gt;</span>  [<span style="color:#a5d6ff">&#39;required&#39;</span>, <span style="color:#a5d6ff">&#39;string&#39;</span>, <span style="color:#a5d6ff">&#39;max:50&#39;</span>],
</span></span><span style="display:flex;"><span>  <span style="color:#a5d6ff">&#39;password&#39;</span> <span style="color:#ff7b72;font-weight:bold">=&gt;</span> [<span style="color:#a5d6ff">&#39;required&#39;</span>, <span style="color:#a5d6ff">&#39;string&#39;</span>, <span style="color:#a5d6ff">&#39;max:255&#39;</span>, <span style="color:#a5d6ff">&#39;min:8&#39;</span>, <span style="color:#a5d6ff">&#39;regex:/^.*(?=.{8,})(?=.*?[a-zA-Z])(?=.*?[0-9]).*$/&#39;</span>, <span style="color:#a5d6ff">&#39;confirmed&#39;</span>]
</span></span><span style="display:flex;"><span>]);
</span></span></code></pre></div><ul>
<li><strong>email</strong><br>為必填 <code>required</code> 欄位，同時檢查傳入的字串是否符合 <code>email</code> 格式以及長度 <code>max</code> 是否超過限制，並確認這個 email 並沒有被註冊過 <code>unique</code>。</li>
<li><strong>name</strong><br>為必填 <code>required</code> 欄位，同時檢查傳入的字串長度 <code>max</code> 是否超過限制。</li>
<li><strong>password</strong><br>為必填 <code>required</code> 欄位，除了檢查傳入的字串長度 <code>max</code> 是否超過限制外，通常會限制最小長度 <code>min</code>；再嚴謹一點會要求 password 複雜度需包含英數字 <code>regex</code>，且內容與 password_confirmation 欄位相同 <code>confirmed</code>。</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h3 class="h-nomark" id="23-優化後端的常見方法">2.3 優化後端的常見方法<a class="h-anchor" href="#23-%e5%84%aa%e5%8c%96%e5%be%8c%e7%ab%af%e7%9a%84%e5%b8%b8%e8%a6%8b%e6%96%b9%e6%b3%95" aria-label="這個段落的連結"></a></h3>
<p>這邊先不討論程式語言和資料庫選擇帶來的影響，專注在共同可行性方案上。</p>
<ul>
<li><strong>操作資料庫時加入限制條件</strong><br>就算前端 Request 的參數沒有限制條件（ex：分頁、筆數、種類&hellip;），後端也要有意識的<mark>設定預設值</mark>，不然當資料量大的時候除了會跑很久浪費效能外，前端也不適合接收/呈現這麼多資訊。</li>
<li><strong>回傳前端的資料盡量是已經計算過的</strong><br>Client 端使用的機器效能未知，如果把太多的邏輯運算交給前端可能導致不好的使用者體驗；我這邊建議後端最好<mark>回傳計算後的資料</mark>，前端負責顯示為主，不過這塊也要看實際的業務量以及情境來 trade-off 。</li>
<li><strong>加入 CDN Cache</strong><br>如果遇到國外客戶抱怨連線速度很慢，就可以考慮採用 CDN 來解決這個問題；CDN 服務商的做法是將 Server 建置在世界各地，將網站上的靜態內容（圖片、影音、檔案）與動態內容（資料庫查詢）Cache 到 Server，<mark>根據訪客的地理位置，從最近的 Server 提供資料</mark>；好處如下：
<ul>
<li>提升網站的穩定度（如果某個 CDN Server 掛了也有替身）。</li>
<li>節省原本 Server 的頻寬（因為流量被分散了）。</li>
<li>改善使用者體驗（過去會卡住的都是大檔案，有了 CDN Cache 後瀏覽會更流暢）。</li>
</ul>
</li>
<li><strong>提升硬體水平</strong><br>江湖傳言：「效能不夠，機器來湊！」雖然聽起來好像是在開玩笑；但實際業務上如果真的遇到效能瓶頸，許多公司的做法就是<mark>先靠硬體讓服務穩定</mark>；服務穩定了，你才有心力去 Refactor 程式。</li>
</ul>
<hr>
<h3 class="h-nomark" id="24-淺談-unit-test單元測試">2.4 淺談 Unit Test（單元測試）<a class="h-anchor" href="#24-%e6%b7%ba%e8%ab%87-unit-test%e5%96%ae%e5%85%83%e6%b8%ac%e8%a9%a6" aria-label="這個段落的連結"></a></h3>
<ul>
<li><strong>為什麼 Unit Test 很重要？</strong>
<ul>
<li>有它保證<mark>程式碼的穩定性</mark>，發生錯誤時可以快速找到源頭，因此開發人員可以更大膽的開發。</li>
<li>減少手動測試的時間，大幅<mark>降低相關維運成本</mark>。</li>
<li>API 版本更新時（ex：v2 升級到 v3），<mark>確保舊版 API 可以正常運行</mark>。</li>
</ul>
</li>
<li><strong>Unit Test 使用時機</strong>
<ul>
<li>開發人員要先在本機 Run 過一遍，確認所有 Unit Test 都通過。</li>
<li>如果有使用 Git 做版本控制，在特定 branch 合併時 CI/CD 應該要有某個 Stage 來做測試，<mark>確保合併分支的程式正確性</mark>。</li>
</ul>
</li>
<li><strong>撰寫 Unit Test 基礎概念</strong>
<ul>
<li><strong>測試時使用（或自動建立）Mock data，不要動到 Server 資料</strong><br>Unit Test 著重在<mark>測試程式邏輯</mark>，建議測試時使用 Mock data，不然可能導致正式環境發生意外。</li>
<li><strong>測試要涵蓋你程式中的所有邏輯</strong>
<ul>
<li>假設一個 API 有 12 種回傳邏輯，你的 Unit Test 就要有 12 個；根據莫非定律，<mark>少寫的測試往往上線後就會爆掉</mark>。</li>
<li>如果 API 有做 JWT 防護、Request 參數驗證，我建議要<mark>把所有錯誤情境都做一次模擬</mark>；甚至要模擬 JWT 還在有效期，但實際權限已被移除的<mark>邊緣測試</mark>。</li>
</ul>
</li>
</ul>
</li>
</ul>
<blockquote>
<p>筆者聽過有些公司在專案正式 Release 時沒有撰寫任何的 Unit Test，直接讓客戶人肉測試，等客戶回報錯誤時再去修復 Bug；嗯&hellip;這種公司的離職率通常很高，因為有一堆歷史業障需要修但沒人敢碰。</p>
</blockquote>
<hr>
<h2 class="h-nomark" id="3-衍伸問題">3. 衍伸問題<a class="h-anchor" href="#3-%e8%a1%8d%e4%bc%b8%e5%95%8f%e9%a1%8c" aria-label="這個段落的連結"></a></h2>
<h3 class="h-nomark" id="31-你知道-put--patch-的差異嗎">3.1 你知道 PUT &amp; PATCH 的差異嗎？<a class="h-anchor" href="#31-%e4%bd%a0%e7%9f%a5%e9%81%93-put--patch-%e7%9a%84%e5%b7%ae%e7%95%b0%e5%97%8e" aria-label="這個段落的連結"></a></h3>
<p><mark>考點：對於 API 基礎操作的掌握程度</mark></p>
<p>「PUT」是<code>替換</code>資源，而「PATCH」則是<mark>更新部份</mark>資源內容；以使用者舉例，假設他有「姓名、簡介、年齡」這幾個欄位，如果想更新「姓名」的資訊：</p>
<ul>
<li>用 PUT 方法送出更新，除了「姓名」外還要填寫所有的欄位，如果沒填寫會導致其他的欄位更新成預設值。</li>
<li>用 PATCH 方法送出更新，只需填寫要更新的「姓名」欄位即可。</li>
</ul>
<hr>
<h3 class="h-nomark" id="32-請舉例-restful-api-的命名原則">3.2 請舉例 RESTful API 的命名原則<a class="h-anchor" href="#32-%e8%ab%8b%e8%88%89%e4%be%8b-restful-api-%e7%9a%84%e5%91%bd%e5%90%8d%e5%8e%9f%e5%89%87" aria-label="這個段落的連結"></a></h3>
<p><mark>考點：確認你寫 API 的習慣是否符合標準</mark></p>
<p>假設今天有一個 users 的 Table。</p>
<ul>
<li><strong>取得 user list</strong>
<ul>
<li><strong>方法</strong>：GET</li>
<li><strong>API 路徑</strong>：<code>/api/users</code></li>
</ul>
</li>
<li><strong>取得 user detail</strong>
<ul>
<li><strong>方法</strong>：GET</li>
<li><strong>API 路徑</strong>：<code>/api/users/{user_id}</code></li>
</ul>
</li>
<li><strong>新增 user</strong>
<ul>
<li><strong>方法</strong>：POST</li>
<li><strong>API 路徑</strong>：<code>/api/users</code></li>
</ul>
</li>
<li><strong>更新 user 資訊</strong>
<ul>
<li><strong>方法</strong>：PUT</li>
<li><strong>API 路徑</strong>：<code>/api/users/{user_id}</code></li>
</ul>
</li>
<li><strong>刪除 user</strong>
<ul>
<li><strong>方法</strong>：DELETE</li>
<li><strong>API 路徑</strong>：<code>/api/users/{user_id}</code></li>
</ul>
</li>
</ul>
<hr>
<h3 class="h-nomark" id="33-graphql-跟-restful-api-的差異在哪裡">3.3 GraphQL 跟 RESTful API 的差異在哪裡？<a class="h-anchor" href="#33-graphql-%e8%b7%9f-restful-api-%e7%9a%84%e5%b7%ae%e7%95%b0%e5%9c%a8%e5%93%aa%e8%a3%a1" aria-label="這個段落的連結"></a></h3>
<p><mark>考點：確認你對市場技術的認知程度</mark></p>
<p>過去 <code>RESTful API</code> 需要根據需求規格書給<mark>每個 API 設計回傳的資料結構</mark>，如果這個 API 在很多頁面被共用就有可能要回傳更多的資訊，但回傳的資訊中有些是只有特定頁面才有需求的，假使拆成多隻 API 也會導致日後維護困難；而 <code>GraphQL</code> 的出現正好解決了這個問題，他能夠<mark>由 Client 端來定義 Server 端要回傳的資料結構</mark>，不再回傳冗贅資訊。</p>
<ul>
<li>
<p><strong>補充：用範例了解兩者差異</strong><br>要查詢圖書館中特定書籍，回傳內容須包含：「作者、書名、出版年」。</p>
<ul>
<li><strong>GraphQL</strong>
<ul>
<li>
<p><strong>Client 端傳送的 query</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>query {
</span></span><span style="display:flex;"><span>  books (id<span style="color:#ff7b72;font-weight:bold">:</span><span style="color:#a5d6ff">12</span>) {
</span></span><span style="display:flex;"><span>    authors {
</span></span><span style="display:flex;"><span>        firstName
</span></span><span style="display:flex;"><span>        lastName
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    title
</span></span><span style="display:flex;"><span>    yearPublished
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div></li>
<li>
<p><strong>Server 端 Response 的 result</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#a5d6ff">&#34;data&#34;</span><span style="color:#ff7b72;font-weight:bold">:</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a5d6ff">&#34;books&#34;</span><span style="color:#ff7b72;font-weight:bold">:</span> {
</span></span><span style="display:flex;"><span>      <span style="color:#a5d6ff">&#34;authors&#34;</span><span style="color:#ff7b72;font-weight:bold">:</span> [
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>          <span style="color:#a5d6ff">&#34;firstName&#34;</span><span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#34;Lin&#34;</span>,
</span></span><span style="display:flex;"><span>          <span style="color:#a5d6ff">&#34;lastName&#34;</span><span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#34;Dean&#34;</span>
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>      ],
</span></span><span style="display:flex;"><span>      <span style="color:#a5d6ff">&#34;title&#34;</span><span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#34;全端工程師生存筆記&#34;</span>,
</span></span><span style="display:flex;"><span>      <span style="color:#a5d6ff">&#34;yearPublished&#34;</span><span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#34;2022&#34;</span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div></li>
</ul>
</li>
<li><strong>RESTful API</strong>
<ul>
<li>
<p><strong>Client 端的 Request</strong><br>需要拆成<code>GET api/books/12</code>、<code>GET api/authors/12</code>來分別取得書籍、作者資訊。</p>
</li>
<li>
<p><strong>Server 端 Response 的 result</strong><br><code>GET api/books/12</code></p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#a5d6ff">&#34;title&#34;</span> <span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#34;全端工程師生存筆記&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a5d6ff">&#34;authorID&#34;</span><span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">12</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a5d6ff">&#34;yearPublished&#34;</span> <span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">2022</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a5d6ff">&#34;page&#34;</span><span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">168</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a5d6ff">&#34;tags&#34;</span><span style="color:#ff7b72;font-weight:bold">:</span> [<span style="color:#a5d6ff">&#34;履歷&#34;</span><span style="color:#f85149">、</span><span style="color:#a5d6ff">&#34;面試&#34;</span><span style="color:#f85149">、</span><span style="color:#a5d6ff">&#34;職場&#34;</span>]
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><code>GET api/authors/12</code></p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#a5d6ff">&#34;firstName&#34;</span><span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#34;Lin&#34;</span>,
</span></span><span style="display:flex;"><span>  <span style="color:#a5d6ff">&#34;lastName&#34;</span><span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#34;Dean&#34;</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div></li>
</ul>
</li>
</ul>
<p>在上面的範例中，RESTful API 需要兩個 Request 才能取得完整資料，如果想用一個 Request 取得完整資料就要重新建立一支 API；比較起來<mark>GraphQL 對前端工程師來說是更好使用的工具</mark>；不過轉換與建立的成本較 RESTful API 高，如果想嘗試 GraphQL 帶來的效益，可以考慮漸進式的遷移。</p>
</li>
</ul>
<hr>
<p>感謝大家的閱讀，如果喜歡我的文章可以<code>訂閱</code>接收通知；如果有幫助到你，按<code>Like</code>可以讓我更有寫文的動力，我們明天見～</p>
<h3 id="參考資源">參考資源<a class="h-anchor" href="#%e5%8f%83%e8%80%83%e8%b3%87%e6%ba%90" aria-label="這個段落的連結"></a></h3>
<ol>
<li><a href="https://ithelp.ithome.com.tw/articles/10224134">進階 RESTful API 討論</a></li>
<li><a href="https://medium.com/%E9%BA%A5%E5%85%8B%E7%9A%84%E5%8D%8A%E8%B7%AF%E5%87%BA%E5%AE%B6%E7%AD%86%E8%A8%98/2e64d72594f8">透過 JWT 實作驗證機制</a></li>
<li><a href="https://blog.yyisyou.tw/5d272c64/">認識 Cookie、Session、Token 與 JWT</a></li>
<li><a href="https://segmentfault.com/a/1190000021810849">簡單聊一聊 Cookie、Session、Token、JWT 的區別和作用</a></li>
</ol>
<hr>
<hr>
<blockquote>
<p><img src="https://deanlin.net/blog/202110/fullstack-career-notes-day-16/images/fullstack-career-notes-day-16-01.webp" width="1024" height="233" alt="參考資源（圖 1）" fetchpriority="high" decoding="async"></p>
<p>在許多人的幫助下，本系列文章已成功出版，除了添加新的篇章，更完善了每個案例的應對進退；如果對現在的職涯感到迷茫，也許這本書能帶給你不一樣的觀點～</p>
<p><strong>天瓏書局：</strong> <a href="https://www.tenlong.com.tw/products/9786263334571">https://www.tenlong.com.tw/products/9786263334571</a></p>
</blockquote>
]]></content:encoded>
    </item>
  </channel>
</rss>
