線上課程觀課進度管理小工具開發日誌
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」。
這兩天花了不少時間在練習「輸入驗證」、「CLI 互動」與「核心邏輯」的責任分層上,並持續透過 Test-Driven Development (TDD) 的流程來實作演算法。這篇文章整理了我今天在實作過程中的一些設計決策與心得,特別是如何利用 Vitest 進行參數化測試,以及從命令式程式碼走向聲明式重構的過程。
在處理使用者輸入時,很容易把「檢查邏輯」和「運算邏輯」混在一起。為了讓程式碼更乾淨,我嘗試將系統切分為三層,讓每一層只專注做一件事。
這一層的責任是「守門員」:接收外部傳來的髒資料(例如使用者輸入的字串),負責清洗、轉型,最後只吐出「合法的原始型別值」或直接丟出錯誤。
例如,我們常需要檢查一個輸入是否為「正整數」。與其在業務邏輯裡到處寫 if (val < 0),不如抽成一個專用的 parsePositiveInt 函式。這裡我用到了一個好用的技巧:預設參數 (Default Parameters)。
可以設計成 parsePositiveInt(input, min = 1)。
預設只檢查是否 >= 1。
如果某些情境需要更嚴格(例如大於 5),也可以彈性傳入 min 參數。
相關 MDN 參考:
這一層負責跟使用者「對話」。它的工作很單純:問問題、拿答案、交給驗證層檢查。
若驗證通過:就把乾淨的值往後傳。
若驗證失敗(丟錯):直接 catch 起來印出錯誤訊息,然後再問一次。
這樣的設計讓 CLI 層完全不需要知道「什麼是合法的整數」,它只負責「重試」這個行為流程。
這是最乾淨的一層。它假設收到的參數一定是合法的(因為髒資料早在驗證層就被擋掉了)。
這樣做的好處是:核心函式裡不再充滿防禦性的 if-else,可以專心處理演算法或業務規則。這也讓這一層特別容易進行單元測試。
在實作演算法(例如「判斷質數」或「陣列搜尋」)時,我採用了 TDD (Test-Driven Development) 的節奏:紅 (Red) → 綠 (Green) → 重構 (Refactor)。目前還在熟悉 Uncle Bob 提倡的「最小化測試與重構」這個每次只推進幾行程式碼的思考流程。
與其寫十幾個 it(...) 來測不同的數字,不如使用 Table-Driven 的方式把測資列成表格。在 Vitest 中可以使用 test.each:
describe('質數索引搜尋', () => {
test.each([
// [輸入陣列, 預期結果]
[, [{ val: 3, idx: 1 }, { val: 13, idx: 3 }]],
[, []], // 沒找到的情況
[[], []], // 空陣列邊界測試
])('輸入 %j,應回傳 %j', (input, expected) => {
expect(findPrimes(input)).toEqual(expected);
});
});
這種寫法讓測試與資料分離,新增案例時只需要在陣列裡多加一行,非常直觀。
Vitest 參考:Test API
以「找出陣列中所有質數與位置」這個需求為例,我的 TDD 過程是這樣的:
第一版(寫死): 為了先確認測試架構沒問題,我會先直接 return 一個固定的陣列讓測試通過。這聽起來很蠢,但能確保「測試程式本身」是對的。
第二版(命令式:For Loop + Push): 這是最直覺的寫法。建立一個空陣列,跑迴圈,遇到符合條件的就 push 進去。 這時候的重點是「把邏輯寫對」,通過所有測試案例。
第三版(聲明式:Map + Filter): 在測試「保護」下,我可以放心地重構程式碼,把 for 迴圈改成更具語意的高階函式 (Higher-Order Function)。
在前端開發(尤其是 React/Vue)中,我們非常依賴 map、filter 這類高階函式 (HOF)。這次練習中,我也嘗試把原本的 for 迴圈重構成資料流管道 (Pipeline)。
簡單來說,只要一個函式能接收函式當參數,或回傳一個函式,它就是 HOF。
命令式寫法 (Imperative): 「建立空陣列 → 跑迴圈 → 判斷條件 → push 進陣列」。這是在告訴電腦怎麼做 (How)。
聲明式寫法 (Declarative): 使用 filter 篩選、用 map 轉換。這是在告訴電腦我要什麼 (What)。
MDN 參考:
透過 TDD 的保護,我可以確認重構前後的行為完全一致,但程式碼的可讀性與維護性卻得到了提升。
這兩天的練習讓我體會到,寫程式不僅僅是把功能做出來,更重要的是架構的整潔度與測試的保護網。
責任分層讓每一段程式碼都好測、好改。
TDD 讓我敢於重構,不怕改壞舊功能。
參數化測試 讓邊界案例的測試變得輕鬆且完整。
從小型的練習題開始,每次都把整個架構流程完整跑過一遍,建立好的開發習慣。在實際的專案開發中,也是維持程式碼品質的重要基石。
這兩天花了不少時間在練習「輸入驗證」、「CLI 互動」與「核心邏輯」的責任分層上,並持續透過 Test-Driven Development (TDD) 的流程來實作演算法。這篇文章整理了我今天在實作過程中的一些設計決策與心得,特別是如何利用 Vitest 進行參數化測試,以及從命令式程式碼走向聲明式重構的過程。
在處理使用者輸入時,很容易把「檢查邏輯」和「運算邏輯」混在一起。為了讓程式碼更乾淨,我嘗試將系統切分為三層,讓每一層只專注做一件事。
這一層的責任是「守門員」:接收外部傳來的髒資料(例如使用者輸入的字串),負責清洗、轉型,最後只吐出「合法的原始型別值」或直接丟出錯誤。
例如,我們常需要檢查一個輸入是否為「正整數」。與其在業務邏輯裡到處寫 if (val < 0),不如抽成一個專用的 parsePositiveInt 函式。這裡我用到了一個好用的技巧:預設參數 (Default Parameters)。
可以設計成 parsePositiveInt(input, min = 1)。
預設只檢查是否 >= 1。
如果某些情境需要更嚴格(例如大於 5),也可以彈性傳入 min 參數。
相關 MDN 參考:
這一層負責跟使用者「對話」。它的工作很單純:問問題、拿答案、交給驗證層檢查。
若驗證通過:就把乾淨的值往後傳。
若驗證失敗(丟錯):直接 catch 起來印出錯誤訊息,然後再問一次。
這樣的設計讓 CLI 層完全不需要知道「什麼是合法的整數」,它只負責「重試」這個行為流程。
這是最乾淨的一層。它假設收到的參數一定是合法的(因為髒資料早在驗證層就被擋掉了)。
這樣做的好處是:核心函式裡不再充滿防禦性的 if-else,可以專心處理演算法或業務規則。這也讓這一層特別容易進行單元測試。
在實作演算法(例如「判斷質數」或「陣列搜尋」)時,我採用了 TDD (Test-Driven Development) 的節奏:紅 (Red) → 綠 (Green) → 重構 (Refactor)。目前還在熟悉 Uncle Bob 提倡的「最小化測試與重構」這個每次只推進幾行程式碼的思考流程。
與其寫十幾個 it(...) 來測不同的數字,不如使用 Table-Driven 的方式把測資列成表格。在 Vitest 中可以使用 test.each:
describe('質數索引搜尋', () => {
test.each([
// [輸入陣列, 預期結果]
[, [{ val: 3, idx: 1 }, { val: 13, idx: 3 }]],
[, []], // 沒找到的情況
[[], []], // 空陣列邊界測試
])('輸入 %j,應回傳 %j', (input, expected) => {
expect(findPrimes(input)).toEqual(expected);
});
});
這種寫法讓測試與資料分離,新增案例時只需要在陣列裡多加一行,非常直觀。
Vitest 參考:Test API
以「找出陣列中所有質數與位置」這個需求為例,我的 TDD 過程是這樣的:
第一版(寫死): 為了先確認測試架構沒問題,我會先直接 return 一個固定的陣列讓測試通過。這聽起來很蠢,但能確保「測試程式本身」是對的。
第二版(命令式:For Loop + Push): 這是最直覺的寫法。建立一個空陣列,跑迴圈,遇到符合條件的就 push 進去。 這時候的重點是「把邏輯寫對」,通過所有測試案例。
第三版(聲明式:Map + Filter): 在測試「保護」下,我可以放心地重構程式碼,把 for 迴圈改成更具語意的高階函式 (Higher-Order Function)。
在前端開發(尤其是 React/Vue)中,我們非常依賴 map、filter 這類高階函式 (HOF)。這次練習中,我也嘗試把原本的 for 迴圈重構成資料流管道 (Pipeline)。
簡單來說,只要一個函式能接收函式當參數,或回傳一個函式,它就是 HOF。
命令式寫法 (Imperative): 「建立空陣列 → 跑迴圈 → 判斷條件 → push 進陣列」。這是在告訴電腦怎麼做 (How)。
聲明式寫法 (Declarative): 使用 filter 篩選、用 map 轉換。這是在告訴電腦我要什麼 (What)。
MDN 參考:
透過 TDD 的保護,我可以確認重構前後的行為完全一致,但程式碼的可讀性與維護性卻得到了提升。
這兩天的練習讓我體會到,寫程式不僅僅是把功能做出來,更重要的是架構的整潔度與測試的保護網。
責任分層讓每一段程式碼都好測、好改。
TDD 讓我敢於重構,不怕改壞舊功能。
參數化測試 讓邊界案例的測試變得輕鬆且完整。
從小型的練習題開始,每次都把整個架構流程完整跑過一遍,建立好的開發習慣。在實際的專案開發中,也是維持程式碼品質的重要基石。
Share Dialog
Share Dialog
No comments yet