最佳的學習環境
我釋出最初版的 PR 式實境學習流程後,最多人回饋的點就是:對初學者來說門檻太高。
的確,Coding 領域本身相對困難,用了擬真的環境只有提升學習的真實性,並沒有降低學習門檻。就算加入了遊戲化要素也只是提升使用者的興趣,並沒有讓他變簡單。
One shoe doesn't fit all。初學和進階需要的學習完全不同。因此我重新定義了學習路徑:
- 初學:低門檻,用明確易懂的視覺、圖像化和生活連結來讓使用者踏入 Coding 領域
- 進階:擬真場景,用原本的 mission 式的題目去讓使用者模擬真實商務場景的 contribute 流程。
Skellar Code - Starters
我將這兩階段分成不同的學習模式:
- Skellar Code - Starters:用豐富直觀的視覺化和簡單的任務,了解程式語言基本運作原理
- Skellar Code - Contributors:用真實的專案場景,完成真實需求,並通過 PR 驗證

我參考了幾種不一樣的初學者 coding 學習平台
- Brilliant.org
- Scratch
- freeCodeCamp
- Codecademy
- Khan Academy
- Udacity
- Tynker
- CodeMonkey
我發現「視覺化」是降低們檻的關鍵,而他們主要聚焦在這幾種視覺化:
視覺化 Logic Flow
如 Scratch 本身,必要,但當 components 變多,反而讓整段「程式」過於龐大而難懂,維護起來也複雜。
Solution: VSCode Debugger。既然要逐行顯示執行順序和流程,那麼直接讓執行過程和 Debugger 結合可以說是完美方案:直觀、擴充性好、減少開發成本。
視覺化 Values & Data Manipulation
許多初學者對變數操作感到困惑,例如:
a = 3
之後為什麼可以再宣告 a = 5
?
a + 3
為什麼不會改變變數,要用 a += 3
?
稍微複雜一點的程式就會因為「中間值」看不到而陷入 Debug 地獄。
Solution: Data and Expression Visualizer(DEV)。
在 DEV 裡,apple_count = 3
會顯示一個箱子,裡面放 3 個蘋果;當運算子執行時則呈現動畫。這比傳統的變數樹狀結構直觀得多。
VSCode Extension 的製作與瓶頸
VSCode Extension 的開發是由官方的 TypeScript yo package 製作的,為了呈現 DEV webview 介面,獨立出了一個 Vite + ReactJS 的專案來開發 webview 內容。
當使用特定 Command 時,extension 會透過幾個不同的資料來源來渲染圖像化的執行過程
Debugger Adapter Protocol (DAP)
VSCode Debugger 提供了一個跨語言的斷點資料結構,讓 extension 可以拿到執行環境、現在有哪些變數、變數值等資料。
但透過 DAP 拿到的資料只有當下的 snapshot,想要知道現在是不是在一個 for loop iteration 或 if else block 中是不夠的,因此我們還需要一個資料來源
Abstract Syntax Tree (AST)
AST 能靜態解析程式結構,例如:
- 哪些區塊是迴圈
- 哪些是條件判斷
- 哪些是函式呼叫

將 AST 與 DAP 的 snapshot 合併,就能同時看到「程式架構」與「執行狀態」。這讓 DEV 得以動畫化還原整個流程。
目前我可以標示「在一個 for loop 中」,但還缺「第幾次迭代」的 pointer。如果 iterable 沒有重複值,可以直接比對 target 值在 iterable 的 index。但當 iterable 含有重複元素時,單靠 DAP + AST 還是無法精準定位。
這時候,就需要 更底層的手段:Instrumentation。
Instrumentation
監控植入,是在程式開始前, inject 一段針對程式碼的執行過程監控的追蹤程式

透過 DAP 的 session.customRequest('evaluate')
功能,我們可以在執行 user 執行前 inject 追蹤程式碼
為了實現 for loop 中的迭代次數,我們從 injection 中加入了一段 tracing,只要當前的 instruction 是 FOR_ITER
,我們就找出該行的 loop list
和 loop var
,並把 counter + 1,並將這個變數 expose 到 global。
# structure: __daps_progress[list_name][var_name] = index
__daps_progress: Dict[str, Dict[str, Any]] = {}
def trace_function(frame, event, arg):
# we still return the tracer to continue tracing in nested frames
if event == "line":
try:
filename = frame.f_code.co_filename
lineno = frame.f_lineno
source_line = linecache.getline(filename, lineno).rstrip()
print(f"Tracing line {lineno}: {source_line}", flush=True)
except Exception:
return trace_function
if _is_for_line(source_line):
...
__daps_progress[loop_list][loop_var]['index'] += 1
再從 extension 中用 DAP 的 customRequest('variables')
來取得這個值,最後顯示 pointer 在 list 相應的位置上

結語
這個 extension 初期雖然只適用於 python,但只要支援上述三種解析追蹤行為的程式語言,未來都可以擴充,不過現階段我只會專注於實現 python 的功能。
能透過 VSCode Extension 完成的事比想像中的更多,這次 PoC 無疑是有史以來最大的強心針,下一步可以整合 Skellar 平台自身的道具功能,提供提示、限時 AI tutor 等功能。
Starscribers Discord Server: https://discord.gg/KURmknGA
Skellar Open Beta: https://skellar.rn-ws.com/