# Day 15:測試保護下的重構與函數式思維 **Published by:** [雞蛋糕的前端修煉屋](https://paragraph.com/@gcake/) **Published on:** 2025-12-10 **URL:** https://paragraph.com/@gcake/day-15 ## Content 今天完成了三個練習,核心收穫是「在測試保護下進行重構」與「從指令式到宣告式的思維轉換」。紅燈 → 綠燈 → 重構:TDD 的安全感來源測試先行,鎖定行為契約在重構現有函式之前,我先為它補齊了單元測試。測試案例明確定義「給定輸入 X,預期輸出 Y」的行為契約,涵蓋正常情境、邊界條件與空值處理。當測試通過(綠燈)時,代表這個函式的「對外承諾」已被測試鎖住。刻意紅燈:確認測試真的在守門重構的第一步,我刻意寫了一個「只做一半」的實作,讓測試故意失敗(紅燈)。這個步驟的價值在於驗證測試真的有在檢查關鍵邏輯,而不是「假性通過」。看到紅燈後,我確認測試確實能偵測到實作缺陷,才放心進入下一步。綠燈重構:專注程式碼品質補齊邏輯讓測試回到綠燈後,我開始專注在「內部實作的優化」——從 for 迴圈改寫為 map().filter() 的 pipeline 風格。這個過程中,每次調整後我都會立刻跑測試,確認「對外行為」依然不變。這種「小步前進、頻繁驗證」的節奏,讓我能放心調整程式結構,不用擔心改壞卻沒發現。從指令式到宣告式:HOF 的心智模型轉換指令式:告訴電腦「怎麼做」原本的 for 迴圈版本是典型的指令式風格:手動管理索引、手動取值、手動 push 結果。程式碼逐行描述「怎麼執行」,像是給電腦的操作手冊。for (let i = 0; i < arr.length; i += 1) { const value = arr[i]; if (condition) { result.push(transform(value)); } }for (let i = 0; i < arr.length; i += 1) { const value = arr[i]; if (condition) { result.push(transform(value)); } } 宣告式:描述「要做什麼」重構後的 HOF 版本聚焦在「資料變換的步驟」:先用 map 轉換每個元素結構,再用 filter 篩選符合條件的項目。程式碼讀起來更接近需求描述,而不是實作細節。const result = arr .map(item => transform(item)) .filter(item => condition(item)); 使用時機判斷我整理了一個選擇標準:適合 HOF:單純的資料轉換/篩選/累加 pipeline適合 for:需要 break/continue、多變數同步更新、極端效能敏感場景實務上我會先問自己:「這段是在操作資料流,還是在做複雜的流程控制?」來決定起手式。數學模型映射到程式邏輯第二個練習讓我實作一個「累進折扣」的計價邏輯。關鍵在於如何將「每滿 N 期增加一次折扣」這個數學規則轉譯成程式。我使用 Math.floor((period - 1) / 5) 來計算累積折扣次數,這個公式直接對應數學直覺:period - 1:將 1-based 期數轉為 0-based,對齊除法運算/5:每 5 期為一個折扣單位Math.floor():無條件捨去,取得「已完成的折扣區間數」這種「將業務規則轉譯為數學表達式」的能力,讓程式碼意圖更清晰,也更容易驗證正確性。函式組合:小函式的樂高積木哲學第三個練習讓我實作三個函式,它們的關係是「組合」而非「繼承」:基礎函式 A:解決單一小問題基礎函式 B:解決另一個獨立小問題組合函式 C:呼叫 A 和 B,組裝成複雜功能每個函式都有明確的單一職責,都有獨立的單元測試。當需求變更時,我只需要調整特定函式,而不會牽一髮動全身。這種「小而美、可組合」的設計,讓程式碼像樂高積木一樣靈活。今日心得TDD 不只是寫測試TDD 的價值不在於「有沒有測試」,而在於它強制我先思考 API 介面設計、再思考實作細節。寫測試的過程中,我會自然地問自己:「這個函式怎麼用最直覺?」「輸入輸出的資料結構怎麼設計最清楚?」這種「由外而內」的思考方式,讓我寫出的函式介面更符合使用者(也就是呼叫端)的心智模型。重構的勇氣來自測試沒有測試保護時,我會猶豫是否該重構——「改了會不會壞掉?」有了測試後,我能放心調整內部實作,因為任何破壞都會立刻被偵測到。這種「安全感」讓我更願意持續優化程式碼,而不是讓技術債累積。小步前進比大步跨越安全Uncle Bob 提倡的「幾秒鐘循環一次」TDD 流程,核心精神是降低每次變更的風險半徑。一次只改一小塊、立刻驗證,比一次改一大片再來除錯要高效得多。今天的練習讓我深刻體會到這種節奏的威力。參考資料The Three Laws of TDD-從紅燈變綠燈的過程TDD 開發五步驟,帶你實戰 Test-Driven Development 範例什麼是高階函式(Higher order function)?使用高階函式有什麼好處?Array.prototype.map() - MDNArray.prototype.filter() - MDN ## Publication Information - [雞蛋糕的前端修煉屋](https://paragraph.com/@gcake/): Publication homepage - [All Posts](https://paragraph.com/@gcake/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@gcake): Subscribe to updates