<?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>Backend Development｜林鼎淵 Dean Lin</title>
    <link>https://deanlin.net/tags/backend-development/</link>
    <image><url>https://deanlin.net/images/author_hu_aa256fc934e9a932.jpg</url><title>Backend Development｜林鼎淵 Dean Lin</title><link>https://deanlin.net/tags/backend-development/</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>Wed, 23 Feb 2022 17:53:45 +0800</lastBuildDate>
    <atom:link href="https://deanlin.net/tags/backend-development/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>[前端＆後端]工程師常犯的錯誤 — 下班有約系列文</title>
      <link>https://deanlin.net/blog/202202/common-frontend-backend-mistakes/</link>
      <pubDate>Wed, 23 Feb 2022 17:53:45 +0800</pubDate>
      <guid>https://deanlin.net/blog/202202/common-frontend-backend-mistakes/</guid>
      <dc:creator>林鼎淵</dc:creator>
      <category>技術教學</category>
      <description>筆者跟擔任 Tech Lead 的朋友聊天時，發現在幫新人 Code Review、Code Refactoring、Bug Fix 時遇到了許多類似的問題，針對這個部分我安排了 3 篇文章做講解，今天這篇文章我挑選了幾個工程師常犯的錯誤來分享。</description>
      <media:content url="https://deanlin.net/blog/202202/common-frontend-backend-mistakes/images/common-frontend-backend-mistakes-og_hu_aaf049d3404ffd4c.jpg" medium="image" type="image/jpeg" width="1200" height="675" />
      <content:encoded><![CDATA[<p>筆者跟擔任 Tech Lead 的朋友聊天時，發現在幫新人 Code Review、Code Refactoring、Bug Fixing 時遇到了許多類似的問題，針對這個部分我安排了 3 篇文章做講解，今天這篇文章我挑選了幾個工程師常犯的錯誤來分享。</p>
<p><img src="https://deanlin.net/blog/202202/common-frontend-backend-mistakes/images/common-frontend-backend-mistakes-01.webp" width="1400" height="745" alt="\[前端＆後端\]工程師常犯的錯誤 — 下班有約系列文（圖 1）" fetchpriority="high" decoding="async"></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:#f85149">➤</span> 保留太多無用的 console.log
</span></span><span style="display:flex;"><span><span style="color:#f85149">➤</span> 沒有註明輸出的 console.log 要做什麼事
</span></span><span style="display:flex;"><span><span style="color:#f85149">➤</span> 忽視 Console 吐出的警告<span style="color:#f85149">、</span>錯誤
</span></span><span style="display:flex;"><span><span style="color:#f85149">➤</span> 不同函式共用<span style="color:#f85149">「</span>命名相同的全域變數<span style="color:#f85149">」</span>
</span></span><span style="display:flex;"><span><span style="color:#f85149">➤</span> 大量存取不必要的 API
</span></span><span style="display:flex;"><span><span style="color:#f85149">➤</span> 將很多用不到程式碼註解而非刪除
</span></span><span style="display:flex;"><span><span style="color:#f85149">➤</span> 沒寫註解<span style="color:#f85149">，</span>或是寫沒有意義的註解
</span></span><span style="display:flex;"><span><span style="color:#f85149">➤</span> Copy <span style="color:#ff7b72;font-weight:bold">&amp;</span> Paste 後<span style="color:#f85149">，</span>Function<span style="color:#f85149">、</span>Variable 命名沒有改
</span></span><span style="display:flex;"><span><span style="color:#f85149">➤</span> 沒有寫 <span style="color:#ff7b72">try</span> <span style="color:#ff7b72">catch</span>
</span></span><span style="display:flex;"><span><span style="color:#f85149">➤</span> 在他人協助下完成功能後<span style="color:#f85149">，</span>沒有真正了解原理
</span></span><span style="display:flex;"><span><span style="color:#f85149">➤</span> 沒有做 Refactoring
</span></span><span style="display:flex;"><span><span style="color:#f85149">➤</span> 詢問別人前沒有自己嘗試
</span></span><span style="display:flex;"><span><span style="color:#f85149">➤</span> 詢問的問題不夠精確
</span></span><span style="display:flex;"><span><span style="color:#f85149">➤</span> 管理者權限與使用者權限混在一起
</span></span></code></pre></div><h2 id="-保留太多無用的-consolelog">保留太多無用的 console.log<a class="h-anchor" href="#-%e4%bf%9d%e7%95%99%e5%a4%aa%e5%a4%9a%e7%84%a1%e7%94%a8%e7%9a%84-consolelog" aria-label="這個段落的連結"></a></h2>
<p>為了追蹤資料流向，我們會用 console.log 來確認程式是否依照我們的想法在執行；但有不少人只會一直增加新的 console.log，而不把已經不需要的 console.log 給移除。</p>
<h2 id="-沒有註明輸出的-consolelog-要做什麼事">沒有註明輸出的 console.log 要做什麼事<a class="h-anchor" href="#-%e6%b2%92%e6%9c%89%e8%a8%bb%e6%98%8e%e8%bc%b8%e5%87%ba%e7%9a%84-consolelog-%e8%a6%81%e5%81%9a%e4%bb%80%e9%ba%bc%e4%ba%8b" aria-label="這個段落的連結"></a></h2>
<p>筆者曾在按下 F12 開啟開發人員工具幫人 debug 時，看到 Console 這個分頁下印出一堆 API 回傳的 response data，但命名完全一樣都叫「result」，這樣我完全無法知道這些 result 是由哪個 API 回傳的ＱＱ</p>
<p><img src="https://deanlin.net/blog/202202/common-frontend-backend-mistakes/images/common-frontend-backend-mistakes-02.webp" width="862" height="433" alt="沒有註明輸出的 console.log 要做什麼事（圖 2）" loading="lazy" decoding="async"></p>
<p>不然就是很多意義不明只有自己才知道是什麼意思的 console.log（這類型的往往一個月後連本人都不知道在做什麼…）</p>
<p><img src="https://deanlin.net/blog/202202/common-frontend-backend-mistakes/images/common-frontend-backend-mistakes-03.webp" width="862" height="509" alt="沒有註明輸出的 console.log 要做什麼事（圖 3）" loading="lazy" decoding="async"></p>
<h2 id="-忽視-console-吐出的警告錯誤">忽視 Console 吐出的警告、錯誤<a class="h-anchor" href="#-%e5%bf%bd%e8%a6%96-console-%e5%90%90%e5%87%ba%e7%9a%84%e8%ad%a6%e5%91%8a%e9%8c%af%e8%aa%a4" aria-label="這個段落的連結"></a></h2>
<p>有些網頁看似運行的很正常，但在按下 F12 開啟開發人員工具後，你會看到一排讓人血壓上升的紅色 Error Message，如果沒有及時處理遲早有一天會業力引爆的。</p>
<p><img src="https://deanlin.net/blog/202202/common-frontend-backend-mistakes/images/common-frontend-backend-mistakes-04.webp" width="862" height="712" alt="忽視 Console 吐出的警告、錯誤（圖 4）" loading="lazy" decoding="async"></p>
<h2 id="-不同函式共用命名相同的全域變數">不同函式共用「命名相同的全域變數」<a class="h-anchor" href="#-%e4%b8%8d%e5%90%8c%e5%87%bd%e5%bc%8f%e5%85%b1%e7%94%a8%e5%91%bd%e5%90%8d%e7%9b%b8%e5%90%8c%e7%9a%84%e5%85%a8%e5%9f%9f%e8%ae%8a%e6%95%b8" aria-label="這個段落的連結"></a></h2>
<p>像是 Vue 框架下用來儲存變數資訊的 「Vuex」，裡面 State 的資訊是可以在多個頁面共同使用，下面舉例幾個不夠謹慎會造成的問題：</p>
<ul>
<li>如果在 loading 資料前沒有清空先前的 state 資訊，會導致進入頁面時會閃現上一次進入的資料。</li>
<li>如果把第幾頁(page)、分頁筆數(per-page)這些參數在多個頁面共用，那你就會看到有些頁面明明是第一次進入，卻跳轉到其他頁數。</li>
</ul>
<h2 id="-大量存取不必要的-api">大量存取不必要的 API<a class="h-anchor" href="#-%e5%a4%a7%e9%87%8f%e5%ad%98%e5%8f%96%e4%b8%8d%e5%bf%85%e8%a6%81%e7%9a%84-api" aria-label="這個段落的連結"></a></h2>
<p>這裡舉出兩個常見的例子：</p>
<ul>
<li>登入後就「一次呼叫所有的 API」，但許多 API 回傳的資料可能使用者根本還用不到。</li>
</ul>
<blockquote>
<p>這邊提醒一下，適當的「預載」可以增加使用者體驗，但如果在系統首頁就全部載入，除了會消耗使用者的資源外，一旦大量使用者同時上線，對伺服器端會造成很大的壓力。</p>
</blockquote>
<ul>
<li>有些搜尋功能會隨著使用者填入的文字去呼叫 API 來即時顯示搜尋結果或是建議關鍵字（ex：Google），但如果沒有把呼叫 API 的時間間隔設定好（debounceTime），使用者又不停更改搜尋列文字，那就會呼叫非常多不必要的 API。</li>
</ul>
<h2 id="-將用不到程式碼註解而非刪除">將用不到程式碼註解而非刪除<a class="h-anchor" href="#-%e5%b0%87%e7%94%a8%e4%b8%8d%e5%88%b0%e7%a8%8b%e5%bc%8f%e7%a2%bc%e8%a8%bb%e8%a7%a3%e8%80%8c%e9%9d%9e%e5%88%aa%e9%99%a4" aria-label="這個段落的連結"></a></h2>
<p>在開發階段有時會想到很多的解決方案，因為不確定哪個效能較高，所以就把每個演算法實現出來。</p>
<p>但有些人在決定使用某個解決方案後，依舊沒把其他的方案刪除，這樣的做法容易造成未來維護的困難度。</p>
<h2 id="-沒寫註解或是寫沒有意義的註解">沒寫註解，或是寫沒有意義的註解<a class="h-anchor" href="#-%e6%b2%92%e5%af%ab%e8%a8%bb%e8%a7%a3%e6%88%96%e6%98%af%e5%af%ab%e6%b2%92%e6%9c%89%e6%84%8f%e7%be%a9%e7%9a%84%e8%a8%bb%e8%a7%a3" aria-label="這個段落的連結"></a></h2>
<p>雖然有神人說過：最好的註解就是程式碼本身</p>
<p>但我想：「<strong>絕大多數的人都難以到達這個境界，所以要乖乖地寫註解ＸＤ」</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 style="color:#ff7b72">let</span> mode <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#a5d6ff">0</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">// do somethings ...
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">if</span> (mode <span style="color:#ff7b72;font-weight:bold">===</span> <span style="color:#a5d6ff">0</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#8b949e;font-style:italic">// excute logic 1
</span></span></span><span style="display:flex;"><span>} <span style="color:#ff7b72">else</span> <span style="color:#ff7b72">if</span> (mode <span style="color:#ff7b72;font-weight:bold">===</span> <span style="color:#a5d6ff">1</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#8b949e;font-style:italic">// excute logic 2
</span></span></span><span style="display:flex;"><span>} <span style="color:#ff7b72">else</span> <span style="color:#ff7b72">if</span> (mode <span style="color:#ff7b72;font-weight:bold">===</span> <span style="color:#a5d6ff">2</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#8b949e;font-style:italic">// excute logic 3
</span></span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p class="code-source">原始碼：<a href="https://gist.github.com/dean9703111/463d3dc91bc4e9789a29bcc4323560d9" rel="noopener">bad_remark_example.js</a>（GitHub Gist）</p>
<p>像是上面這段 Code，我們可以知道 mode 這個變數應該是應用在某個狀態的判斷上；但具體在哪個地方使用、總共有哪些狀態、各自代表什麼意義，在沒有註解的狀態下只能一行一行的閱讀，沒辦法第一時間理解程式。</p>
<h3 class="h-nomark" id="-註解的好處">👍 註解的好處<a class="h-anchor" href="#-%e8%a8%bb%e8%a7%a3%e7%9a%84%e5%a5%bd%e8%99%95" aria-label="這個段落的連結"></a></h3>
<ol>
<li>交代前因後果：為什麼這樣寫?遇到了什麼困難?解決了什麼問題?</li>
<li>作為文件說明：有些技術是需要被學習後才能夠看得懂的(ex:引入的模組、套件)，你的註解能讓他快速理解這些工具怎麼使用</li>
</ol>
<h3 class="h-nomark" id="-請不要有註解如下">🙅 請不要有註解如下<a class="h-anchor" href="#-%e8%ab%8b%e4%b8%8d%e8%a6%81%e6%9c%89%e8%a8%bb%e8%a7%a3%e5%a6%82%e4%b8%8b" aria-label="這個段落的連結"></a></h3>
<ol>
<li>毫無意義的牢騷(ex:我好崩潰啊，這段程式我寫了一個禮拜…)</li>
<li>把註解當成版本控制(ex:2020/08/23 完成此函式)</li>
<li>說明這段程式是誰寫的(簽名檔)</li>
<li>把舊的程式碼註解起來怕以後會用到(但通常再也不會用到，而且這個問題用版控就能解決)</li>
</ol>
<h2 id="-copy--paste-後functionvariable-命名沒有改">Copy &amp; Paste 後，Function、Variable 命名沒有改<a class="h-anchor" href="#-copy--paste-%e5%be%8cfunctionvariable-%e5%91%bd%e5%90%8d%e6%b2%92%e6%9c%89%e6%94%b9" aria-label="這個段落的連結"></a></h2>
<p>如果寫專案時發現之前做過類似的功能，我們會複製過來再做微調，以此加快開發的速度。</p>
<p>但<strong>請修改 Function、Variable 命名！</strong>這不會花你太多時間，但在未來當你需要維護專案時，你會感謝現在的自己。</p>
<blockquote>
<p>筆者之前曾在幫忙 Debug 時，於Ａ系統裡面看到一堆Ｂ系統的命名，當下還以為自己開錯專案了…</p>
</blockquote>
<h2 id="-沒有寫-try-catch">沒有寫 try catch<a class="h-anchor" href="#-%e6%b2%92%e6%9c%89%e5%af%ab-try-catch" aria-label="這個段落的連結"></a></h2>
<p>程式在缺乏 try-catch 的機制下是非常脆弱的，只要發生例外事件就容易崩潰。</p>
<p>如果你直接假定 API 只會回傳正確的資訊，而沒有撰寫 try-catch 去捕捉可能的 400、500 系列錯誤，就很可能導致系統許多行為錯誤如：</p>
<ol>
<li>跳轉到無權限的頁面</li>
<li>程式進入無限迴圈</li>
<li>瘋狂 Call 某隻 API 直到變成 429 錯誤（Too Many Requests）</li>
</ol>
<h2 id="-在他人協助下完成功能後沒有真正了解原理">在他人協助下完成功能後，沒有真正了解原理<a class="h-anchor" href="#-%e5%9c%a8%e4%bb%96%e4%ba%ba%e5%8d%94%e5%8a%a9%e4%b8%8b%e5%ae%8c%e6%88%90%e5%8a%9f%e8%83%bd%e5%be%8c%e6%b2%92%e6%9c%89%e7%9c%9f%e6%ad%a3%e4%ba%86%e8%a7%a3%e5%8e%9f%e7%90%86" aria-label="這個段落的連結"></a></h2>
<p>我相信大部分的人都是樂於幫助別人解決問題的，但同時也相信，沒有人希望再次被「相同的問題」打擾。</p>
<p>我這邊強烈建議請他人協助問題前，先 commit 一版，這樣無論對方成功還是失敗，你都有一個記錄在。</p>
<p>如果對方成功解決這個問題，一定找時間回到當時 commit 的那版，用自己的邏輯把功能完成；<strong>請記住，別人完成的任務不會自動成為你的知識。</strong></p>
<h2 id="-沒有做-refactoring">沒有做 Refactoring<a class="h-anchor" href="#-%e6%b2%92%e6%9c%89%e5%81%9a-refactoring" aria-label="這個段落的連結"></a></h2>
<p>演算法相關的 Refactor 有一定的難度，但有一些很基礎的 Refactor 我認為是有必要的，像是變數命名這一塊。</p>
<p>我們先來看一個不好的範例：</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 style="color:#ff7b72">let</span> result <span style="color:#ff7b72;font-weight:bold">=</span> responseData;
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">if</span> (result[result.length <span style="color:#ff7b72;font-weight:bold">-</span> <span style="color:#a5d6ff">1</span>]) {
</span></span><span style="display:flex;"><span>  <span style="color:#ff7b72">if</span> (<span style="color:#a5d6ff">&#34;check_in&#34;</span> <span style="color:#ff7b72">in</span> result[result.length <span style="color:#ff7b72;font-weight:bold">-</span> <span style="color:#a5d6ff">1</span>] <span style="color:#ff7b72;font-weight:bold">&amp;&amp;</span> result[result.length <span style="color:#ff7b72;font-weight:bold">-</span> <span style="color:#a5d6ff">1</span>].check_in <span style="color:#ff7b72;font-weight:bold">!==</span> <span style="color:#79c0ff">null</span>) {
</span></span><span style="display:flex;"><span>    state.check_in <span style="color:#ff7b72;font-weight:bold">=</span> result[<span style="color:#a5d6ff">0</span>].check_in.toString();
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">if</span> (result[result.length <span style="color:#ff7b72;font-weight:bold">-</span> <span style="color:#a5d6ff">1</span>]) {
</span></span><span style="display:flex;"><span>  <span style="color:#ff7b72">if</span> (<span style="color:#a5d6ff">&#34;check_out&#34;</span> <span style="color:#ff7b72">in</span> result[result.length <span style="color:#ff7b72;font-weight:bold">-</span> <span style="color:#a5d6ff">1</span>] <span style="color:#ff7b72;font-weight:bold">&amp;&amp;</span> result[result.length <span style="color:#ff7b72;font-weight:bold">-</span> <span style="color:#a5d6ff">1</span>].check_out <span style="color:#ff7b72;font-weight:bold">!==</span> <span style="color:#79c0ff">null</span>) {
</span></span><span style="display:flex;"><span>    state.check_out <span style="color:#ff7b72;font-weight:bold">=</span> result[result.length <span style="color:#ff7b72;font-weight:bold">-</span> <span style="color:#a5d6ff">1</span>].check_out.toString();
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p class="code-source">原始碼：<a href="https://gist.github.com/dean9703111/3c6c9d59d698b8738771eee07056b8fd" rel="noopener">need_refactor.js</a>（GitHub Gist）</p>
<p>上面這個是要取得回傳的「最後一筆」資料做邏輯處理，但是全部都使用「<strong>result[result.length -1]</strong>」來表示，相信大家都會看得有點眼花。</p>
<p>下面我們做個簡單的 Refactor，看起來就會舒服很多：</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 style="color:#ff7b72">let</span> result <span style="color:#ff7b72;font-weight:bold">=</span> [];
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">let</span> last_record <span style="color:#ff7b72;font-weight:bold">=</span> result[result.length <span style="color:#ff7b72;font-weight:bold">-</span> <span style="color:#a5d6ff">1</span>];
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">if</span> (last_record) {
</span></span><span style="display:flex;"><span>  <span style="color:#ff7b72">if</span> (<span style="color:#a5d6ff">&#34;check_in&#34;</span> <span style="color:#ff7b72">in</span> last_record <span style="color:#ff7b72;font-weight:bold">&amp;&amp;</span> last_record.check_in <span style="color:#ff7b72;font-weight:bold">!==</span> <span style="color:#79c0ff">null</span>) {
</span></span><span style="display:flex;"><span>    state.check_in <span style="color:#ff7b72;font-weight:bold">=</span> last_record.check_in.toString();
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">if</span> (last_record) {
</span></span><span style="display:flex;"><span>  <span style="color:#ff7b72">if</span> (<span style="color:#a5d6ff">&#34;check_out&#34;</span> <span style="color:#ff7b72">in</span> last_record <span style="color:#ff7b72;font-weight:bold">&amp;&amp;</span> last_record.check_out <span style="color:#ff7b72;font-weight:bold">!==</span> <span style="color:#79c0ff">null</span>) {
</span></span><span style="display:flex;"><span>    state.check_out <span style="color:#ff7b72;font-weight:bold">=</span> last_record.check_out.toString();
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p class="code-source">原始碼：<a href="https://gist.github.com/dean9703111/f9afe9487cbf14ddec3b92a61335f2f5" rel="noopener">after_refactor.js</a>（GitHub Gist）</p>
<h2 id="-詢問別人前沒有自己嘗試">詢問別人前沒有自己嘗試<a class="h-anchor" href="#-%e8%a9%a2%e5%95%8f%e5%88%a5%e4%ba%ba%e5%89%8d%e6%b2%92%e6%9c%89%e8%87%aa%e5%b7%b1%e5%98%97%e8%a9%a6" aria-label="這個段落的連結"></a></h2>
<p>有些人在遇到問題時沒有先從網路找資料，而是遇到問題先問同事、前輩。</p>
<p>儘管這樣可以最快速得到解答，但卻少了很多自我思考的部分，長期來講對工程師職涯是非常不健康的。</p>
<h2 id="-詢問的問題不夠精確">詢問的問題不夠精確<a class="h-anchor" href="#-%e8%a9%a2%e5%95%8f%e7%9a%84%e5%95%8f%e9%a1%8c%e4%b8%8d%e5%a4%a0%e7%b2%be%e7%a2%ba" aria-label="這個段落的連結"></a></h2>
<p>有時會收到主旨模糊的問題，像是：「這個搜尋功能常常會 fail，可以幫我看看嗎？」</p>
<p>如果可以，收到問題的人會希望問題敘述微調一下：「在人資系統中，我如果在職員列表頁面的搜尋條件中加入部門篩選，會發現搜尋出的結果不合預期，有時會找出其他部門的人員，可以幫我看一下是不是資料庫語法錯誤呢？」</p>
<blockquote>
<p><strong>結構為</strong>：哪個系統-&gt;哪個頁面-&gt;你調整了哪些參數-&gt;錯誤結果為何-&gt;初步判定錯誤來源</p>
</blockquote>
<h2 id="-管理者權限與使用者權限混在一起">管理者權限與使用者權限混在一起<a class="h-anchor" href="#-%e7%ae%a1%e7%90%86%e8%80%85%e6%ac%8a%e9%99%90%e8%88%87%e4%bd%bf%e7%94%a8%e8%80%85%e6%ac%8a%e9%99%90%e6%b7%b7%e5%9c%a8%e4%b8%80%e8%b5%b7" aria-label="這個段落的連結"></a></h2>
<p>很多系統都會分成前台（一般使用者）以及後台（管理者），有時後端為了增加程式共用率，而讓他們使用同一隻 API 存取資料，如果權限有設計好那沒問題，但如果沒設計好可能就出大包了。</p>
<p>以人資系統來說，假設有一隻 API 是用來存取個人資訊的，API 格式為：「users/{user}」</p>
<p>假使把這隻 API 共用，一般使用者透過修改中間的「user id」就有可能看到其他人的隱私資訊，這在資訊安全上是非常危險的。</p>
<p>因此建議將一般使用者與管理者的 API 切割清楚，避免讓使用者看到權限外的資料。</p>
<hr>
<blockquote class="pullquote"><p>筆者曾經犯過文章中許多錯誤，沒有人一開始就是強者，但至少要走在變強的道路上。</p>
</blockquote>
<p><strong>如果你對目前的職涯感到迷茫，想從不同視角檢視自己的選擇，相信《<a href="https://www.tenlong.com.tw/products/9786264142083">工程師下班有約</a>》這本書能為你帶來靈感與啟發：</strong></p>
<figure class="figure"><img src="https://deanlin.net/blog/202202/common-frontend-backend-mistakes/images/common-frontend-backend-mistakes-05.webp" width="1400" height="319" alt="林鼎淵著作《工程師下班有約：企業內訓講師帶你認清職涯真相！》" loading="lazy" decoding="async">
  <figcaption><a href="https://www.tenlong.com.tw/products/9786264142083">https://www.tenlong.com.tw/products/9786264142083</a></figcaption>
</figure>

<pre tabindex="0"><code>下班有約系列文
▋ [前端]新手工程師容易卡住的問題
▋ [前端＆後端]工程師常犯的錯誤(本篇)
▋ 讓開發團隊更好協作的方式
▋ 談談 Pair Programing
▋ 談談工程師的話語權
▋ 出社會後，新鮮人要及早知道的 5 件事
▋ 面試的性向測驗竟然準到讓人心裡發寒？
▋ 反其道而行的任務分配
▋ 現在的 Daily Scrum 真的適合團隊嗎？
▋ 用低成本也能請到好員工？資深 HR 不想告訴你的秘密！
</code></pre>]]></content:encoded>
    </item>
  </channel>
</rss>
