《Code Complete 軟體建構之道》Podcast 準備稿:變數的一般事項與命名的力量
書名: 軟體建構之道 Code Complete(A Practical Handbook of Software Construction, 2nd Edition) 作者: Steve McConnell 系列: 啃一本大書(恩普拉氏) 公開標題建議: 啃一本大書|Code Complete.變數的作用範圍,與命名的力量 (5/15) 涵蓋範圍: 第10章 使用變數的一般事項 + 第11章 變數名稱的力量
背景速覽
從這集開始進入全書第三大部「變數」。如果前面講的是大尺度的設計(系統、類別、常式),這部就縮到最小的磚塊——變數。這集講兩件事:第10章談變數使用的通則(初始化、作用範圍、單一用途),第11章談命名。命名看似老生常談,但 McConnell 給的是有研究數據撐腰的命名學,跟一般「取個好名字啦」的泛泛建議不同。
一句話重點
變數的核心原則是「越靠近、越收斂越好」——初始化要靠近第一次使用、作用範圍要盡量小、一個變數只做一件事;而好名字應該完整精準地描述它代表的東西,命名的真正難處,在於它逼你想清楚「這東西到底是什麼」。
值得討論的重點
1. 初始化是錯誤最肥沃的溫床——靠近原則救你一命
McConnell 說不當的初始化是 bug 最肥沃的溫床之一:變數從沒被賦值(內容是隨機位元)、值已過時、只被部分初始化。最關鍵的守則是鄰近原則(Principle of Proximity)——在首次使用處附近初始化,而不是把所有宣告和初始化都堆在常式開頭。他特別警告那種「宣告集中在頂、初始化集中在頂、使用卻在很下面」的老派風格:當 code 被改(比如加了個迴圈),遠在天邊的初始化很容易被遺忘。最便宜的防禦就是宣告時立即初始化。
2. 作用範圍要小——「方便性」與「智識可管理性」的取捨
這段是這集的思想核心,也再次回扣全書的「管理複雜度」。McConnell 引入兩個量化概念:跨距 Span(同一變數兩次引用之間隔幾行,越小越集中越好讀)和存活時間 Live Time(第一次到最後一次引用之間的總行數,越短越好)。短存活時間的好處一串:降低初始化錯誤、提升可讀性、減少同時要追蹤的變數、有利於把大常式拆小。然後他講全域變數那段最有力:全域變數用起來方便,但讀、除錯、改的時候會變地獄——因為你必須同時理解所有共享它的常式。所以策略是從最嚴格的可見性開始:先用區域變數,需要時才放寬到類別私有、受保護、套件、最後才是全域。
3. 一個變數只做一件事——別搞「混合耦合」
McConnell 反對把一個變數拿來身兼數職。最經典的反例是「混合耦合 Hybrid Coupling」——讓一個變數偷偷夾帶第二種意思:pageCount 平常是頁數,但值為 -1 時代表錯誤(整數兼差當布林);customerId 超過 50 萬要減 50 萬才是逾期帳號。他說即使這種雙重用途對你自己很清楚,對別人永遠不清楚。用兩個變數承載兩種資訊帶來的清晰度,會「令你驚訝」。同理,別把同一個 temp 又拿來存判別式、又拿來交換陣列——該叫 discriminant 就叫 discriminant。
4. 命名的力量——名字就是設計想清楚沒的照妖鏡
第11章是命名的硬核版。最重要的原則:名字要完整且精準地描述變數代表的實體——最好的技巧是「用一句話說明這變數是什麼,那句話本身往往就是最好的名字」。有研究數據:變數名平均 10-16 個字元時除錯心力最低。作用範圍影響名字長度——i 適合幾行內的迴圈索引,但巢狀迴圈用 score[teamIndex][eventIndex] 遠勝 score[i][j](還能避免索引交叉錯誤)。布林變數要暗示真假語意(statusOK 好,status 爛)、要用正面語意(found 比 notFound 好,因為 if not notFound 很難讀)。狀態變數別叫 flag,那不傳達任何意義。還有一條金句:程式碼被讀的次數遠多於被寫的次數,命名要優先考慮讀的人。
注意事項
⚠️ 第11章後半的「標準化前綴」「匈牙利命名法 Hungarian Notation」(wn 視窗、p 指標、m_ 成員、g_ 全域)帶非常重的 2004 年色彩。在現代 IDE 普及、強型別語言當道的今天,匈牙利命名法基本上被淘汰了(型別資訊 IDE 會告訴你,前綴只是視覺雜訊)。講的時候要誠實標註這是時代產物——但背後「讓相關變數的關係一眼可辨」的精神(比如 g_ 區分全域)在某些弱型別/大型專案仍有殘餘價值。
⚠️ 「縮寫策略」那一大段(移除母音、保留首尾字母……)在現代語言幾乎用不到——McConnell 自己也說「現代語言很少需要縮寫」。重點唸一句就好:縮寫要一致、要能唸出來(通過「電話測試」)、不要只省一個字元。別花太多時間在縮寫技巧上。
⚠️ 「名字長 10-16 字元」是平均值不是上限。別讓聽眾矯枉過正——迴圈裡的 i、lambda 裡的 x 不需要長名字,這條跟「作用範圍越小、名字越短」是一致的。
專家補充
💡 命名這個主題是整個系列的「共識區」——《Clean Code》第2章、《Pragmatic Programmer》、Code Complete 第11章,三本書講命名幾乎沒有矛盾,都同意「名字要表達意圖、要為讀者而寫」。可以告訴聽眾:命名是軟體界少數沒有教派之爭的領域,所有大師都同意,所以這集講的東西可以放心照做。
💡 有句工程界老笑話值得唸:「電腦科學只有兩件難事——快取失效、命名,以及 off-by-one error。」命名為什麼難?因為它逼你真正想清楚這東西到底是什麼。McConnell 在書裡多次暗示這點:取不出好名字(暫存變數叫 temp、x),往往代表你還沒充分理解問題。命名困難是「設計還沒想清楚」的徵兆——這個洞見比任何命名規則都深。
💡 「跨距」和「存活時間」這兩個量化指標,是 Code Complete 很有特色的地方——它把「變數作用範圍小一點比較好」這種模糊建議變成可量測的東西。這種「凡事能量化就量化」的氣質,是這本書的招牌,後面講複雜度(McCabe)、講測試覆蓋率時還會看到。
討論問題
🎙️ 開場鉤子:「軟體界有句老笑話:電腦科學只有兩件難事——快取失效、命名、還有 off-by-one error。這集我們就來談談這個『最難的小事』——變數,跟它的名字。」
🎙️ 自問自答:「為什麼全域變數這麼方便,卻被罵這麼慘?」——因為它把方便性換成了智識負擔:一旦用了全域變數,你想搞懂任何一段相關的 code,就得同時理解所有碰它的地方。方便的是寫的當下,痛苦的是之後每一次閱讀。
🎙️ 帶走的一題:「下次取變數名取不順、想叫它 temp 或 data 的時候,停一下——這通常不是命名能力的問題,是你還沒想清楚這個值到底代表什麼。先把它想清楚,名字會自己浮現。」
更大範圍關聯
- 命名的共識區:本集與《Clean Code》第2章、《Pragmatic Programmer》高度重疊且零衝突,是整個軟工經典群最有共識的主題,可在 [軟體工程領域切分藍圖] 標為「跨書共識」節點。
- 回扣管理複雜度:作用範圍最小化、單一用途,本質都是 EP2「管理複雜度」原則在變數尺度的落地——可提醒聽眾這條主線一直沒斷。
- 量化精神:跨距、存活時間、名字字元數這些量化指標,是 Code Complete 的招牌氣質,會延續到 EP8(McCabe 複雜度)、EP10(測試覆蓋率)。
- 時代座標:匈牙利命名法在這版仍佔篇幅,但它正好是「IDE 與強型別讓某些 1990 年代慣例過時」的活化石——是觀察軟體實務如何隨工具演進的好案例。
錄製建議
- 建議時長:約 25 分鐘。配比:初始化與鄰近原則 5 分;作用範圍/跨距/存活時間/全域變數 8 分;單一用途與混合耦合 5 分;命名的力量 7 分。
- 討論策略:用那句「命名難題」老笑話開場最有共鳴。中段把「跨距/存活時間」當亮點——告訴聽眾 Code Complete 厲害在「把模糊建議變成可量測的數字」。命名那段強調「這是全書最沒爭議的章節,照做就對了」,並把「取不出名字=沒想清楚」這個深層洞見當收尾。
- 務必誠實處理匈牙利命名法:標註它是 2004 年產物、今天大多淘汰,但別全盤否定——把過時的部分濾掉、歷久彌新的精神留下,這正是整季的定調。