從名字出發的術語檢查,抓不到被反覆使用而從未命名的概念
論述基礎與限制
本卡由一個語言層教材分類(二十二篇加二十一張卡)的一次外部提問抽出。那個分類在提問之前跑過五輪多輪審查,reviewer 分寫作規範、實測回歸、跨章一致、冷讀、steelman、outbound、個案實跑等 frame,另派過理解探針、術語探針與翻譯探針;backlog 已收斂。提問者拿一份社群解答連問四題,前三題在分類裡都有落點、目錄頁的問題表也有對應的列,第四題問一個術語是什麼意思,而那個術語在整個分類裡沒有住址。
個案一則,無對照組。 本卡另附一次全站掃描與一批三份反向探針,兩者的數字各有明寫的口徑,不要拿來當精確度。
核心原則
站內每一種術語檢查都以「文本裡出現的名字」為入口——給它一個名字,它去查定義、查卡、查通用度。 一個概念以操作的形態在多篇裡反覆出現,而它的名字一次都沒有寫進正文時,沒有任何一條檢查會走到它。這是承重術語漏定義的另一端:那裡的名字出現頻率最高、作者寫到失去陌生感;這裡的名字出現頻率是零,作者用的是它的寫法而不是它的名字。兩端由同一個機制產生(作者手上有讀者沒有的東西),而既有的偵測只覆蓋高頻那一端。
外部讀者帶名字進來,模組帶用法出去——這個入射角的差異是缺口為什麼由提問撞出、而非由任何一輪 reviewer 找到的原因。
症狀:模組把一個運算用得很重,而從來沒叫過它的名字
那個分類講「有沒有對應資料」的三種寫法,其中 EXISTS 那一種在關聯代數裡叫半連接(semi-join),否定式 NOT EXISTS 叫反連接(anti-join)。分類對這兩個運算的處理是:
semi-join寫在講三種寫法那一篇的tags裡,正文一次都沒有出現。- 「半連接」在講連接起手式的那一篇正文裸用一次、無定義無連結,緊接著路由到講三種寫法的那一篇,而目的地全篇沒有這個詞。
- 關聯代數那張卡列運算時漏了它,而它的兄弟(積)在同一輪已經有專卡。
anti-join與「反連接」全分類零命中,而NOT EXISTS出現在五篇裡,講分組鍵那一篇的結論就是它。
同批另抓到一條錯路由:積那張卡宣稱「自連接與 EXISTS 兩種寫法的差別」在講三種寫法的那一篇,而那一篇沒有自連接,那個對照住在講代價的那一篇。
為什麼每一個 frame 都放行
每一條檢查各有自己的理由,而理由相同:入口是名字。
術語處理分級的觸發條件是「文章內出現關鍵術語」,決定行內展開、連卡或裸用。名字不在文中,分級不啟動。
承重術語掃描(scripts/loadbearing-terms.py)掃連續漢字的高頻詞。這個概念在正文裡的形態是 ASCII 關鍵字 NOT EXISTS,腳本的射程明寫不含英文;它的中文名詞頻是一或零,排不進任何一篇的候選。
術語探針的受測單位是文中的一個詞。沒有那個詞就沒有受測單位。
理解探針問「你讀到什麼」。讀者回報得出讀錯的、讀不懂的,回報不出不知道存在的名字——他不知道有那個詞。
冷讀的行話洩漏理論上該抓到那一處裸用的「半連接」。它放行有兩個可能成因,而歸因要回原文查:緊鄰的連結讓 reviewer 把「有路由」讀成「有定義」,而路由承接的驗收(#240)查的是目的地承接主題、不查目的地含這個詞——這裡主題承接了(那一篇確實講 EXISTS)、詞沒有;或者探針自己認得這個詞,知道得比目標讀者多,於是不覺得它是行話。第二種是探針當讀者代理的反向失效——常被記錄的是高階模型自動補完缺漏,這裡是低階模型的既有知識超過了讀者定位。
outbound 的知識卡缺口這一輪抓到三張候選(覆蓋索引、儲存引擎、系統目錄),三個全是正文裡的承重詞。這個 frame 自己的產出證實了它的入口也是名字。
共同前提盤點抓的是各篇前置段裡重複的判斷,這裡重複的是動作不是判斷。
枚舉卡的完整性在 steelman 裡有一條「enumeration 是否窮盡」,而窮盡的對照是領域的正典清單——關聯代數的經典運算表本來就不列半連接(它是導出運算)。對照正典會通過;對照這個模組實際執行過的運算才會發現少一個。同形態的缺口在同一輪修過一次:積那張卡的建立動機是新文章需要那個詞、順手補進代數卡的清單。修的是那個實例,動機仍是名字驅動;代數卡的清單從未對照過模組的用法清單。
tags 是宣稱而沒有人驗證宣稱。 frontmatter 檢查驗 tags 欄位存不存在,不驗 tag 說的話在正文裡成不成立。這與#318同構:格子逐格驗過,由格子導出的那句話沒有驗。
這個機制不限於術語:每一種檢查都有入口
本卡的形狀在術語之外一樣成立。每一種檢查都從某個入口出發,而零命中只證明「從那個入口走不到」。 術語檢查的入口是文本裡的名字,所以概念以操作形態存在而名字零次進正文時,沒有任何一條會走到它。
路由檢查是同一個機制的另一個實例,而它的兩個方向分得特別乾淨:死名檢查(正文指過去、目的地不存在)與孤兒偵測(內容存在、沒有任何地方指過來)。一次實測裡死名檢查全綠,而孤兒那一側從來沒有被驗過——兩者都是路由缺陷,回報也都是零命中,而差別既不在作用域、也不在指令或判斷標準,只在只驗了一個方向。
雙向都驗過之後還有一層:方向數不等於入口數。 一次外部實測把一份文件外移三節,路由表的雙向檢查全綠(零死名、零孤兒),而同一批有三處跨檔指涉是失效的——那個檢查比對的是路由表與目標檔的標題,而各檔檔頭的同目錄索引、正文裡的跨檔指涉是另外兩套指標,它一條都沒掃。三套指標系統,一個檢查覆蓋其中一套的兩個方向。
雙向全綠比單向零命中更容易讓人收工,因為它讀起來像涵蓋率這個問題已經處理過了。分辨的方法是先數指標系統再數方向:這份內容裡有幾套指標在指別的地方(路由表、檔頭索引、正文行內連結、設定檔或程式碼裡的路徑字串),每一種是一個入口,而雙向只是每個入口各有兩個走法。
處置因此是一句話:雙向各驗一次,並在報告上分開寫。 合成一句「路由檢查通過」會讓沒驗的那一側繼承已驗那一側的信用。
盤點入口的方法是問每一條檢查「它從什麼東西出發」,再問「反過來會走到什麼」:名字對用法、指過去對被指到、宣告對實作、輸入對輸出。反向那一側多數沒有現成工具,而它存在與否是可以先回答的。
入口之外還有軸:同一種檢查對另一個失效軸沒有效力。 一次拆分把三套指標系統各驗了一遍(路由表、檔頭索引、正文的跨檔指涉),而六份檔裡五十三條相對連結全部斷掉、三套檢查一條都沒抓到。它們不是第四套指標——前三套的失效是目標動了,這一類的失效是指標自己搬了家而目標沒動,相對路徑的基準點跟著檔案走了。把它列成第四套會讓人用同一種「目標在不在」的檢查去驗,而那種檢查對它恆真。盤點入口的時候要多問一句:這個指標失效的方式是目標消失,還是指標本身的意義因位置而改變;後者要用另一種檢查(以指標所在位置解析後驗存在)。
修法
處置分兩層:這一批補卡與修路由,是那個分類的 backlog;方法層補的是一個方向相反的檢查,讓下一批不必等外部提問。
從用法盤點到名字。 列出這批稿件裡反覆出現的操作形態——程式碼區塊裡的語法構造、跨篇重複的查詢形狀、同一組步驟在多篇各走一次——對每一種問兩件事:這個領域叫它什麼;那個名字在模組裡有沒有住址。便宜的候選指標是同一個構造出現在三篇以上的程式碼區塊而正文沒有給它任何名字。這是共同前提盤點的操作層版本:那個 frame 管被多篇當前提的判斷,這一條管被多篇執行的動作。
反向術語探針。 既有的術語探針給名字問意思,這一種給形態問名字:把程式碼片段單獨餵給多份低階模型(不附正文、不附模組的用詞),問「這種查詢形狀在教材裡的標準名稱是什麼」,明令沒把握就寫沒把握。收斂到同一個名字代表那個名字在領域裡是通用的,回模組 grep 它有沒有住址。設計條件沿用術語探針:同批混入至少一個模組已經命名的形態當控制,控制項收斂才採用;測試的名字要先查不在探針讀得到的規範檔裡。
這一種跑過一批(三份 Haiku,指令逐字相同,四段查詢不附任何正文):EXISTS 那一段三份全部回 semi-join,NOT EXISTS 與 LEFT JOIN … IS NULL 兩段三份全部回 anti-join(一份寫 anti-semi-join,所指相同)並全部指出兩段是同一形狀;控制項自連接三份收斂,而那個名字模組已經用了八篇。測試詞在規範檔的詞頻是零,所以收斂可歸因到領域而非提示。單批、無對照批——它證明的是這個方向問得出名字,不是它的漏報率。
tag 當宣稱驗。 對每篇的每個 tag 問正文有沒有承接它。這一條可以機械產生候選而精確度低:一次全站掃描,一萬兩千餘個 tag 裡近四千個在該篇正文字面零命中;那個分類四十一個,收成「整個分類任何正文都零命中」之後剩二十二個,其中真缺口一個。噪音的主要來源是英文 tag 對中文正文(self-join 對「自連接」、three-valued-logic 對「三值邏輯」)。所以它是候選生成器,判定要人做;tag 與術語卡建立對應之後才收得緊。
枚舉卡對照模組的用法、不只對照正典。 一張卡列一組運算或成員時,第二份對照表是這個模組實際執行過的那些;新文章用到清單外的運算時,枚舉卡是要回頭改的檔案之一。積那張卡那次做對了實例,這一條把它變成類。
外部提問是最便宜的異源。 #296 寫規模買不到異源視角,本卡是它在術語層的實例:同一個 session 出的搜尋落點問題會沿用模組自己的詞彙——出題人正是那個沒寫過 semi-join 的人。讀者實際的提問要收進下一輪的問題清單,而且收的重點是他用了哪些模組沒用過的詞。
跟其他原則的關係
- #303 串連佔掉的是本篇的篇幅:那張卡的「承重術語在自己的主場最容易沒有定義」是頻率最高的那一端,本卡是頻率為零的那一端。同一支掃描腳本對兩端都盲,成因不同——那裡是主題詞干擾排序,這裡是 ASCII 關鍵字與零詞頻根本進不了候選。
- #306 按功能組織的教材裡「該用哪一個」沒有住址:與 #305 合起來是同一個成因的三個缺席——深度、入口、名字。作者手上有讀者沒有的東西,這裡作者有的是用法而沒有名字。
- #240 路由目的地要承接該主題:本卡的裸用實例是那條驗收在術語層的形態——目的地承接了主題而不含那個詞。承接的驗收要多問一句:路由句裡的術語在目的地出現了嗎。
- #296 規模買不到異源視角:本卡的 finding 由外部提問撞出,而提問帶進來的正是模組詞彙之外的詞。異源在這裡買到的是詞表,視角只是其中一半。
- #318 每一格都驗過,不代表由格子導出的那句話驗過了:tags 欄位驗存在不驗宣稱,是同一個結構。
- #322 比對回報零差異時,那個零只證明這個粒度看不到差異:同一批工作抽出的姊妹卡。本卡是檢查走不到對象(入口是名字),那張卡是檢查走到了但看不清(粒度不夠),兩者在報告上都是零命中。
- #232 自審 sweep 的偵測方法要對齊規則類型:名字驅動的偵測對無名概念是方法錯配,補救是加一個方向相反的方法,不是把既有方法跑得更細。
- 要求揭露只擋得住省略 與 掃描的作用域會默默對齊「我這次動過什麼」:同屬「零命中有幾種來源」這個家族。本卡貢獻的那一種是只驗了一個方向——死名檢查全綠而孤兒那一側從未被驗,兩者都是路由缺陷、回報也都是零,而處置是雙向各驗一次並在報告上分開寫。
- #343 拆分產生的缺陷落在檔與檔的交界:本卡回填的「方向數不等於入口數」在那裡被推進一步——入口數也不等於落點數。同一條指路寫在檔頭與寫在首次用點的效果相差三份對零份(單變項對照),所以檔頭的同目錄索引這套指標即使完整無缺,正文那一套仍可能對讀者無效。
判讀徵兆
- 一個語法構造出現在多篇的程式碼區塊裡,正文沒有給它任何名字。
- tag 裡有一個詞,整個分類的正文零命中。
- 枚舉卡列了一組成員,而模組某篇在做清單外的那一個。
- 某個術語在正文只出現一次、緊跟一條連結,而目的地沒有那個詞。
- 外部提問用的名詞,模組裡查不到,而模組有一篇整篇在講它指的那件事。