前言

我寫技術文章已經有一段時間了。從最早在 iT 邦幫忙的鐵人賽開始,到現在自架部落格持續更新,過程中學到最重要的一件事就是:寫技術文章是一種可以練習的技能

很多工程師覺得「我技術還不夠好,沒資格寫教學」或是「我不擅長寫文章」。但說實話,技術寫作的門檻比你想像的低,而且回報比你想像的高。寫完一篇文章後,你對那個主題的理解會深入好幾倍——因為你必須把模糊的直覺,整理成別人也能理解的文字。

這篇文章想分享我對技術寫作的一些心得,包括文章結構設計、程式碼範例原則、圖文搭配、讀者視角,以及我參加鐵人賽的經驗。


為什麼要寫技術文章?

費曼學習法

如果你不能用簡單的話解釋一個概念,代表你還不夠理解它。—— Richard Feynman

寫技術文章是最好的學習方式之一。當你嘗試把一個概念寫成教學,你會被迫面對自己知識的盲點:

你以為你懂的:「就是用 useEffect 啊」
寫文章時發現你不懂的:
  • useEffect 的 cleanup function 什麼時候執行?
  • dependency array 是用 Object.is 比較的嗎?
  • 為什麼 React 團隊建議用 useSyncExternalStore?

每一個「寫到一半發現自己不確定」的瞬間,都是學習的機會。

建立專業形象

技術文章是最好的作品集。面試官看你的部落格,比看你的 GitHub 綠點更能了解你的深度。一篇寫得好的教學文,展現的不只是技術能力,還有溝通能力和系統化思考。

幫助他人

你今天踩的坑,別人明天也會踩。你花了三天才解決的問題,如果寫成一篇文章,可能幫某個人省下三天的時間。這是一種很棒的正向循環。


文章結構設計

基本框架

每一篇技術教學文章,我建議用這個框架:

1. 前言 / 問題描述
   - 這篇文章要解決什麼問題?
   - 讀者讀完會得到什麼?

  1. 背景知識
- 讀者需要先知道什麼? - 簡短補充必要的前提
  1. 核心內容
- 概念解釋 - 程式碼範例 - 分步驟說明
  1. 實作演練
- 完整的可執行範例 - 常見錯誤和除錯
  1. 小結
- 重點摘要 - 延伸閱讀

倒三角形原則

新聞寫作有個「倒三角形」原則:最重要的資訊放在最前面。技術文章也一樣。

不好的開頭:

今天我想跟大家聊聊 Docker。Docker 是 2013 年由 Solomon Hykes 在 DotCloud 公司開發的開源專案。DotCloud 後來改名為 Docker Inc.。Docker 使用 Linux 的 cgroups 和 namespaces 技術⋯⋯

讀者看到這裡已經關掉了。

好的開頭:

你有沒有遇過「在我電腦上可以跑啊」這個問題?Docker 可以一次解決:把程式和它的整個執行環境打包在一起,不管在哪台機器上都能跑出一模一樣的結果。這篇文章教你用 Docker Compose 在十分鐘內架好一個 WordPress 部落格。

先講「為什麼你該在乎」,再講「是什麼」和「怎麼做」。

章節的粒度

一個章節(##)應該聚焦在一個概念。如果一個章節超過螢幕高度的 2-3 倍,考慮拆分。

## Docker 的基本概念

Image:靜態的藍圖

(3-5 段解釋 + 範例)

Container:執行中的實例

(3-5 段解釋 + 範例)

Volume:持久化的資料

(3-5 段解釋 + 範例)

每個 ### 小節控制在 200-400 字左右。


程式碼範例的原則

1. 可執行、可複製

讀者看到程式碼範例,第一件想做的事就是複製貼上來跑看看。如果他們貼上你的 code 卻跑不起來,你就失去了信任

# 不好:缺少 import,讀者不知道 requests 是什麼
response = requests.get('https://api.example.com/data')
data = response.json()

# 好:完整可執行 import requests

response = requests.get('https://api.example.com/data') data = response.json() print(data)

2. 漸進式複雜度

不要一開始就丟出完整的解決方案。先給一個最簡單的版本,然後逐步加入功能:

// Step 1: 最基本的 fetch
const response = await fetch('/api/users');
const data = await response.json();
// Step 2: 加上錯誤處理
try {
  const response = await fetch('/api/users');
  if (!response.ok) {
    throw new Error(HTTP ${response.status});
  }
  const data = await response.json();
} catch (error) {
  console.error('Failed to fetch users:', error);
}
// Step 3: 封裝成可重用的函式
async function fetchAPI(endpoint) {
  try {
    const response = await fetch(endpoint);
    if (!response.ok) {
      throw new Error(HTTP ${response.status}: ${response.statusText});
    }
    return await response.json();
  } catch (error) {
    console.error(API Error [${endpoint}]:, error);
    throw error;
  }
}

// 使用 const users = await fetchAPI('/api/users'); const posts = await fetchAPI('/api/posts');

每一步都是前一步的延伸,讀者可以在任何一步停下來,都能得到有用的東西。

3. 註解要解釋「為什麼」,不是「做什麼」

# 不好的註解:描述 code 在做什麼(看 code 就知道了)
# 設定 timeout 為 30
timeout = 30

# 好的註解:解釋為什麼這樣做 # 外部 API 在高峰時段回應時間可能超過 10 秒, # 設定 30 秒的 timeout 避免長時間阻塞 timeout = 30

4. 標示語言和檔名

<pre><code class="language-markdown">不好:</code></pre>
const x = 1;
<pre><code>好:</code></pre>javascript
// app.js
const x = 1;
<pre><code></code></pre>

告訴讀者這是什麼語言、這段 code 在哪個檔案裡。


善用比喻和類比

技術概念往往很抽象。好的比喻能讓讀者瞬間理解。

比喻的範例

| 技術概念 | 比喻 |
|———|——|
| Docker Container | 一個獨立的套房(公寓大樓裡的隔間) |
| API | 餐廳的菜單(你看菜單點餐,不用進廚房) |
| Cache | 書桌上的便條紙(常用的資訊放在手邊) |
| Load Balancer | 銀行的叫號系統(把客人分配到不同櫃台) |
| Git Branch | 平行宇宙(在不同分支做實驗,不影響主線) |
| Middleware | 機場的安檢(每個請求都要經過的檢查站) |

比喻的注意事項

  • 比喻不是等式:一定要說明比喻的局限性。「Docker 像虛擬機,但比虛擬機輕量,因為⋯⋯」
  • 用讀者熟悉的事物:如果你的讀者是後端工程師,用資料庫的比喻比用烹飪的比喻更有效
  • 一個概念一個比喻:不要用太多不同的比喻來解釋同一件事,會讓人混亂

圖文搭配

什麼時候需要圖?

  • 架構圖:系統組件之間的關係
  • 流程圖:步驟性的操作流程
  • 截圖:UI 操作說明
  • 資料流圖:請求/資料的走向

文字版圖表

如果你跟我一樣不擅長用圖形工具,可以用 ASCII art 或 Mermaid:

用戶請求的旅程:

Client → Nginx → Load Balancer → App Server → Cache ↓ ↑ ↓ (cache miss) Database

graph LR
    A[Client] --> B[Nginx]
    B --> C[Load Balancer]
    C --> D[App Server]
    D --> E{Cache Hit?}
    E -->|Yes| F[Return Cached]
    E -->|No| G[Query DB]
    G --> H[Update Cache]
    H --> F

程式碼就是最好的圖

對技術文章來說,一段好的程式碼範例,比一張架構圖更有說服力。因為圖是抽象的,但 code 是具體的。


讀者視角:為誰而寫?

定義你的讀者

寫文章之前,先想清楚你的目標讀者是誰:

目標讀者:有 1-2 年經驗的後端工程師,用過 SQL 但沒用過 PostgreSQL RLS
前提知識:基本的 SQL、知道什麼是 multi-tenant
不需要知道:PostgreSQL 的安裝方式、SQL 的基本語法

寫給太初級的讀者:你會花很多篇幅解釋基礎知識,核心內容反而被稀釋。
寫給太進階的讀者:讀者少,而且他們可能直接去看官方文件就好了。

我的經驗是,寫給「一年前的自己」最剛好。你曾經有的困惑、踩過的坑、花時間才搞懂的概念——這些就是最好的文章題材。

預想讀者的問題

寫每一段的時候,想像讀者會問什麼:

你寫:「我們可以用 RLS 來實現多租戶隔離。」
讀者可能問:
  • 「RLS 是什麼?」→ 需要先解釋
  • 「為什麼不直接在程式碼裡加 WHERE?」→ 需要說明 RLS 的優勢
  • 「效能會不會有問題?」→ 需要討論效能影響

把這些問題的答案寫進文章裡,你的文章就會很完整。


鐵人賽經驗分享

什麼是鐵人賽?

iT 邦幫忙鐵人賽 是台灣最大的技術寫作挑戰。規則很簡單:連續 30 天,每天發一篇技術文章

我的鐵人賽策略

1. 提前準備大綱

在比賽開始前,我會把 30 篇文章的標題和大綱都列好:

Day 01: 系列介紹 — 為什麼我要寫這個主題
Day 02: 環境設定 — 把開發環境準備好
Day 03-05: 基礎概念(一~三)
Day 06-10: 核心技術(一~五)
Day 11-15: 實作練習(一~五)
Day 16-25: 進階主題(一~十)
Day 26-28: 實戰案例(一~三)
Day 29: 常見問題 FAQ
Day 30: 總結與延伸

2. 預寫 buffer

比賽開始前先寫好 3-5 篇文章存著。這樣如果某天狀態不好或臨時有事,有 buffer 可以用。

3. 控制每篇字數

鐵人賽的文章不需要每篇都是長篇大論。800-1500 字是最舒適的長度。太長你寫得累、讀者也看得累。

4. 接受「不完美」

連續 30 天每天產出,品質不可能篇篇都高。有些天你會寫出自己很滿意的文章,有些天你只是勉強交差。這很正常。鐵人賽的價值在於「完成 30 天」,不在於「每篇都完美」。

鐵人賽之後

比賽結束後,你手上會有 30 篇文章。接下來可以:

  • 整理成部落格系列文
  • 篩選出最好的幾篇,重新打磨後投稿到技術媒體
  • 把整個系列整理成電子書

寫作工具推薦

編輯器

  • VS Code + Markdown Preview:我最常用的組合
  • Typora:所見即所得的 Markdown 編輯器
  • HackMD:線上協作,適合跟人共寫

程式碼截圖

  • Carbon(carbon.now.sh):把程式碼變成漂亮的截圖
  • ray.so:類似 Carbon,有更多主題可選
  • 但我更建議直接用 Markdown 的程式碼區塊,方便讀者複製

圖表工具

  • Excalidraw:手繪風格的圖表,特別適合架構圖
  • Mermaid:用文字描述生成圖表,可以放在 Markdown 裡
  • draw.io(diagrams.net):免費的線上圖表工具

常見的寫作陷阱

1. 知識的詛咒

你太熟悉某個概念,以至於忘了初學者不知道的東西。

對策:寫完後找一個不熟悉這個主題的朋友看一遍,看他能不能看懂。

2. 流水帳式寫法

「首先做 A,然後做 B,接著做 C⋯⋯」通篇都是步驟,沒有解釋為什麼。

對策:每個步驟都附上一句「為什麼要這樣做」。

3. 完美主義拖延

「等我把這個主題徹底搞懂再寫。」結果永遠不會寫。

對策:先寫出 70% 的版本發布,之後再慢慢修改。你的讀者不會因為你後來修改文章就覺得你不專業——反而會覺得你很認真。

4. 只寫技術,不寫心得

純粹的技術紀錄跟官方文件沒什麼差別。加入你的個人觀點、踩坑經驗、和思考過程,才是讀者來你的部落格(而不是去看官方文件)的原因。


小結

技術寫作是一個正向循環:寫文章 → 加深理解 → 幫助他人 → 建立聲譽 → 獲得回饋 → 寫更多文章。

不需要等到你成為某個領域的專家才開始寫。事實上,剛學會一個東西的時候,你最能理解初學者的困惑,這時候寫出來的教學反而最有價值。

今天就開始吧。打開你的編輯器,想一個你最近學到的東西,寫下來。不用完美,不用很長,500 字就好。發布出去,你就是一個技術作者了。

延伸閱讀