技術文章撰寫規範
適用範圍
本規範適用於團隊內部各類型技術文章,包含:
- 概念說明:技術原理、系統架構、協定規格
- 實作教學:操作步驟、範例、API 用法
- 架構決策:方案比較、選型紀錄、設計文件
- 除錯復盤:事故紀錄、疑難排解
- 技術評估:工具調研、可行性評估
核心目標:讓讀者能複製思考過程,不只複製結論。結論一行就能給,思考過程才是文章的主體。
本規範四條規則各自後方附有正反例,來源標註:
- 正例多引自
/work-log/目錄下的已成文文章 - 反例多引自同系列文章修改前的版本(實際寫作過程中踩到過的問題)
一、階段分層
規則的商業邏輯
技術文章的內容從「事實或需求」推導到「動作或結論」,這個過程有四個功能不同的階段。每個階段處理的問題不同、失敗模式不同:
- 觀察:描述現況、需求、事實或訊息
- 判讀:說明本質、原理、問題所在
- 策略:列出可選方案並比較
- 執行:具體操作或實作
四階段若混著寫,讀者無法區分「這一段失敗是哪個階段」,也無法判斷自己的類似情境卡在哪一步。文章只能被原封不動複製,不能被理解後套用。
做法
每個主題段落應包含四階段。不同類型文章中四階段的對應:
| 階段 | 概念說明 | 實作教學 | 架構決策 | 除錯復盤 |
|---|---|---|---|---|
| 觀察 | 需求或背景 | 使用情境 | 現況限制 | 錯誤訊息 |
| 判讀 | 概念本質 | 工具的位置與功能 | 需求本質 | 問題根因 |
| 策略 | 不同用法 | 不同操作路徑 | 可選方案 | 可行解法 |
| 執行 | 程式碼範例 | 操作步驟 | 選定實作 | 修復動作 |
實例對照
反例(跳過判讀,觀察直接進執行):
1## 錯誤
2flutter_broadcasts_4m:Kotlin 1.8 vs Java 17 mismatch
3
4## 解法
5在 subprojects 加上:
6tasks.withType(KotlinCompile).configureEach { jvmTarget = '17' }問題:讀者能複製貼上,但無法回答「為什麼是 configureEach 不是其他方式」「遇到下一個類似問題怎麼想」。思考過程沒有被保存。
正例:gradle_reasoning_traps 的節點 A 結構,每個節點顯式展開成「當下看到 → 判讀 → 可選策略 → 選擇與理由 → 結果 → 事後檢視」六個子段落。讀者看完後即使遇到不同錯誤訊息,也能套用同一個四階段推導。
禁止事項
- 從觀察直接跳執行,省略判讀與策略
- 判讀留下未解問題就進策略
- 文章中出現「選擇」卻只列一個選項
例外
純介紹性段落(例如 API 參數說明)可以省略「策略」階段,但不得省略判讀。
二、商業邏輯先於 CASE
規則的商業邏輯
技術文章的內容包含兩種資訊層次:
- 商業邏輯:系統層的概念(為什麼這件事存在、在體系中代表什麼)
- CASE:實例層的資料(具體的數值、路徑、屬性、設定)
CASE 單獨存在沒有意義。「jvmTarget = 17」這個值需要「為什麼 JVM target 要一致」這個概念當容器才能被理解。
順序顛倒(先 CASE 後商業邏輯)等於讓讀者先記一組沒有脈絡的資料,再倒推抽象概念。這條認知路徑是反向的,多數讀者在倒推失敗後會放棄,即使專業讀者能勉強跟上也會覺得閱讀成本偏高。
做法
每個主題段落包含兩層,順序不得顛倒:
商業邏輯層
- 主題涉及的系統層概念
- 該概念為什麼存在、解決什麼問題
- 該類內容的共通本質
此層不討論具體數值、路徑、屬性名。
CASE 層
- 訊息或規格中的關鍵字對應商業邏輯的哪個位置
- 具體數值或內容
- 從 CASE 推論的結論
實例對照
反例(直接給 CASE,預設讀者懂背景):
1### 判讀
2
3- 這個子專案的 Java task 產出 bytecode target = 17
4- 同一個子專案的 Kotlin task 產出 bytecode target = 1.8
5- 兩者不一致觸發 Kotlin 2.2 的 strict validation專業人士看了懂,但讀者若不知道「bytecode target」「strict validation」在系統中代表什麼,只能抓到字面字串,無法建立模型。
正例(加上商業邏輯層當容器):
1### 判讀
2
3**這類錯誤的本質(商業邏輯)**:
4
5Android 每個 module 會分別編譯 Java 跟 Kotlin 原始碼,各自產出
6JVM bytecode。每個 bytecode 有 target version,決定能在哪些 JVM
7runtime 上跑。同 module 內若兩種語言產出不同 target,runtime
8可能踩到 API 相容性問題。Kotlin 2.2 把這個從 warning 提升為 error。
9
10**這次訊息具體說了什麼(CASE)**:
11
12- compileDebugJavaWithJavac (17) → Java 產出 target 17
13- compileDebugKotlin (1.8) → Kotlin 產出 target 1.8
14- 符合上面「module 內不一致」的 pattern(出自 gradle_reasoning_traps 節點 A 修改後的版本。修改前是反例那種寫法,修改後加入商業邏輯層。)
完成標準
段落結束前,讀者應能回答:
- 這個主題在系統中為什麼重要?
- 這個主題的具體案例對應商業邏輯的哪個位置?
若只能回答第二題,商業邏輯層不足。
三、評估用內在屬性
規則的商業邏輯
技術文章經常包含選擇或比較:選 A 不選 B、用 X 不用 Y、選這個架構不選另一個。選擇的優劣取決於方案的內在屬性,不取決於執行者的時間消耗:
- 內在屬性:覆蓋完整性、風險、可逆性、維護成本、可理解性、依賴前提
- 時間消耗:實作要多久、多少人工時
時間消耗是執行者的資源考量,跟方案本身的正確性無關。用時間當評估維度會造成結構性偏差:投資型方案(擴大影響、建立基礎)看起來總是比消費型方案(解當前問題)差,但兩者能力的性質不同,不應以同一量度比較。
讀者讀到時間評估會誤以為「這個方案比較好」,但真正該學到的是「兩個方案各自適合什麼情境」。
做法
每個方案比較必須包含下列維度中至少三項:
| 維度 | 評估內容 |
|---|---|
| 覆蓋完整性 | 處理所有同類情境,還是只處理當前 |
| 風險 | 失敗機率與代價 |
| 可逆性 | 出錯能否回滾 |
| 維護成本 | 長期需要多少精力 |
| 可理解性 | 未來接手者能否理解 |
| 依賴前提 | 建立在什麼假設上,前提變了會如何 |
實例對照
反例(用時間成本換算划不划算):
1節點 A 事後回顧:
2這一步多 2 分鐘掃一遍 pub-cache,但可以省下後來約 30 分鐘的
3build-炸-修循環。明顯划算。讀者學到的是「划不划算」這個執行層結論,沒學到兩個方案的結構性差異。
正例(用內在屬性列出方案差異):
1節點 A 事後檢視:
2
3若當下選擇「A2 + 同步盤點 pub-cache」:
4
5- 優點:一次盤點所有同類地雷,修復範圍完整;避免之後
6 遇到一個修一個的反應式除錯
7- 缺點:盤點結果可能含假陽性;擴大修復範圍可能引入新變數
8
9當下漏掉這個選項的本質問題是:
10單點錯誤修復後沒有主動擴大搜尋同類問題。
11這是決策是否涵蓋完整問題面的問題,不是執行層的快慢考量。(出自 gradle_reasoning_traps 節點 A 事後檢視。修改前是反例版本,修改後改用「覆蓋完整性」「範圍完整」這類內在屬性。)
禁止事項
不得以時間成本作為主要評估維度,包含:
- 「這方案比較快」
- 「多花 X 分鐘省下 Y 分鐘」
- 「立即可完成」
四、事後檢視看判讀品質
規則的商業邏輯
技術文章的品質檢視(review、事故檢討、復盤)常只看「結論對不對」,但多數失敗的根源在判讀階段:
- 判讀未確認的推論被當結論
- 判讀觀察範圍不足(只看單點)
- 判讀用類比代替機制驗證
這類問題會表現成「結論失敗」的樣子,但改善方向完全不同:
- 結論失敗 → 下次多列幾個選項
- 判讀失敗 → 下次判讀要更嚴謹、更廣、更實證
兩者混為一談會得到「要更仔細」這種無法行動的結論。
做法
文章或決策完成後,必須回答下列四題:
- 判讀階段的「需要確認」項目是否全部解答?
- 觀察範圍是否涵蓋同類情境,或僅處理當前一個?
- 推論中的類比假設是否驗證?
- 策略列舉是否完整?
任一題答「否」,對應失敗類型必須明確標示:
| 答「否」的題 | 失敗類型 | 改善方向 |
|---|---|---|
| 題 1 | 未確認推論帶入結論 | 判讀完成標準要收緊 |
| 題 2 | 觀察範圍不足 | 擴大搜尋類似情境 |
| 題 3 | 類比代替驗證 | 機制差異需實證 |
| 題 4 | 策略列舉不足 | 至少列兩個選項 |
實例對照
反例(只檢視結論,歸因模糊):
1這次修復走了彎路,下次應該更仔細。無法行動。下次遇到類似情境仍會犯同樣錯誤。
正例(分類失敗類型,對應不同改善方向):
1七個節點中四個失敗,分類:
2
3| 節點 | 失敗類型 | 根本來源 |
4|---|---|---|
5| 節點 C | 需要新資訊(toolchain 時機) | 節點 B 判讀留下「需要確認」但沒補 |
6| 節點 D1 | 對稱假設 | 節點 D 判讀用「結構對稱」取代「機制驗證」 |
7| 節點 F | 方法呼叫時機 | 節點 E 判讀沒展開 API 的兩階段行為 |
8
9三個失敗都源自判讀未完成就進策略。不是策略選錯,是判讀階段
10進入策略時,還帶著未解決的問題。(出自 gradle_reasoning_traps 的「整個過程的決策品質檢視」段落。)
這樣的檢視產出具體改善方向:「判讀完成標準要收緊」、「機制差異需實證」,而不是模糊的「要更仔細」。
五、判讀徵兆對照
技術文章撰寫中常見的徵兆與對應的判讀要求。看到徵兆時,作者必須回答對應問題。
徵兆:單一位置指向(檔案、行號、屬性名)
該位置是「現場」,不一定是「根因」。必須追問:
- 為什麼是這個位置出問題?
- 是目標的狀態錯了,還是呼叫的時機錯了?
徵兆:同類情境第二次出現
前次處理範圍不完整。必須追問:
- 還有哪些同類情境?
- 是否有共通原因?
徵兆:修改看似合理但未生效
時機或機制假設錯誤。必須追問:
- 修改的生效時機是否晚於覆蓋對象?
- 覆蓋機制是否真的能蓋過目標?
徵兆:「final」「already」「cannot」這類字眼
目標已進入不可修改狀態。必須追問:
- 目標何時進入該狀態?
- 修改能否提前到狀態轉換之前?
徵兆:「inconsistent」「mismatch」這類字眼
兩部分不一致。必須追問:
- 哪一邊是正確的目標值?
- 不一致的方向決定治理施加在哪一邊?
實例
這組徵兆對照表的完整應用案例見 gradle_evaluation_order_traps,該文將三種 Gradle 時序錯誤(already evaluated、is final、覆寫沒生效)各自對應到同一個底層問題(時機錯位),並給出對應的解法方向。這就是「看到徵兆 → 查表 → 推出判讀結論」的標準路徑。
六、術語
| 術語 | 定義 |
|---|---|
| 商業邏輯 | 系統層次的概念說明,不涉及具體值 |
| CASE | 具體內容(數值、路徑、屬性名) |
| 判讀 | 從事實推導本質的過程 |
| 策略 | 可選方案 |
| 現場 | 訊息直接指向的位置 |
| 根因 | 底層原因,不一定等於現場 |
| 投資型策略 | 有長期回報的方案(擴大覆蓋、建立認知) |
| 消費型策略 | 只處理當前問題的方案 |
七、提交自檢
提交文章前自檢:
- 四階段(觀察/判讀/策略/執行)完整,或已說明可省略的階段
- 每個主題段落先商業邏輯後 CASE
- 判讀中所有「需要確認」項目已解答或註明可暫不確認
- 每個方案比較至少三個評估維度
- 未以時間成本為主要評估維度
- 事後檢視四題已回答
- 失敗類型已標示(若有)
參考範例
本規範四條規則的完整應用案例:
- Gradle JVM target 除錯復盤:七個節點的策略權衡 — 全四條規則的完整應用,每個節點皆含觀察/判讀/策略/結果/事後檢視五層
- Gradle 強制覆寫 plugin 的 JVM target:Kotlin 與 Java 的切入點不對稱 — 商業邏輯先於 CASE 的範例(先講 Kotlin plugin 與 AGP 的機制差異,再講具體寫法)
- Gradle Configuration 時序陷阱:afterEvaluate、evaluationDependsOn、finalized properties — 判讀徵兆對照的完整應用
- 為什麼 Bug 在合併後才爆:Gradle Cache 掩蓋潛伏問題的邏輯 — 事後檢視看判讀品質的範例(將「合併造成」重新歸因為「判讀時把觸發條件當根因」)