前言
我寫技術文章已經有一段時間了。從最早在 iT 邦幫忙的鐵人賽開始,到現在自架部落格持續更新,過程中學到最重要的一件事就是:寫技術文章是一種可以練習的技能。
很多工程師覺得「我技術還不夠好,沒資格寫教學」或是「我不擅長寫文章」。但說實話,技術寫作的門檻比你想像的低,而且回報比你想像的高。寫完一篇文章後,你對那個主題的理解會深入好幾倍——因為你必須把模糊的直覺,整理成別人也能理解的文字。
這篇文章想分享我對技術寫作的一些心得,包括文章結構設計、程式碼範例原則、圖文搭配、讀者視角,以及我參加鐵人賽的經驗。
為什麼要寫技術文章?
費曼學習法
如果你不能用簡單的話解釋一個概念,代表你還不夠理解它。—— Richard Feynman
寫技術文章是最好的學習方式之一。當你嘗試把一個概念寫成教學,你會被迫面對自己知識的盲點:
你以為你懂的:「就是用 useEffect 啊」
寫文章時發現你不懂的:
- useEffect 的 cleanup function 什麼時候執行?
- dependency array 是用 Object.is 比較的嗎?
- 為什麼 React 團隊建議用 useSyncExternalStore?
每一個「寫到一半發現自己不確定」的瞬間,都是學習的機會。
建立專業形象
技術文章是最好的作品集。面試官看你的部落格,比看你的 GitHub 綠點更能了解你的深度。一篇寫得好的教學文,展現的不只是技術能力,還有溝通能力和系統化思考。
幫助他人
你今天踩的坑,別人明天也會踩。你花了三天才解決的問題,如果寫成一篇文章,可能幫某個人省下三天的時間。這是一種很棒的正向循環。
文章結構設計
基本框架
每一篇技術教學文章,我建議用這個框架:
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 字就好。發布出去,你就是一個技術作者了。
延伸閱讀
- iT 邦幫忙 — 台灣最大的技術社群
- Technical Writing Courses by Google — Google 的免費技術寫作課程
- Write the Docs — 技術寫作社群
- The Documentation System — 四種類型的技術文件
- Hemingway Editor — 幫助你寫出更清晰的文字