線上課程觀課進度管理小工具開發日誌
Day 6:JavaScript 程式碼執行排序:遞迴函數、Call Stack、Task Queue
Call Stack;遞迴函數與 call stack 的關係;Task Queue(非同步的概念再釐清)
Day 9:「修煉圈圈 Practice Rings」Web app 開發日誌 - 2025 六角 AI Vibe Coding 體驗營期末大魔王作業
這份筆記旨在記錄 2025 六角 Vibe Coding 體驗營每日作業 Day 21 的期末專案成果,從一個簡單的個人痛點出發,透過與 AI(在我這個情境中是 Perplexity)協作,在一天內完成了一個包含前後端的全端網頁小工具:「修煉圈圈 Practice Rings」。
<100 subscribers
線上課程觀課進度管理小工具開發日誌
Day 6:JavaScript 程式碼執行排序:遞迴函數、Call Stack、Task Queue
Call Stack;遞迴函數與 call stack 的關係;Task Queue(非同步的概念再釐清)
Day 9:「修煉圈圈 Practice Rings」Web app 開發日誌 - 2025 六角 AI Vibe Coding 體驗營期末大魔王作業
這份筆記旨在記錄 2025 六角 Vibe Coding 體驗營每日作業 Day 21 的期末專案成果,從一個簡單的個人痛點出發,透過與 AI(在我這個情境中是 Perplexity)協作,在一天內完成了一個包含前後端的全端網頁小工具:「修煉圈圈 Practice Rings」。
今天完成了三個練習,核心收穫是「在測試保護下進行重構」與「從指令式到宣告式的思維轉換」。
在重構現有函式之前,我先為它補齊了單元測試。測試案例明確定義「給定輸入 X,預期輸出 Y」的行為契約,涵蓋正常情境、邊界條件與空值處理。當測試通過(綠燈)時,代表這個函式的「對外承諾」已被測試鎖住。
重構的第一步,我刻意寫了一個「只做一半」的實作,讓測試故意失敗(紅燈)。這個步驟的價值在於驗證測試真的有在檢查關鍵邏輯,而不是「假性通過」。看到紅燈後,我確認測試確實能偵測到實作缺陷,才放心進入下一步。
補齊邏輯讓測試回到綠燈後,我開始專注在「內部實作的優化」——從 for 迴圈改寫為 map().filter() 的 pipeline 風格。這個過程中,每次調整後我都會立刻跑測試,確認「對外行為」依然不變。這種「小步前進、頻繁驗證」的節奏,讓我能放心調整程式結構,不用擔心改壞卻沒發現。
原本的 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 的價值不在於「有沒有測試」,而在於它強制我先思考 API 介面設計、再思考實作細節。寫測試的過程中,我會自然地問自己:「這個函式怎麼用最直覺?」「輸入輸出的資料結構怎麼設計最清楚?」這種「由外而內」的思考方式,讓我寫出的函式介面更符合使用者(也就是呼叫端)的心智模型。
沒有測試保護時,我會猶豫是否該重構——「改了會不會壞掉?」有了測試後,我能放心調整內部實作,因為任何破壞都會立刻被偵測到。這種「安全感」讓我更願意持續優化程式碼,而不是讓技術債累積。
Uncle Bob 提倡的「幾秒鐘循環一次」TDD 流程,核心精神是降低每次變更的風險半徑。一次只改一小塊、立刻驗證,比一次改一大片再來除錯要高效得多。今天的練習讓我深刻體會到這種節奏的威力。
今天完成了三個練習,核心收穫是「在測試保護下進行重構」與「從指令式到宣告式的思維轉換」。
在重構現有函式之前,我先為它補齊了單元測試。測試案例明確定義「給定輸入 X,預期輸出 Y」的行為契約,涵蓋正常情境、邊界條件與空值處理。當測試通過(綠燈)時,代表這個函式的「對外承諾」已被測試鎖住。
重構的第一步,我刻意寫了一個「只做一半」的實作,讓測試故意失敗(紅燈)。這個步驟的價值在於驗證測試真的有在檢查關鍵邏輯,而不是「假性通過」。看到紅燈後,我確認測試確實能偵測到實作缺陷,才放心進入下一步。
補齊邏輯讓測試回到綠燈後,我開始專注在「內部實作的優化」——從 for 迴圈改寫為 map().filter() 的 pipeline 風格。這個過程中,每次調整後我都會立刻跑測試,確認「對外行為」依然不變。這種「小步前進、頻繁驗證」的節奏,讓我能放心調整程式結構,不用擔心改壞卻沒發現。
原本的 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 的價值不在於「有沒有測試」,而在於它強制我先思考 API 介面設計、再思考實作細節。寫測試的過程中,我會自然地問自己:「這個函式怎麼用最直覺?」「輸入輸出的資料結構怎麼設計最清楚?」這種「由外而內」的思考方式,讓我寫出的函式介面更符合使用者(也就是呼叫端)的心智模型。
沒有測試保護時,我會猶豫是否該重構——「改了會不會壞掉?」有了測試後,我能放心調整內部實作,因為任何破壞都會立刻被偵測到。這種「安全感」讓我更願意持續優化程式碼,而不是讓技術債累積。
Uncle Bob 提倡的「幾秒鐘循環一次」TDD 流程,核心精神是降低每次變更的風險半徑。一次只改一小塊、立刻驗證,比一次改一大片再來除錯要高效得多。今天的練習讓我深刻體會到這種節奏的威力。
Share Dialog
Share Dialog
No comments yet