論述基礎與限制

本卡的論述基於 1 個 casedart Stream 事故的 review)抽出來的觀察。具體限制:

  • Keyword bank 是 starting set、不是 exhaustive list:列出的口語詞(一輩子 / 碰巧 / 撞牆 / 啊原來)都是這次 dart 篇出現過的、不代表「口語修辭的完整詞庫」。新類型出現時要持續擴充
  • 「精度 vs 可讀性」是情境化取捨、不是 zero-sum:本卡聚焦「判斷工具型段落」(讀者要從中拿到 portable 工具的論述)、在這類段落精度優先;但 hook / 引言 / narrative 段落口語反而幫讀者進入論述、不適用本卡
  • Self-case 的修補有效性未獨立驗證:dart 篇修補後讀起來更精準、但「精準度跟讀者實際理解之間的相關性」沒做使用者測試

讀者使用本卡時、先判斷段落是否屬於「判斷工具型」——是 → 套用;否 → 評估口語跟可讀性的取捨。


核心原則

技術文章的「判斷工具型段落」(讀者用來判斷自己 case 的論述)裡、用詞選擇要能對應到具體技術屬性。口語修辭(「一輩子」「碰巧」「立刻撞牆」「沒事」)讀起來流暢、但在這類段落會稀釋精度——精度標準是「用詞能不能反推到具體機制 / 條件 / 契約」、口語修辭多半不能、寫了等於把判斷工具退化成感性印象。

下面三個層次的稀釋是觀察到的 pattern——不是窮舉、實際違規模式可能更多:

口語修辭稀釋的層次讀者拿到的訊息真實技術屬性
「一輩子只能 X」時間性誇張永遠這樣(無範圍感)生命週期內最多承載 1 次
「碰巧能用」因果模糊運氣使然觸發條件不滿足、限制處於沉默狀態
「立刻撞牆」結局描述代替契約描述視覺意象、不知為什麼違反型別契約、執行期 throw
「沒事」缺失條件描述沒問題限制存在、但沒有可見影響
「整個炸了」嚴重度誇張知道很糟、不知糟在哪違反契約導致 X 行為
「啊原來 X」結局視角的驚訝句事後恍然大悟感在 Y 條件下 X 才暴露

三個稀釋層次的具體 case

層次 1:時間性誇張

口語版:「stream 一輩子只能被 listen 一次」

問題

  • 「一輩子」沒有對應的技術概念——是「整個 process lifetime」?「stream object lifetime」?「listener cancel 之後也算嗎」?
  • 讀者要靠猜測決定範圍

精度版:「stream 在整個生命週期內只允許被 listen 一次(StreamController object lifetime;cancel() 之後再 listen() 仍違反契約、要重建 StreamController)」

差別:精度版讓讀者能反推「我這個 case 屬於哪個範圍、會不會踩到」、口語版讀者只能感受「應該很嚴格」。

層次 2:因果模糊

口語版:「碰巧能用掩蓋了設計缺陷」

問題

  • 「碰巧」暗示運氣使然、機制不可解釋
  • 但實際上「能用」有明確的機制:訂閱者數量沒達到觸發違反契約的條件
  • 用「碰巧」會讓讀者學到「這是運氣問題」、不學到「這是條件未滿足的可預測現象」

精度版:「訂閱者單一時、限制處於沉默狀態」

差別:精度版描述「為什麼沒影響」的具體條件、口語版只描述「結果」。讀者能用精度版去判斷自己的 case 何時會觸發、不能用口語版做同樣的判斷。

層次 3:結局描述代替契約描述

口語版:「新加第二個訂閱者就立刻撞牆」

問題

  • 「撞牆」是視覺意象、不是技術描述
  • 讀者拿到的是「發生了不好的事」、不是「為什麼發生」「在哪一層發生」
  • 套到不同 case(如「使用 cancelled stream」「使用 closed controller」)會推不出對應的修法

精度版:「新加第二個訂閱者直接違反契約、執行期 throw」

差別:精度版指明「違反的是什麼(契約)」「在哪個時間點(執行期)」「具體後果(throw)」、讀者能 generalize 到其他違反契約的情境。


為什麼口語修辭會出現

技術寫作中口語修辭的出現有三類典型來源:

來源 1:寫的當下感性敘事比技術敘事好寫

「一輩子只能 listen 一次」比「整個 lifecycle 只允許被 listen 一次」少 5 個字、寫起來順、語氣強烈。但精度也差距 5 倍。寫作便利度高的版本通常離精度遠(#67 寫作便利度跟意圖對齊反相關 的同骨——寫得順 ≠ 寫得對)。

來源 2:對讀者「直覺感受」的妥協

「碰巧能用」這類詞讓讀者「立刻有共鳴」、感覺像在讀故事。但技術文章的讀者來這裡找的是判斷工具、不是故事——共鳴感換來精度損失、是錯誤的取捨。

來源 3:誤把「事故當下的反應」當成「論述用詞」

事故當下工程師的內心 OS 確實是「啊原來這個 mutation 路徑沒帶」「進入頁面就炸」——這些是當下的口語反應。寫成正式論述時要把這些反應翻譯回技術描述、保留意圖(驚訝 / 嚴重程度)但不保留口語形式。


識別訊號:什麼時候你在用口語修辭

訊號 1:時間 / 範圍誇張詞

「一輩子」「永遠」「整個炸了」「全部 GG」「直接死」——這類詞沒有對應的技術範圍、用了讀者要靠猜測。

修法:問「具體是哪個範圍 / 哪個生命週期 / 哪個 scope?」、把答案寫進去取代誇張詞。

訊號 2:運氣 / 巧合語氣

「碰巧」「剛好」「湊巧」「運氣好」——這類詞遮蔽了背後的機制。技術系統的行為幾乎都有可解釋的條件、不是運氣。

修法:問「為什麼當下沒發生?是哪個條件沒滿足?」、把條件寫出來取代運氣語氣。

訊號 3:視覺意象 / 動作比喻

「撞牆」「炸了」「鎖死」「卡住」「當機」(口語的,不是技術術語的 hang/freeze)——這些是事件的視覺描述、不是契約 / 機制描述。

修法:問「在哪一層、違反了什麼、執行期表現是什麼?」、把答案寫出來取代視覺比喻。

訊號 4:結局視角的驚訝句

「啊原來」「結果發現」「最後才知道」——這些把讀者帶到「事故已發生、回頭看」的視角、依賴 hindsight。

修法:問「在事前、什麼條件成立時這個 X 才會出現?」、改成事前可判斷的描述。詳細處理見 #110 設計檢討用當下三軸論證、不依賴 hindsight

訊號 5:「沒事」「沒問題」當成段落結論

「運作正常」「沒事」「沒問題」「一切看起來都好」——這類詞代替了「在哪些條件下沒可見影響」的具體描述、暗示「不需要進一步審視」。

修法:問「沒影響是因為什麼條件沒觸發?換條件會怎樣?」、把條件寫出來取代「沒事」。

訊號 6:「下次 X 時、做 Y」結尾段

「下次看到 X 時、先問 Y」「下次寫 Z 時、想 W」「下次面對 V 時、停下來」——這類段落想給讀者實踐建議、但有兩個結構問題:

  1. 前綴是 wrapper、不增加資訊:讀者來讀這段的脈絡通常已經是「正在處理 X」、「下次看到 X 時」對讀者是廢話、把重點推到後面(違反規則五「最重要的話優先說」)
  2. 預設讀者會主動回憶:「下次 X 時做 Y」假設讀者下次會自動想起這條建議、實際上讀者多半不會主動 recall——應該寫成「判斷工具」而不是「回憶指令

修法:把 wrapper 拿掉、把建議改寫成判斷工具的形式:

修補前修補後
下次看到 Bad state 時、不要先想「我寫錯了」根因落在 stream 定義端的型別契約、不在訂閱端
下次寫 test 時、想「這份 file 是唯一 doc 嗎」把「這份 file 是模組唯一 doc」當命名的質量門檻
下次看到自己寫三行 doc、停下來想能不能變型別寫到「三行 doc 解釋輸入範圍」這個訊號時、自問能不能變型別簽章

差別:修補前是「下次 X 時、做 Y」的 hortative 命令;修補後是「遇到 X 訊號時、用 Y 工具判斷」的 reactive 工具。前者依賴讀者主動 recall、後者由訊號觸發判斷。

注意 ≠「描述讀者的具體情境」:

「讀者讀完事後諸葛論述、能複述 case、但問他下次遇到不同議題怎麼判斷答不出來」

這個「下次遇到 X」是描述讀者的測驗情境(檢驗論述是否 portable)、不是給讀者的指令——保留合理。


何時口語修辭仍然合理

「精度優先」這條原則在大多數技術論述情境成立、但有合理例外:

情境為什麼口語仍合理
對話 / 訊息 / Slack 討論即時溝通、共識在場、口語反而更快建立 mutual understanding
個人筆記 / scratchpad寫給自己看、知道自己當下在想什麼、不需要對他人精度
故事性引言 / hook 段文章開頭吸引讀者、口語可暫時用、但很快要切回精度敘事
引用當事人的反應 / 直接 quote「事故當下工程師說『啊我哪裡寫錯了』」是引用、保留口語反映真實心境
反例段落(教讀者「不要這樣寫」)故意用口語版讓讀者看到差別、然後切到精度版

判讀:寫之前自問「讀者拿這段去做技術判斷時、口語修辭會不會讓判斷模糊?」——會 → 翻成精度版;不會 → 口語可接受。


跟其他抽象層原則的關係

原則跟本卡的關係
#67 寫作便利度跟意圖對齊反相關口語修辭比精度敘事好寫——但精度才是讀者要的工具、便利 vs 對齊的同骨展現
#110 設計檢討用當下三軸論證、不依賴 hindsight「啊原來」「碰巧」這類詞天生帶 hindsight 視角、本卡是 #110 在「字句層級」的延伸
Compositional-writing 規則一:階段分層(觀察 → 判讀 → 策略 → 執行)口語修辭多半混淆四階段——「立刻撞牆」混了觀察跟判讀、要拆開重寫
Compositional-writing 規則二:商業邏輯先於 CASE「碰巧能用」隱藏商業邏輯(為什麼能用)、本卡要求把商業邏輯顯式寫出來

判讀徵兆

訊號該做的行動
段落讀起來「順」「有畫面」「像故事」停下來掃口語修辭、問「這個詞對應什麼具體技術屬性?」
用了「一輩子」「永遠」「整個」這類絕對詞換成具體生命週期 / scope
用了「碰巧」「剛好」這類運氣語氣找出背後的機制條件、寫出條件
用了「撞牆」「炸了」這類視覺意象換成「違反 X 契約 / 在 Y 時刻 throw / 觸發 Z error」
用了「啊原來」「結果發現」改成事前可判斷的條件描述
用了「沒事」當段落結論補「在 X 條件下沒影響、換 Y 條件會怎樣」

核心原則:技術文章的用詞要能反推到具體機制 / 條件 / 契約。口語修辭的便利在於寫得順、代價是讀者拿不到判斷工具。寫完每段後跑一次「這個詞對應什麼具體技術屬性?」自問、答不出來的詞就要翻譯。


Self-case:本卡的觸發來源

本卡的觸發是修 Dart StreamController:single-subscription vs broadcast 的事故實錄 的第二輪審查。

讀者指出該文有四處口語化問題:「stream 一輩子只能被 listen 一次」「進入頁面就炸」「現在只要有人訂閱、把它記錄下來,UI 就能用」「碰巧能用掩蓋了設計缺陷」。修補時的觀察是這些不是孤立問題、是「口語修辭代替技術描述」這個共通 frame 在不同句子的展現。

修補後對比:

修補前修補後
stream 一輩子只能被 listen 一次整個生命週期內只允許被 listen 一次(StreamController object lifetime)
進入頁面就炸第二個訂閱者觸發底層限制
立刻撞牆直接違反契約、執行期 throw
碰巧能用限制處於沉默狀態(觸發條件不滿足)
啊原來這個 mutation 路徑沒帶暴露出某些 mutation 路徑沒填寫該欄位

每一組修補都把「口語視覺意象」翻譯回「技術屬性 + 條件 + 契約」。讀者拿到的是可反推的判斷工具、不是感性印象。

對應本卡:口語修辭的稀釋是字句層級的、容易在第一輪寫作後被忽略——multi-pass review 要在輪 4「Grep-ability / 命名 / 術語」加掃這個 frame、用 grep 找口語詞庫