第 1 / 8 部 待錄

重構是什麼與第一個範例

《Refactoring 重構》Podcast 準備稿:重構是什麼・第一個範例

書名: 重構 Refactoring(Improving the Design of Existing Code, 2nd Edition) 作者: Martin Fowler 系列: 啃一本大書(恩普拉氏) 公開標題建議: 啃一本大書|Refactoring.先動手再下定義:第一個範例 (1/8) 涵蓋範圍: 第1章 A First Example(第一個範例)

背景速覽

這是「啃一本大書」系列啃《重構》的起手集。《Refactoring》(1999 初版、2018 第2版) 是 Martin Fowler 的代表作,與《Clean Code》《The Pragmatic Programmer》並列軟體工匠三大必讀。這本厚書有趣的地方在於:Fowler 開篇不先定義重構,而是直接帶你看一段爛 code,手把手改一遍。這集就跟著他走完第一個範例,把「重構到底長什麼樣」這件事用畫面講清楚——理論留到下一集。

一句話重點

重構不是「大改一場」,而是一連串微小、各自獨立、且每一步都跑過測試的安全變動;改的是內部結構,不動外在行為,靠的就是「小步快跑+測試保護網」這套紀律。

值得討論的重點

1. 為什麼 Fowler 要「先示範、後定義」

整本書最聰明的編排,就是把第一章留給一個完整範例(戲劇團演出計費的程式)。Fowler 知道,講「重構」的定義一句話就講完,但那句話無法讓你相信它安全。所以他先讓你親眼看到:一段交織著計算與列印、難以加新功能的 code,是怎麼透過十幾個微小步驟,變成結構清晰、易於擴充的樣子。看完範例,你對「小步快跑」的信任感是用眼睛建立的,不是用道理說服的。這集的講法也該這樣——用過程帶聽眾,而不是先丟定義。

2. 標準重構流程:Extract → Rename → 優化變數 → Split Phase → 多型

書裡的範例走了一條很有代表性的路線,值得整理成一張地圖讓聽眾記住:

  • 準備測試:動手前先有一套能自動判斷對錯的測試,這是安全網。
  • 拆解函式(Extract Function):把一整坨邏輯依「完整行為」切成小函式,每切一次就跑一次測試。
  • 變數命名(Rename):回傳值統一叫 result,臨時變數給它說得清楚的名字。
  • 優化變數(Remove / Replace Temp with Query):把不必要的暫存變數換成查詢函式,降低區域狀態。
  • 拆分階段(Split Phase):把「計算」和「格式化輸出」這兩個關注點分開——這是這個範例的設計轉捩點。
  • 引入多型(Polymorphism):最後用類別與多型取代冗長的 switch / if-else,讓新增劇種變成加一個子類別。

重點不是背這條順序,而是體會:每一步都很小、很無聊、很安全,但累積起來就是脫胎換骨。

3. 「困難就是訊號」:先重構,再加功能

範例裡 Fowler 想加新需求(支援新劇種計費)時,發現現有結構讓這件事很難做。他的反應不是硬塞,而是先停下來重構,把結構整理到「加功能變順理成章」為止,再戴上功能帽去加。這句「當你發現要加功能很難,先重構讓它變容易,再加」是整本書的核心節奏,值得在這集就種進聽眾腦裡。

注意事項

⚠️ 這集的目標是「畫面」不是「術語」。 別急著把所有重構手法的名字都倒出來——聽眾還沒看過範例,名詞只會變雜訊。讓「一段爛 code 怎麼一步步變乾淨」這個過程自己說話,手法名稱點到為止,細節留給後面集數。

⚠️ 本書這份筆記的範例用 Python,但原書第2版改用 JavaScript。 第1版是 Java。Fowler 第2版刻意改用 JS,是因為它「夠普及、夠不挑剔語言特性」,讓重構的觀念不被特定語言綁架。錄製時可以提一句:重構手法是跨語言的,語言只是載體——這正是 Fowler 換語言想傳達的訊息。

⚠️ 別把重構和效能優化混為一談。範例過程中 Fowler 完全不擔心效能(多拆幾個函式呼叫的成本)。重構階段只追求結構清晰;效能是之後針對量測出來的瓶頸做的獨立步驟。 現代編譯器/直譯器對小函式呼叫的優化也讓這個顧慮大幅降低。

專家補充

💡 這個「先範例後定義」的編排,本身就是 Fowler 的一個教學主張:重構是一門手藝,手藝要看人做才學得會,不是讀定義學得會。 這也呼應了為什麼《重構》後面有一整本的「手法目錄」(catalog)——它更像一本食譜或拳譜,是拿來查、拿來練的,不是拿來從頭讀到尾的。這集可以先替整季定錨:「啃這本大書,不是要你背 60 幾招,是要你看懂這套小步快跑的心法。」

💡 範例裡那個「Split Phase(拆分計算與輸出)」的動作,其實藏著一個更大的設計原則:把「決定要算什麼」和「決定怎麼呈現」分開,這正是 MVC、純函式核心(functional core)/外圍副作用(imperative shell) 等架構思想的微縮版。一個第一章的小重構,連得到很大的架構觀念,這條線拉出來很有縱深。

💡 Fowler 有句名言可以在這集用:「任何傻瓜都能寫出電腦看得懂的程式碼;好的程式設計師寫出人看得懂的程式碼。」(Any fool can write code that a computer can understand. Good programmers write code that humans can understand.) 這句和《Clean Code》「程式碼是寫給人看的」是同一個信仰,正好把兩本經典接起來。

討論問題

🎙️ 開場鉤子:「你有沒有過這種經驗——想加一個小功能,結果發現現有的 code 根本不讓你好好加?今天這集就是在講,遇到這種時候,高手會先做什麼。」

🎙️ 自問自答:「重構為什麼要『小步』?一次大改不是比較快嗎?」——答案:大改一旦出錯,你不知道是哪一步壞的,只能整段回退;小步快跑每一步都跑測試,錯了立刻知道是這一步,幾乎不用除錯。慢就是快。

🎙️ 帶走的一題:「這禮拜挑一段你看不太懂的 code,只做一件事:把其中一坨邏輯 Extract 成一個有好名字的函式。改完跑一次測試。就這樣。」

更大範圍關聯

  • 軟體工匠三經典:《Refactoring》+《Clean Code》(Uncle Bob)+《The Pragmatic Programmer》。《Clean Code》告訴你「乾淨長什麼樣」,《重構》告訴你「怎麼從髒變乾淨、而且不弄壞東西」——兩本是互補的,可互相引路(見 [軟體工程領域切分藍圖])。
  • 與 TDD 的血緣:重構是 TDD 紅-綠-重構循環裡的第三步,沒有重構,TDD 只剩「能跑的爛 code」。Fowler 與 Kent Beck 是長期戰友,這套小步+測試的紀律兩人共享。
  • 思想座標:重構讓「演進式設計(evolutionary design)」成為可能——你不必一開始就設計完美,可以邊做邊改進。這是對「大設計先行(Big Design Up Front)」的一種回應。

錄製建議

  • 建議時長:約 18-20 分鐘。配比:系列開場+這本書是誰約 3 分、走完第一個範例約 12 分、收束三條心法(小步、測試、兩頂帽子)約 4 分。
  • 討論策略:這集千萬別變成術語朗讀。用「想加功能卻加不動」的痛開場,然後用「跟著 Fowler 走一遍範例」當主菜,把每一步講得很小、很安全,讓聽眾建立對「小步快跑」的信任。結尾收在「困難就是訊號:先重構再加功能」這條最好用的習慣。
  • 系列起手,花 30 秒介紹「啃一本大書」要幹嘛、《重構》在軟工史上的地位,建立系列感。