看到小孩連續三題紅叉,以前我會馬上湊過去給提示。後來想通:習題本根本就是測試案例的集合,紅叉不是壞事,是「該長大的地方」在告訴你。把這套思路帶進育兒,叫它『失敗確認驅動』。育兒框架系列 第 2 篇。
「又錯了啦。」
數學評量,前三題連續紅叉。小孩在那邊嘟嘴,瞪著紙。
說真的,一年前的我大概會「欸唷」一聲,順手在下一題旁邊偷偷寫個小提示。就那麼一下。
之前寫過 小孩跌一下,我就先把他撈起來了,結果寫完了,習慣也沒那麼快戒掉。一看到一排紅叉,手就會自己先伸出去。
不過最近,我有比較安靜一點點。想把理由整理一下。
道理大家都懂啦。但實際看到自家小孩考卷分數的瞬間,理智就掉到地上了。我也常常這樣。
不過自己想一想,長大之後還記得的,大部分都是 當年寫錯的地方。順順寫完的題目,早就忘了。
先寫一下我自己的定義 (只是我家這樣想啦)。
到第三步才算開始念書,在我心裡是這樣劃的。
只把題目解完,還不是念書。
解完加上對答案,也還不是念書。
到「打分數,看幾個圈圈幾個叉叉」就停,然後為對的多錯的多開心或失落 ── 那樣分數其實不會動。會動的關鍵,是把叉叉那邊真的弄懂。
… 寫完還是要承認,小時候我也是「打完分數就放生」那一派的,所以也沒什麼立場唸別人。
切到工程師頻道一下。
軟體開發現場有個東西叫「Bug 曲線」 (現在大家比較少特別提了)。把測試階段抓到的 bug 數量,沿著時間軸畫出來。
有趣的地方是:測完一輪,回報「都沒抓到 bug」,現場通常不會歡呼。反而會皺眉一下,真假? 那種反應。
為什麼?因為開發現場的前提就是 人會出錯。Code review、測試、CI,整套都是建在「人會手滑」這個假設上。
沒抓到 bug 不等於沒 bug。常常代表「測試太鬆」,bug 還在裡面只是沒被翻出來。
這篇我最想講的應該是這段。
明明在講開發的事,可是一講到「人會出錯」這個前提的瞬間,這個 know-how 其實沒理由只關在開發圈裡面對吧?
講「人」嘛。那「人」就包括小孩,也包括我。
建立在「人會出錯」前提之上的那些做法,大概都可以原樣搬到念書這邊。我們不會把「production 上零 bug」當成理想,所以我們也沒有理由把「考卷上零紅叉」當成理想。
給沒寫過 code 的人快速說明一下,TDD (測試驅動開發) 大概是這樣:
def test_add():
assert add(1, 2) == 3 # ← 先把「正確答案」寫下來 (現在跑會壞掉 = Red)
def add(a, b): # ← 然後才寫實作
return a + b # ← 跑得過測試就是 Green
先寫「應該長這樣」的測試 (答案),從壞掉的狀態 (Red) 開始,把實作慢慢修到測試會通 (Green)。一直循環。
寫到這邊我自己也才想到 ── 習題本,根本就是這個東西。
小孩 (= 那個要被實作出來的本體) 現在還是紅的。所以就解題。解錯了 (Red 留在那邊)。看解答,把「為什麼」吸收進來。下次遇到同類型題,通了 (Green)。
寫習題本的目的,不是把眼前這幾題寫完。
是把自己變成 Green。
從這個角度去看,看到紅叉就垮下來那個反應,好像就有點不太對。紅叉就是 Red,就是一個測試結果,而且還很貼心地指了路:「下次要修這裡喔。」
講白了就是 失敗確認驅動 (Failure Confirmation Driven) 育兒。
寫出來真的也沒什麼了不起。可是套上 TDD 的詞彙之後,我自己比較講得清楚:為什麼最近看到小孩一排紅叉,我可以不立刻緊張。
我跟小孩,大概是這樣講的:
「寫題目本身不是念書喔。紅叉幾個都沒關係。把紅叉那邊弄懂,才是念書。倒過來想,就是 ── 你又知道一個『該長大的地方』在哪邊了。其實還不錯欸。」
看他一臉不買單。我就現場出題試試看。
1+1=?、1+2=?、1+3=?
當然秒答。
「有變強嗎?」
「沒有啊,我本來就會。」
「對嘛。全部都圈圈,那寫這本就沒意義了。本來就是要把叉叉挖出來。找到叉叉,等於找到一個可以長大的地方。」
這應該是很普通的事啦。可是我自己也是寫到這邊才比較講得出口。
順著這條線想,寫作業這件事的意義也變了一下。先預習一下、再來做題目,好像也不錯。題目就是測試案例嘛。