<?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>經驗分享 on Tarragon</title><link>https://tarrragon.github.io/blog/tags/%E7%B6%93%E9%A9%97%E5%88%86%E4%BA%AB/</link><description>Recent content in 經驗分享 on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Thu, 12 Mar 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/%E7%B6%93%E9%A9%97%E5%88%86%E4%BA%AB/index.xml" rel="self" type="application/rss+xml"/><item><title>經驗分享文章的寫作準則</title><link>https://tarrragon.github.io/blog/record/%E7%B6%93%E9%A9%97%E5%88%86%E4%BA%AB%E6%96%87%E7%AB%A0%E7%9A%84%E5%AF%AB%E4%BD%9C%E6%BA%96%E5%89%87/</link><pubDate>Thu, 12 Mar 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/record/%E7%B6%93%E9%A9%97%E5%88%86%E4%BA%AB%E6%96%87%E7%AB%A0%E7%9A%84%E5%AF%AB%E4%BD%9C%E6%BA%96%E5%89%87/</guid><description>&lt;p>整理自 2026-03 測試經驗記錄的多次修改過程。
每一條都是實際犯過的寫作錯誤，附上修改前後的對比。&lt;/p></description><content:encoded><![CDATA[<p>整理自 2026-03 測試經驗記錄的多次修改過程。
每一條都是實際犯過的寫作錯誤，附上修改前後的對比。</p>
<h2 id="1-語氣經驗分享不是教人">1. 語氣：經驗分享，不是教人</h2>
<p>不要用「你應該」「要記得」這種由上往下的口氣。這是在記錄自己的經歷，不是在寫教材。</p>
<table>
  <thead>
      <tr>
          <th>修改前</th>
          <th>修改後</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>教訓：測試應該驅動被測程式碼的真實路徑</td>
          <td>後來改成從入口方法開始呼叫，Bug 隨即被發現</td>
      </tr>
      <tr>
          <td>教訓：覆寫子類別時，要測試上層呼叫者實際會用到的方法</td>
          <td>測試覆蓋到的方法，和實際執行路徑走到的方法不是同一個</td>
      </tr>
      <tr>
          <td>關鍵原則：如果你的功能涉及多個元件協作，只寫單元測試是不夠的</td>
          <td>（直接移除，用案例本身說明）</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="2-語氣陳述事實不帶情緒">2. 語氣：陳述事實，不帶情緒</h2>
<p>避免用強調語氣、反問、或帶有自責/誇張的措辭。平鋪直敘地描述發生了什麼。</p>
<table>
  <thead>
      <tr>
          <th>修改前</th>
          <th>修改後</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>我到底哪裡搞砸了</td>
          <td>經驗記錄</td>
      </tr>
      <tr>
          <td>炸了四次</td>
          <td>陸續發現四個 Bug</td>
      </tr>
      <tr>
          <td>說到底，不是測試寫得不夠多，是測試走的路不夠深</td>
          <td>這次的問題在測試覆蓋的路徑深度</td>
      </tr>
      <tr>
          <td>我寫了一個永遠會過的斷言</td>
          <td>這個斷言無法區分成功和失敗</td>
      </tr>
      <tr>
          <td>真正會爆的那個完全沒碰</td>
          <td>測試覆蓋到的方法和實際執行路徑使用的方法不同</td>
      </tr>
      <tr>
          <td>但我偷懶了</td>
          <td>但模擬的回傳資料只有一行純文字</td>
      </tr>
      <tr>
          <td>其他路根本沒碰</td>
          <td>其他分支沒有被覆蓋到</td>
      </tr>
      <tr>
          <td>測試全過是假象</td>
          <td>測試通過不代表修改生效</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="3-用功能描述不要用函式名稱">3. 用功能描述，不要用函式名稱</h2>
<p>文章的讀者不一定看過這份程式碼。如果只寫函式名稱，只有自己看得懂。函式名稱可以出現在程式碼範例裡，但前後的解說要用功能語言。</p>
<table>
  <thead>
      <tr>
          <th>修改前</th>
          <th>修改後</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>_buildItemPrinterMapping</code> 沒有被執行</td>
          <td>品項分派的程式碼沒有被執行</td>
      </tr>
      <tr>
          <td><code>applyPrintResult</code> 的資料儲存功能</td>
          <td>把結果存進去再讀出來，資料有沒有一致</td>
      </tr>
      <tr>
          <td>只測了覆寫的 <code>sendBytes</code>，沒測繼承的 <code>printText</code></td>
          <td>只測了「送出資料」，沒測「組裝列印指令」這個步驟</td>
      </tr>
      <tr>
          <td><code>generator</code> 未初始化</td>
          <td>印表機內部元件未初始化</td>
      </tr>
      <tr>
          <td><code>_getLexemes('')</code> 對 <code>text[0]</code> 越界</td>
          <td>解析文字時沒有處理空字串，直接取第一個字元導致越界</td>
      </tr>
      <tr>
          <td><code>GeneralPrinterAdapter.printText</code> 加了空字串檢查</td>
          <td>在呼叫 library 之前加了空字串的前置檢查</td>
      </tr>
  </tbody>
</table>
<p>程式碼區塊裡的函式名稱不需要替換——那是具體的範例，讀者看到程式碼會理解。要替換的是程式碼區塊外的描述文字。</p>
<hr>
<h2 id="4-敘事角度不是每件事都是犯錯">4. 敘事角度：不是每件事都是「犯錯」</h2>
<p>有些問題不是自己造成的，不需要用自責的角度來寫。例如第三方 library 的 bug 本來就存在，能觸發它代表前面的工作都做對了。</p>
<table>
  <thead>
      <tr>
          <th>修改前</th>
          <th>修改後</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>修完一個 Bug 我就以為沒事了</td>
          <td>第三方 library 的地雷——前面都做對了才踩到</td>
      </tr>
      <tr>
          <td>我沒想到修完之後下游還有問題</td>
          <td>前三個 Bug 都修好之後，執行路徑才真正打通，觸發了這個潛在問題</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="5-每個案例要有脈絡發現--找因--修復">5. 每個案例要有脈絡：發現 → 找因 → 修復</h2>
<p>只說「問題是 X，改成 Y」不夠。讀者需要知道完整的脈絡：是怎麼意識到有問題的、怎麼一步步定位原因的、最後怎麼修的。</p>
<h3 id="修改前">修改前</h3>
<blockquote>
<p>測試名稱是「品項分派邏輯」，但分派邏輯沒有被執行。後來改成從入口方法開始呼叫，Bug 隨即被發現。</p></blockquote>
<h3 id="修改後">修改後</h3>
<blockquote>
<p><strong>怎麼發現的：</strong> 實機上兩台廚房印表機只有一台收到品項，另一台完全沒動。但測試裡的分派測試是通過的。</p>
<p><strong>怎麼找到原因的：</strong> 回頭看測試程式碼，發現測試裡的分派結果是手動寫死的，不是由分派邏輯算出來的。測試驗證的是「把結果存進去再讀出來」，但品項分派的程式碼從頭到尾沒有被執行過。</p>
<p><strong>怎麼修的：</strong> 改成從入口方法開始呼叫，讓品項分派的邏輯實際跑一遍。跑完之後 Bug 就出現了——分派邏輯的 fallback 條件寫錯，所有品項都被送到同一台。</p></blockquote>
<hr>
<h2 id="6-不要用特定產品sdk-名稱">6. 不要用特定產品/SDK 名稱</h2>
<p>具體的產品名稱（如某個 SDK 的名字）讓文章變成只適用於特定情境。著重描述問題的結構，而非特定技術。</p>
<table>
  <thead>
      <tr>
          <th>修改前</th>
          <th>修改後</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>imin SDK 不驗證 width 總和</td>
          <td>POS 主機不驗證欄位寬度總和</td>
      </tr>
      <tr>
          <td>imin vs ESC/POS 有不同的 width 規則</td>
          <td>兩種印表機對同一個參數的限制不同</td>
      </tr>
  </tbody>
</table>
<p>例外：第三方 library 的名稱可以出現在「最終修復」等技術細節區段，因為那是給自己未來查閱用的。</p>
<hr>
<h2 id="檢查清單">檢查清單</h2>
<p>寫完經驗分享文章後，對照這些問題：</p>
<ol>
<li>有沒有「你應該」「要記得」「教訓是」這類由上往下的用語？→ 改成描述自己做了什麼、發現了什麼</li>
<li>有沒有情緒化的措辭（搞砸、偷懶、炸了、根本沒）？→ 改成陳述事實</li>
<li>程式碼區塊外的函式名稱，不看程式碼的人能理解嗎？→ 用功能描述替代</li>
<li>每個案例有完整的脈絡嗎？（怎麼發現 → 怎麼找因 → 怎麼修）</li>
<li>有沒有把不是自己造成的問題寫成自己的錯？→ 用適當的角度描述</li>
<li>有沒有出現特定產品/SDK 名稱？→ 除了技術細節區段外，用功能描述替代</li>
</ol>]]></content:encoded></item></channel></rss>