feat(smells): 第 5 組擴充條列式步驟、導向連結與標示語法

What:references/smells.md 第 5 組擴充。5.1 的方法描述後面要接條列式的處理步驟
與規則,5.3 的回傳值是自訂資料模型時要附上型別定義的導向連結;新增 5.6 內含
功能的導向連結、5.7 XML 註解標籤各占一行、5.8 註解裡的專有名詞與變數依語言
慣例標示。文末的嚴重度分級補上一張表,逐項標明這五個新項目的級別與理由。

Why:使用者提出的產出物文件品質規則裡,有三條講的都是原始碼註解要寫到什麼
程度。動手前先比對過既有內容,第 5 組已經涵蓋大部分,缺的是條列步驟、導向
連結與標示語法這三塊。另開一支技能會跟 code-review 的目標重疊,所以直接擴充
第 5 組。新項目多半屬於可讀性層級,混在原本「註解缺漏」一句話裡分不出輕重,
所以級別另外列。

How:5.1 與 5.3 在原有定義後面接上新要求,偵測訊號與建議重構手法同步補列,
原本的判準一個都不動。5.6 到 5.8 照既有小節的四段結構寫:定義、偵測訊號、
建議重構手法、注意事項。5.8 的標示語法用表格對照 XML 與 JSDoc、docstring
兩類格式。5.6 與 5.7 都寫明註解格式不支援時不適用,避免硬造連結字串,也避免
把 XML 的排版規則套到沒有結束標籤的格式上。

Who:jsc-review 的壞味道參考清單,第 5 組註解契約。
This commit is contained in:
2026-08-27 15:41:38 +08:00
parent 8b8f23a17b
commit dbaf81005b
+46 -7
View File
@@ -122,9 +122,9 @@
### 5.1 方法描述
- **定義**:每個公開方法要有一句話描述,並標明所屬層級:**顯示層、邏輯層、存取層**。
- **偵測訊號**:公開方法無描述;描述未標層級;描述與方法實際行為不符。
- **建議重構手法**:補上單句描述與層級標記;若一個方法橫跨多層,先依 Split Phase 拆分再各自標註。
- **定義**:每個公開方法要有一句話描述,並標明所屬層級:**顯示層、邏輯層、存取層**。描述後面要接**條列式的處理步驟與規則**,讀註解就知道這個方法做了哪幾件事、依哪些規則做。
- **偵測訊號**:公開方法無描述;描述未標層級;描述與方法實際行為不符;描述只有一句話,方法內部卻有多段流程或多條判斷規則,註解裡找不到對應的條列;條列步驟與程式碼實際順序對不上。
- **建議重構手法**:補上單句描述與層級標記,再把處理流程拆成條列步驟、把判斷條件寫成條列規則;若一個方法橫跨多層,先依 Split Phase 拆分再各自標註;條列長到十項以上,代表方法本身太肥,同時列 1.2 並建議 Extract Function。
### 5.2 輸入參數說明
@@ -134,9 +134,9 @@
### 5.3 輸出說明
- **定義**:輸出(回傳值)要說明回傳的資料內容概要。
- **偵測訊號**:無回傳說明;未說明 null、空集合、錯誤時的回傳;回傳布林但未說明 true/false 意義。
- **建議重構手法**:補回傳內容概要與邊界情況說明。
- **定義**:輸出(回傳值)要說明回傳的資料內容概要。回傳值是自訂資料模型,而註解格式支援導向時(XML 的 `<see cref>`、JSDoc 的 `{@link}`),說明要附上該資料模型的檔案連結,讀的人一鍵就跳到定義。
- **偵測訊號**:無回傳說明;未說明 null、空集合、錯誤時的回傳;回傳布林但未說明 true/false 意義;回傳自訂資料模型卻只寫型別名稱純文字,沒有 `<see cref>` 或 `{@link}` 導向。
- **建議重構手法**:補回傳內容概要與邊界情況說明;自訂資料模型改用註解格式的導向標籤指到型別定義,泛型集合指到元素型別。
### 5.4 輸入與輸出範例
@@ -150,6 +150,35 @@
- **偵測訊號**:DTO/ViewModel 僅頂層有註解;內層類別、集合元素型別的欄位無說明或無範例。
- **建議重構手法**:逐層補齊 5.1–5.4;巢狀過深(≥ 3 層)時同時評估 Extract Class 是否被濫用。
### 5.6 內含功能的導向連結
- **定義**:一個功能內部呼叫了其他功能時,註解要交代呼叫了誰、為什麼呼叫。註解格式支援導向就用導向標籤(XML 的 `<see cref>`、JSDoc 的 `{@link}`),讓 IDE 直接跳過去。
- **偵測訊號**:方法內呼叫其他公開方法或服務,註解卻完全沒提;提了但只寫純文字方法名,沒有 `<see cref>` 或 `{@link}`;寫了連結卻沒寫用途,讀的人還是要自己點進去猜。
- **建議重構手法**:在條列步驟裡把被呼叫的功能改成導向標籤,後面接一句用途;被呼叫的功能多到列不完,代表這個方法在當協調中心,同時列 1.2 或 3.1 評估職責搬移。
- **注意**:註解格式不支援導向(例如純 `//` 行註解)就只寫用途,不硬造連結字串。
### 5.7 XML 註解標籤排版
- **定義**:註解採 XML 格式時,起始標籤與結束標籤**各自獨立一行**,內容夾在中間。這樣多行內容、條列與巢狀標籤才排得整齊,diff 也只動到真正改的那幾行。
- **偵測訊號**:起始標籤、內容、結束標籤擠在同一行(例:`/// <summary>取得訂單</summary>`);結束標籤跟在內容尾巴後面沒有換行(例:`/// 取得訂單</summary>`);`<param>`、`<returns>`、`<remarks>`、`<example>` 同樣擠成一行;巢狀標籤(`<list>` 內含 `<item>`)沒有逐層換行與縮排。
- **建議重構手法**:把每個標籤拆成三行——起始標籤一行、內容一行或多行、結束標籤一行;巢狀標籤逐層縮排;`<param>` 這類帶屬性的標籤,屬性留在起始標籤那一行。
- **注意**:只針對 XML 格式註解。JSDoc、docstring 沒有結束標籤,不適用本項。
### 5.8 專有名詞與變數標示
- **定義**:註解裡提到程式碼元素時,要用該語言註解格式的標示語法標起來,不能混在純文字裡。標示的目的是讓 IDE 與文件產生工具讀得懂,並在文件上呈現成程式碼樣式。
- **偵測訊號**:XML 註解裡直接以純文字寫參數名、型別名、成員名或程式碼字面;JSDoc 或 docstring 裡以純文字寫變數名與型別名,沒有加反引號;標錯類別(例如拿 `<c>` 標參數名、拿 `<paramref>` 標型別)。
- **建議重構手法**:依語言慣例補標示。
| 註解格式 | 對象 | 標示語法 |
| --- | --- | --- |
| XML | 變數、參數 | `<paramref name="orderId" />` |
| XML | 型別、成員 | `<see cref="OrderService.GetOrder" />` |
| XML | 程式碼字面、列舉值 | `<c>null</c>` |
| JSDoc、docstring | 變數、型別、程式碼字面 | 反引號 `` `orderId` `` |
- **注意**:標示規則跟著語言慣例走,不是跟著個人喜好走。IDE 的跳轉與文件工具的交叉引用都靠這些標籤,標錯等於沒標。
## 第 6 組:淺模組(Shallow Module)
- **定義**:介面複雜度相對於功能深度過高的模組——使用它要懂的事,跟自己寫差不多(出自《A Philosophy of Software Design》:好模組要「介面簡單、實作深」)。
@@ -162,4 +191,14 @@
| --- | --- | --- |
| 高 | 會造成錯誤或已阻礙修改 | 吞掉異常、重複程式碼改漏、死碼誤導 |
| 中 | 持續增加維護成本 | 巨型類別、臃腫函式、巢狀地獄、Couplers 全組 |
| 低 | 可讀性與一致性 | 命名、魔術數字、註解缺漏、文件編號夾帶、淺模組 |
| 低 | 可讀性與一致性 | 命名、魔術數字、註解缺漏、文件編號夾帶、淺模組、XML 標籤排版、專有名詞未標示 |
第 5 組新增項目的級別另外標明,避免全部壓在「註解缺漏」一句話裡:
| 項目 | 級別 | 理由 |
| --- | --- | --- |
| 5.1 缺條列式步驟與規則 | 中 | 讀的人要重讀整個實作才知道規則,維護成本直接上升 |
| 5.3 回傳值缺資料模型連結 | 低 | 型別名稱還查得到,只是多花幾秒 |
| 5.6 缺內含功能的導向連結 | 低 | 同上,影響的是查找速度 |
| 5.7 XML 標籤排版擠在同一行 | 低 | 純排版,不影響語意 |
| 5.8 專有名詞未標示或標錯 | 低 | 影響 IDE 跳轉與文件呈現,不影響執行 |