本文為星箭廣播 154 集——連載再開!從程式設計之道走向軟體工程師的修煉與成長(ft. vgod) 訪談逐字稿,為了方便閱讀,內容經過編修。本集節目介紹與相關連結請到此頁面閱讀。
本集使用說明&來賓介紹
Titan:嗨!大家好!歡迎收聽星箭廣播第 154 集,我是主持人 Titan,今天很特別,我們又再度要跟來自矽谷的來賓連線,這次邀請到的特別來賓,他在網路上的 ID 應該蠻多聽眾,特別是現在 30 歲左右,或是更老的工程師可能都有聽過,我們今天的特別來賓就是 vgod 張琮翔,我們先請他跟聽眾朋友打招呼。
vgod:嗨!大家好!我是 vgod 張琮翔,我在矽谷這邊一個軟體公司工作,很高興今天收到 Titan的邀請,來星箭廣播跟大家分享我的一些心得。
Titan:對於一些太年輕的聽眾,我這種說法是從一種比較忌妒心態,太年輕而不是這種比較中性的說法,是比較年輕,我覺得對於一些太年輕的聽眾還是要介紹一下,vgod 他是一位從小在台灣長大的台中人,後來去 MIT 讀博士,現在在矽谷的軟體公司擔任軟體工程師,我現在講起來輕描淡寫,等一下你就知道他有多厲害。
這次能夠邀請到 vgod,其實本來還想找我們星箭廣播的老朋友 iCook 愛料理的共同創辦人 Richard 一起來錄音,跟 vgod 一起聊軟體工程師跟程式設計這件事情,可惜因為時間的關係,比較沒有辦法,我覺得我不敢說我是讀 vgod 的文章長大,但 Richard 一定是讀 vgod 的文章長大,他算是你的粉絲,他反而還沒跟你見過面,我以前還有在矽谷跟你見過面,Richard 對我們後面要錄的集數的題目設計跟規劃裡面,提供蠻大的幫助,畢竟我自己不是軟體工程師,所以大家要記得回來聽我們後面的節目。
這次邀請他來錄音真的蠻開心,因為我從大學時期嗎?或是剛畢業那時候開始讀他的文章,他那時候寫了一系列的文章,其實有些人我猜讀過很多次〈追求神乎其技的程式設計之道〉,加上番外篇總共有 12 篇,他在最近把它重編了一次,在他 Medium 的部落格上面有重新刊登,變成一整篇文章,我看 Medium 一個比較不準確的計時方式,因為他們大概是用英文的方式去計算閱讀這樣一篇文章要多久,可能要讀超過1小時,我覺得中文的話,如果大家用正常速度讀可能會更久一點。
這次邀請到 vgod 來上節目的契機是因為他最近,我猜啦!應該是因為生完小孩,小孩長比較大了,有時間重新寫文章,加上他職涯又開始到另外一個階段的發展,我猜他應該有覺得是時候在回顧一下,重新開啟一系列的文章叫做〈軟體工程師的修煉與成長〉,前面講的第一個系列文章,叫做〈程式設計之道〉,後來變成〈軟體工程師的修煉與成長〉,關鍵字大家可以記一下,我們這次計畫順利的話,就是兩集,如果不順利的話,可能會更多集,我們希望透過〈程式設計之道〉這系列的文章,跟大家做一個開場,然後讓大家了解到 vgod 他從國中開始到他到 MIT 去讀博士結束,甚至還有短暫創業的時期,作為一個開場,也是我們第一集的主題。
最主要是希望可以作為一個銜接到第兩集,讓他〈軟體工程師的修煉與成長〉這系列文章寫的內容,在我們錄音的前兩天,他刊登了第七篇文章,之後應該還是會繼續往下寫,我們希望可以用兩集的方式,讓大家稍微瞭解一下程式設計這件事情,跟當你到軟體公司,尤其是已經有一定規模的軟體公司去上班,作為一個軟體工程師 vgod 他的體會,後來的〈軟體工程師的修煉與成長〉第一篇,大家可能會發現說他自己有稍微,講反省有點太誇張,他自己有稍微分析了一下,他剛成為全職的軟體工程師的一些體悟,跟他以前想的可能又蠻大的不同。
今天我們節目大概分成三個部分,第一個就是請 vgod 回顧一下,我想這個應該在學術圈蠻常見的,這種講學思歷程的東西。先認識一下 vgod 一路學習寫程式,求學的階段,到真的要開始當一個軟體工程師的時候,他初期遇到的一些問題,以及他的一些理解,再來就是他在公司裡面尋求協助跟一些突破,過程當中比較初步的歷程。vgod 是從國中就開始自學寫程式,大家回想起來,自己一開始接觸程式的時候,總是有一些不同的起點,我覺得聽這個故事是蠻有意思的。
國中自學程式學到的重要一課
vgod:如果要從我國中講起的話,這個已經好久以前,超過十年了,現在想起來。國中的時候我記得那時候還沒有 internet 這個東西,其實有了啦!那時候我記得我剛接觸到電腦的時候,就是玩一些單機的遊戲,然後那時候我記得我家裡有一台新買的 modem,跟現在比起來,大概是現在的一千倍慢吧,那時候也沒有 Google,所以那時候要學東西其實是非常困難的。
國中的時候,一開始記得像大家一樣,很多時間都花在學校,學學校的東西,可是我覺得那個開始的契機是我在國三的時候,因為先推薦甄試上了台中一中,不用去考聯考,現在不叫聯考,所以我的國三其實就很 free,我就可以自己決定我想要做什麼,那時候我就利用那個時間開始學寫程式,我學的方法其實就是去買了一些書,然後自己開始看。
那時候學的程是語言叫做 Visual Basic,現在我不確定還存不存在,可能已經沒有人在用這個程式語言了,Visual Basic 是一個微軟出的,用來做圖形化介面的程式語言,你可以很容易的拉一個視窗,在視窗上面加入你想要的一些 Events,再填寫那些 events 的 handler,你就可以做一些很簡單的視窗程式了。
當初我開始寫程式的時候,我的目的其實是為了要寫遊戲,因為我是一個很喜歡玩遊戲的小孩,所以寫遊戲對我來說是我的一個夢想。第一個目標就是我想要先寫出一個自己的遊戲,在我國三的時候,老師在台上上課,我在下面其實就看我自己的書,因為我沒有升學壓力,所以老師其實也不太管我在幹嘛,學校沒有電腦,所以我是回家再用電腦真的去把我學到的東西,把它試做出來,大概就這樣子花了將近整個國三,快一年的時間。
Titan:我那時候在讀文章的時候,你說在學校先用看的,然後在腦中想,或者是紙筆寫,回家再把程式 key 到電腦裡面去,這有點像是很久以前,大家在用那種打孔機的感覺,物理的。
vgod:對,沒錯。在用打孔寫程式的時候,其實你必須要先把程式想得非常清楚才能寫,因為你在寫的時候,是沒有任何 feedback,就要把它放到電腦裡去,執行後才會有結果,那時候學寫程式,其實差不多就是這樣。我在學校看完書,會先用紙筆先寫,寫一些東西下來,可是寫出來的東西,其實完全不會知道他到底會不會 work,你真的要打到電腦裡面才知道,這個 feedback 的 loop 其實是蠻長的。我就這樣持續做了將近一年吧,那時我回家開始寫的時候,訂了一個計劃,我想要寫出一個自己的小遊戲,那時候我決定的是黑白棋,我會選這個遊戲是因為那時候有電子辭典,我不知道你小時候有沒有用過,快譯通之類的電子辭典,電子辭典上面就有黑白棋這個遊戲。
我覺得這遊戲夠簡單,而且好像我只要學了一點程式,我就可以寫出來,所以我就把這個當作目標,開始學習寫程式。這樣花了幾個月,可能將近一年的時間,回家慢慢地寫,最後還真的把它寫出來了,可是這中間有很多很痛苦的 debug 經驗吧,這算是我寫程式遇到的第一個很大的瓶頸,放很多程式進去電腦以後,電腦跑出來的東西跟你想的完全不一樣,有一些狀況是你事先沒有想清楚,沒有想到的,你如過想的沒有夠透徹的話,你就會漏掉一些狀況,你如果只看電腦給你的回饋,他跑出來的樣子是很難發現他根本那個深層的原因是什麼,這件事情讓我一開始困擾很久,一開始的這個 bug,讓我花了一兩個禮拜吧。
當初那個 bug 是這樣的,黑白棋就是你可以下一個子,它會把例如說這兩個黑棋中間連到的所有的白棋全部吃掉,會把它全部翻過來,可是那時候我就下了一個子以後,他會把整個盤面都打亂,完全像一個亂數的盤面一樣,我不知道為什麼會這樣。我花一兩個禮拜的時間在 trace 這個程式,然後研究到底發生什麼事情,結果最後發現其實只是一個變數忘了歸零而已,程式裡面有幾個迴圈,然後裡面其中一個變數忘了歸零,就造成一個完全意想不到的結果。
Titan:你這個 debug 的過程完全都是自己跟自己在檢查這個程式?反覆的測試嗎?有沒有去問別人或是尋求協助,還是其實當時的你也沒有這個管道?
vgod:當時我完全沒有任何管道,因為在我家裡,我爸媽其實完全不會寫程式,他們也不太懂電腦,然後我周圍的人,也沒有認識任何人會寫程式,我是完全靠自己念書,然後學起來的。那時候也沒有 internet,所以你也沒有 Stack Overflow,也沒有 Google,現在很簡單,你把你碰到 bug 打到 Google 裡,你很容易就可以找到答案了,大概 90% 的 bug 其實都可以這樣找出來,可是那時候完全沒有,我就只能自己一行一行的去 trace 這個程式,在 debug 的時候,你可以 step by step 執行那個程式,然後去觀察裡面的每一個變數,他變成什麼新的質,然後就這樣一行一行去跑,才真的找到這個問題在哪裡。
Titan:我覺得第一個蠻有趣的是你開始注意到一件事情,如果你可以早一點把犯錯的原因,把那個根源找出來,而不是只是單純的提醒自己,原來我當時變數的設計是有問題的,以後不要再犯錯就好。因為我覺得這個概念不是只有在寫程式才有,其實做很多事情都有一點像是這樣,大部分的狀況我們可能都會自己跟自己講不要忘記就好。比如忘記帶鑰匙,我下次就不要忘記就好,可能有少部分人會開始想,我要怎麼樣讓自己不要忘記,比如把鑰匙放在門口,或者是多打幾個鑰匙,像是這種方式。我不知道你大概是什麼時候開始去注意到這件事,還是說你當時就馬上開始很深入的去反省這件事情。
vgod:我覺得我一開始的時候,碰到這個 bug 我把它修掉以後,當時沒有馬上意識到,我需要例如:改變我的習慣。也是過了一陣子當我再繼續寫更多程式的時候,所以這樣大概是幾天、幾個禮拜吧,因為那時候我很密集的在學這件事情,所以我從頭到尾,其實都在想這件事情,在想的過程中,我一邊除了學新的,例如:Coding 的語法,或者是 Coding 的技巧以外,我其實也會想怎麼讓自己以後不要再犯一樣的錯,就像你講的提醒自己其實不是好的方法,因為人一定會忘記事情,人的腦天生有這個缺陷,我們沒有辦法把事情記得很好,所以才需要用電腦。
我理解到這一點以後,就會知道一定要有一個比較系統化的方法,或是要徹底的改變我寫程式的習慣,才有辦法在以後避免這個問題,所以那時候我其實理解到這點以後,我就發現說這個其實是一個改變我 coding style 就可以解決的問題,如果當初我宣告變數的時候,不是像書裡面,大部分的書都會講,你宣告變數要在你整個函式的一開頭,這件事情在大部分時候是 ok 的,可是這個習慣並不是最好的,你如果把這個習慣稍微改變一下,在你真的要用到那個變數的時候,才宣告那個變數,讓你用到的地方,那個 blog 自動把變數重新 reset,重新把它 release 掉,就自然不會遇到這個問題了。
所以在哪裡放這個變數,其實是會造成很大的影響,可是一般的書在教你的時候,只會跟你說你就把所有的變數宣告放在函式一開頭就好了,有的甚至完全不講這件事情,讓你放在全域的變數也沒有關係,可是你如果寫程式寫就知道,把那個變數放在全域變數是一件非常糟糕的事情,因為它會汙染你整個程式,這會造成很多意想不到的結果,就像我當初犯了這個 bug 一樣。
後來我理解到這件事情以後,我就開始改變我 coding 的習慣,開始更注意寫程式的 structure 應該要長什麼樣子,你的變數應該要放哪裡,甚至變數要怎麼命名,這些其實都會造成很大的影響,會讓我更不容易犯錯,因為我不可能完全不犯錯,可是如果改變習慣會減少犯錯的機會,其實這樣就可以跟值得。
Titan:我剛好最近在讀一本書叫《清單革命》,它剛好也是用這種比較系統化的方式,當然它處理的問題並不是寫程式的問題。作者是一位外科醫師,他寫這本書的契機就是在醫院裡面有一些程序,他們想要找出是什麼原因會導致病人在術後,通常都是感染而死亡,手術過程可能根本沒有問題,但是因為不明的原因造成這樣子的結果,他們想要找出來,這個之後有機會可以再跟大家談。
vgod 的這系列文章,我根本就不是工程師,也不會寫程式,但其實我這樣讀下來是不會有太多的障礙,我想可以先跟我們其他不同背景的聽眾說明一下,我是蠻鼓勵大家去讀一下這系列的文章,包含最近 vgod 開始寫這個新的系列〈軟體工程師的修煉與成長〉,假如你是設計師,或是你是 PM 的話,我覺得去了解這種軟體公司裡面工程師的運作,他們對於一些問題跟遭遇到一些狀況該怎麼處理,他們的想法我覺得去了解是很有意思的。
參加程式競賽
Titan:接下來我們把這個時間快轉到高中,根據的他說法,接下來就是要進入到他升上高中之後,應該就是他覺得自己進步速度非常快的一個時期,這種飛輪的效應是怎麼開始轉的,
vgod:我升上高中以後,我一開始很巧合的認識了一個學長,他非常厲害,他現在在 MIT 當教授。當初,他是中一中的資訊代表隊的一個成員,他那時候就有 demo 給我看一個他用 QBasic 寫的一個遊戲,那時候我看的時候,我真是目瞪口呆,那個遊戲的品質就像你在外面會買到的遊戲一樣,那個畫面、聲音,還有它的流暢度,完全不像是一個高中生寫出來的程式,看到這影片後,我覺得非常的震驚,我就開始問他說要怎麼樣才能變得像他這樣,要怎樣才能寫出這麼好的程式來。
他就開始跟我講他寫程式是自學起來的,可是他同時有在參加一個叫資訊能力競賽,還有資訊奧林匹亞這個比賽,資訊奧林匹亞這個比賽是全世界的所有高中生都可以參加的比賽,算是可以當成寫程式的奧林匹克,每年都會舉辦一次,全世界的每個國家都要選出大概四個選手去參加,不是只有資訊而已,包括像數學、物理、化學、生物,都有他們自己的奧林匹亞比賽。在臺灣要參加這個比賽,需要經過幾個國內的小比賽,比如我在台中的時候,要參加中區的資訊能力競賽,前兩名還是前三名,我有點忘記,可以再去參加全國的資訊能力競賽,你如果在全國,好像是得到前十名吧,可以進入一個奧林匹亞的培訓營,等於是把全國寫程式最厲害的高中生聚集在一起,讓他們在一個地方訓練一個月,我記得是一個月。
這個比賽,當初我其實完全不知道這個是什麼,我以為我會寫程式了,因為我在國中的時候,我有自己學 Visual Basic,我覺得我好像已經會寫程式,我就跑去參加了。那時候我只是參加校內的比賽,參加以後才發現這個寫程式跟我想的完全不一樣,比得不是給一個時間你可以自由發揮,你想寫什麼都可以,而是他有一些非常 specific 的要求,他會給你一個題目,你的題目需要讀入什麼樣的輸入資料,然後你必須要輸出什麼,你的輸出必須有非常嚴格的格式,例如:你的輸出是要用書的資料做一些計算,然後輸出每一行一個數字。它的問題就是解題,比較像數學問題,而不是程式問題,程式比較像是用來解題的工具而已,你只是把你的想法用程式寫出來,讓電腦去幫你運算出結果。
你很多的問題都是要找出一些最佳化,例如:一個電信的問題是給你一個地圖,你要從 A 點走到 B 點,你要怎麼找出最短的路徑,你要把最短的路徑用程式算出來,然後把這個最短的路徑 output 出來,一個點一個點的印出來,印在螢幕上面,這樣子的問題對於高中生來說其實是蠻難的,當初我在校內比賽的時候,拿到就是這樣的問題,算比較簡單一點,可是我基本上是完全傻眼,完全不知道如何下手,而且那時候在校內比賽還是要寫程式寫在紙上面,不是用電腦寫。你寫在紙上的時候,你是完全沒有辦法想像這個電腦會輸出什麼結果,因為在那時候,你用紙筆寫程式都還是一件非常陌生的事情,我雖然會寫程式,可是我必須要有電腦才行。
Titan:我以為你國中的訓練可以在這時候發揮一點功效。
vgod:我那時候也是這麼以為,我沒有理解到這兩種程式是完全不一樣的,我自己想要寫一個遊戲,跟我需要寫個程式來解一個特定的問題,是兩件完全不同的事情。解這個特定問題,著重的是你必須要先想出這個問題的解法,你必須要有一個 Algorithm,這個 Algorithm 是可以把輸入透過某些運算的步驟,固定的步驟轉成你要的輸出,在寫遊戲的時候,其實很少這樣的東西,大部分你在做的事情是你要在畫面上,比如畫這些棋,你要決定黑色或白色,你要放在什麼位置,你要在電腦上輸入一些座標,讓你按滑鼠,按這個點它會發生什麼事情,大概是這樣的程式,可是解題的時候幾乎完全沒有這個東西,這些輸入、輸出都是比較次要的,他們著重性完全在於解題的 Algorithm 上。
當初我進入這個領域的時候,是因為我開始參加校內的競賽,那時候校內競賽,我好像只得了佳作吧,勉強被選上,進入學校的一個小的培訓營,就開始認識那時候高中其他的學長,他們其實都是以要去參加國際奧林亞為目標,跟著他們一起學,每天中午在我們學校電腦教室裡都會一起練習,雖然有一半的時間都在打電動,練習打電動,也有時間可以聚在一起討論那些題目,討論如何解題,那時候寫程式基本上就是這樣子。
奧林匹亞有個好處,它有非常大量的題目,奧林匹亞大概舉辦了十年左右,除了奧林匹亞以外,每一年國內的資訊比賽,這些題目其實都有留下來,如果用心找都找得到,那時候我花很多時間去收集這些舊的題目,我才理解到原來我要學的東西叫做 Algorithm,就是演算法,還有另外一個叫做資料結構,這兩個東西算是寫程式一定要懂的一些基礎能力,可是這些基礎能力,其實是大學才會教,你上大學以後,大學的第一年大概會開始教你寫程式這件事情,程式的語法,例如:Z 語言的語法,或是現在可能還有 Java 的語法。
語法其實跟你要怎麼指揮電腦,讓電腦如何運作是完全沒有關係的。你會一個語言,不代表你就可以寫出像莎士比亞一樣的文章,寫程式其實是一樣的道理,你必須要讓程式非常有效率,正確的工作,你必須要懂演算法和資料結構,演算法可以讓電腦知道說怎麼樣是用最有效率的方法來解決一個問題,資料結構可以讓電腦知道怎麼樣用最有效率的方式儲存一些資料,然後你用那些資料再去做運算,這兩個東西其實是相輔相成的。
一般大學大概是大二的時候才會教這件事情,所以那時候對我來說,我其實也沒有什麼管道可以學,所以我又跑去買書,買了一些演算法、資料結構的書,我還跑去把整個台中圖書館所有演算法、資料結構的書借回來看。那時候學校是有個老師,他是數學老師,我還記得他好像叫廖瑞芳老師,我還滿感謝他的,他雖然本身不太會寫程式這件事情,可是他也給我們很多資源,跟我們說要去哪裡找書,然後把我們這些都喜歡寫程式的人聚集在一起,讓我們可以互相討論。那個時候我主要的管道還是靠我自己看書,然後跟學長討論,有學長其實算是幫助蠻大的,因為他們已經在這條路上走過一段時間,相對於我,他們其實也厲害非常多,所以跟他們一起練習,讓我進步得很快。
遭遇勁敵,卻也是成長最快的時期
vgod:我覺得我進步最快的時候,是一直到高一的後半段到高二剛開始。我那時候已經去參加全國的比賽了,就是在全國能力競賽的時候拿到第二名,第一名是一個建中的同學,他非常厲害,那時候他才高一而已,所有人都覺得他應該會在那一年當上國手可以去比奧林匹亞,那時候我覺得跟他的差距感覺還蠻大的,他有一種遠遠超過我的感覺,我會這樣想是因為,那時候我們還有一個在網路上叫做 Online Judge 的練習系統,上面有非常多題目,大概有四五百題,它的問題就是從各個奧林匹亞,或是各個大學的程式比賽收集來的。
大學有一個很類似的比賽叫 ACM ICPC,他是一個團隊的解題比賽,三個人一組,可是它解的問題跟奧林匹亞的問題是類似的,對於在練比賽的人來講,我們都會上去那裡找問題,然後開始寫程式,寫完可以把你的答案 submit 上去,它就會開始跑,執行完以後就會跟你說答案是對的還是錯的,甚至它還會跟你說你的答案跑太久,超過時間。
在這個 Online Judge 系統上面,我記得這個建中的同學非常厲害,他在排行榜的非常非常頂端,可是我一開始當然在最後面,離他非常非常遙遠,可是我上了高二的時候,我就發現這個系統非常的好,因為它可以讓我很快有一個 feedback,我可以學完一個演算法,學完一個資料夾之後,馬上去找一下相關的問題,把前面講的最短路徑問題,把所有的問題都找出來,然後一題一題的寫,寫完以後就 submit 上去,對了以後就可以在排行榜上面往上升一點,我的高二基本上都在做這些事情。
我在學校其實也沒在上課,我把那個題目全部印出來帶到學校,然後我就在教室裡用紙筆寫程式,我沒有電腦,我又是用紙筆寫程式,寫完以後我就帶回家,然後在家裡把它 key 到電腦裡面去,然後跑看看答案對不對,我每天都這樣做,而且都沒什麼在上課,這樣做不知不覺我也寫了三四百題,到最後我竟然跑到那個排行榜的非常前面了,跟建中同學那時候是一直不斷在第一和第二名交替互換,因為他也每天都在寫,我覺得他應該是做一樣事情,每天在學校有時間就寫,所以他常常在第一名,我回家把今天寫的 submit 上去後,我就變成第一名,後來我們到了全國競賽,我們都進入奧林匹亞培訓營。
我在培訓裡面算是過得蠻順利的,培訓營每個禮拜都有一個測驗,算是一個迷你模擬考,有類似的題目讓大家做,然後到第二個禮拜以後就要淘汰掉大概一半的人,剩下大概四個人左右可以進入第二階段,然後在第二階段繼續訓練、測試,這樣兩個禮拜,最後選出四個人代表台灣去比賽,你如果留到第二階段,基本上你就可以保送任何一個大學的資訊科系,你可以自己選。
我在高二的時候就被丟到第二階段,最後很幸運的選上國手,可是有點可惜的是那個建中同學最後沒有選上,我其實也不知道為什麼,我覺得跟他有一種勁敵的感覺,跟他一直不斷的互相激勵,互相的讓對方進步,讓我進步的非常快,因為那時候如果你是自己一個人在練習這個東西,你是沒有一個目標的,你不知道應該要學多少才夠,或是你要練到什麼程度才行,當有另外一個人跟你一起在比賽,就像一起在賽跑一樣,他就跑在你旁邊,所以你就有一個目標,你會想要一直跟著他,甚至你可以超過他,所以他讓我不知不覺進步非常多,然後我其實也沒有理解到這件事情,一直到最後我被選上國手,我才發現這一年學到這麼多,讓我從完全不知道這些比賽是怎麼回事,到被選上台灣的代表隊國手。
Titan:vgod 在他的文章裡面有蠻生動地描寫,用大家熟悉的漫畫,這種進擊的概念,火影忍者或者像棋靈王,他裡面描述跟那位建中同學競爭也蠻有趣,大家可以去讀一下。通常漫畫也是這樣講,主角自己單方面認定這個人是我的勁敵,像櫻木花道跟流川楓這樣子。
LeetCode反而比較簡單?
Titan:還有一個我讀到印象蠻深刻的,你那時候有評價像你在作資訊奧林匹亞題目,跟工程師們在準備面試的時候,一定會碰到這種 LeetCode 的題目,你說資訊奧林匹亞題目比 LeetCode 還要難很多。
vgod:對,沒錯。那時候還沒有 LeetCode 這個東西,LeetCode 這件事情啊,其實是 Google 開始的,在矽谷,現在軟體工程師的面試,尤其是初階的軟體工程師,你一定要經過這些寫程式的關卡,已經被人家蒐集起來,變成一個題庫了,這個題庫就叫 LeetCode,這個題庫其實跟我剛剛講的 Online Judge 非常像,給你一個題目,這題目有很明確跟你說你的輸入是什麼、輸出要是什麼,然後你就寫個程式 submit 上去後,就會幫你跑程式,看看你的答案對不對。
題目的類型跟奧林匹亞其實很像,一樣也是非常著重在演算法、資料結構這些東西,要有很基礎的 Computer science 的底子,才能寫出很有效率又正確的程式,他們想要的其實就是這樣子的能力而已。
這是從 Google 開始的,Google 開始把這種面試變成標準化、一般化以後,其他公司就開始模仿,後來 Facebook,甚至其他所有大公司、小公司,全部都開始用這種類似的方式,他們的題目可以看成是比較簡單版的奧林匹亞題目,奧林匹亞的題目我們去比賽的時候,一天只有三題而已,三題我記得是給四個小時還是五個小時,非常長的時間,所以你一題可以想一個多小時,即使是去比賽的選手,都沒有辦法全部解出來,你可以解出一半其實就不錯了。
可是你在公司 interview 的時候,他給你的題目是期待你可以當場解出來的,你必須要在大概十分鐘、二十分鐘內,就有想法可以解出來,所以它的題目其實不會太難,大概都是你只要大學的演算法、資料結構底子有打好,他們目的其實是要 verify 這件事情,確定你是真的可以寫程式的,給你一個簡單的問題,你有沒有辦法把它用程式解出來。
我後來變成軟體工程師的時候才開始參加面試,發現這些面試的題目怎麼都這麼簡單,跟高中比賽的題目難度完全不能比,你如果是高中、大學有曾經參加過這些程式比賽的選手,完全不需要準備現在這種程式面試的問題,這些都太簡單了!
Titan:剛剛 vgod 這樣講,我就想到我前面有跟大家說,各位聽眾其實也可以借鑑一部分 vgod 的經驗,但我覺得一定有一些工程師聽眾一邊聽到這段的時候說哪有,根本就不是這樣。
vgod:這個我覺得是一個意外收穫啦!我在高中因為花很多時間練習這個東西,假設我高中沒有這個經驗,我現在開始去找工作,大學剛畢業,我想要找軟體公司的工作,我其實也是要花很多時間練習題目的,這叫刷題,現在很流行刷題這件事情,你要去準備面試也是要抓個兩三百題,也是很常有的事情。只是我在高中就把這件事做完,我在高中的時候就已經練習過這件事情,而且我練習的題目難度又難很多,所以對我來說這件事情相對變得比較簡單。
Titan:但這種事情總是要等你回過頭來看才會發現,當初這整件事情後來的影響力,不是只有在資訊奧林匹亞競賽有幫助而已,他還遞延到後來,你出社會找工作有這樣的幫助。
vgod:對,沒錯。
一種心態
Titan:因為我是一次把它讀完,所以這個模式就變得比較清晰一點,看起來你有一個 pattern,你一開始不太會去想一件事情的困難度,這個讓我想到,我不知道你有沒有看過一本科幻小說叫 Ender’s Game 戰爭遊戲,好像有拍成電影,我不爆雷,但是我想 vgod 知道我的意思,它其實故事的結局就有點像這樣,一開始都不知道這件事情是有多困難,但正是因為這種 mindset 讓你比較有機會一步一步往前進。
vgod:我覺得對,我有這種可以說是有勇無謀吧,我一開始碰到一件事情的時候,不會去想說它有多困難,或是這件事情 risk 有多大,我只會想說這件事情好像蠻有趣的,是一件值得做的事情,是一件我想做的事情,我有興趣的事情,我比較 care 這方面,所以當我想到這的時候,我通常就會開始去做了,至於會不會成功,這不是我主要的考量,我比較在意的第一是我能不能做到我想做的部分,我有興趣的部分可能只是其中一小部分,另外就是我能不能學到一些東西對我自己的成長,所以我很多事情都是在這種太清楚的狀況下就開始做了。
像我國中開始學寫程式,自己寫遊戲,或是到後來去比奧林匹亞,我其實並不知道這件事有多難,後來雖然我很幸運的成功了,你也可以說是我運氣好所以成功,可是很大一部分我覺得也是因為我沒有先被這個困難嚇跑,很多人在做事情的時候會先去想太多,做這件事情好像 risk 很大,或是說這件事情好像非常困難,很少人可以做得到,我是不是就不應該走這條路,我應該去走比較安全的路,大部分人在做選擇都是這樣子,走安全的路沒有不好,可是他也讓你直接捨棄掉一些可能成功的機會。
這其實有點矛盾,因為例如很多父母都很想要自己的小孩非常傑出,可以是第一名或是可以上台大,去最好的公司,可是你想要變成最好的這件事情,其實就跟你想要走安全的路,這件事有所抵觸,因為你如果選那個大多數人都走的路,你只會跟大多數人一樣而已,你是沒有辦法變得非常傑出的,你如果要變成 outlier,你一開始就必須要有變成 outlier 的準備,就要接受這些 outlier 他們選的路的這個 risk,他們選的路其實是相對風險比較大的,很可能可以大成功,可是也可能會失敗,什麼都沒有了,所以這個是一開始做選擇時候,你就必須要有這種心理準備,你才有辦法得到你想要變成 outlier 的結果。
Titan:vgod 前面在講他國中、高中不經意的提到這個風險的部分,剛剛有聽到說他上課其實沒有在上課,所以如果沒有辦法保送的話,後面可能狀況會比較麻煩,因為他其實在文章裡面有題道說因為國中、高中自學程式這件事情,跟父母親也有一些衝突,在準備升學的時候,我蠻好奇現在回過頭來看,旁邊人這樣看,包含你剛剛有提到這是滿驚險的,因為你完全是按照不知道未來會發生什麼事情,也沒有一個前人的經驗可以讓你完全參照的走,這種狀況底下你去做,包含之前有在部落格上面寫文章分享你兒子學習的這個過程,如果讓你再選一次,或是你也在當父母了,你要怎麼幫小孩去營造這個環境?或是讓你自己再選一次的話,你會怎麼做?
vgod:回頭看我會覺得當初做的決定是對的,我有 follow自己的,你知道 follow your heart,你要 follow 自己的 passion,當初我的確沒有想那麼多,甚至我那時候在跟父母爭執的時候,很大一部分就是我到底要在這件事上面花多少時間?我什麼時候要停損?如果我一直做下去,可是沒有得到好結果,那我是不是最壞是要回去考聯考才能上大學,所以我們那時候有設一個停損點,我跟父母講說在高二的時候,我要全力拚這個比賽的事情,如果我成功就可以保送上大學,所以你們不用擔心,如果我失敗了,我沒有靠這個保送上大學,那我高三就不再碰電腦,我就不寫程式,我就開始回頭專心準備聯考,走這個安全的路,所以我其實是有給自己留一個後路,設一個停損點,讓我知道如果真的走上那條路,可能結果不會太好,我可能上不了台大,如果光靠考試,我應該是上不了台大的,也不會有後來我去 MIT 這些事情,我那時候算是運氣很好,選了我想要走的路,而且真的成功走完了。
因為我兒子現在6歲,雖然現在選的路不用選這麼極端,我們最近在幫他找學校,其實也是有一樣選擇的困擾,我們可以選比較傳統的學校,比較好安全,比較用傳統的教學方法教你每一科的知識,可是也有不同的學校,例如我們現在選擇的學校,是比較讓小孩可以做他有興趣的東西,讓小孩 lead 他們想要學的過程,老師會設一個主題,可是他們可以用自己的方式來學習,按照自己的步調還有進度來學習,他們甚至不用被侷限在某一個科目裡,他們做一個 project 的時候可以往外延伸,把相關的知識全部都同時找進來,對他們來說知識是沒有界線的,沒有一個學科的分界,所以他們其實可以一次學很多東西,學科分界只是我們人為設的一些 boundary而已,這些知識是後來為了我們教學方便設下來的,可惜對小孩來說現在他可以同時學很多東西。
他覺得這樣很開心,他也很有興趣做這些事情,我們的方式就是讓他發覺他的興趣,我覺得發掘興趣是很重要的事情,你要先對一件事情有興趣,你才會真的投入很多心力,很認真的想要去做好這件事情,學好這件事情,沒有興趣的東西就只是被強迫的學,到最後你也只是很痛苦而已,我覺得很多人沒有意識到,你如果被強迫學了一件事情,之後你要被強迫再去做這個可能不喜歡的工作,你一輩子是不是要在這個你並不喜歡的選擇裡面,那你一輩子就這樣過完了,這樣其實是一件很可惜的事情。
到某個程度你一定要為自己做一些你自己喜歡的事情,做一些讓你開心的事情,人生的目的其實就是開心而已,每個人得到開心的方式不一樣,可是你如果一直接受一些別人給你的選擇,或是一些比較安全的選擇,你可能就會完全喪失掉這些機會,讓你可以實現理想、夢想的機會。
Titan:我發現你的這個態度,高中時候的態度,你好像有把它帶到台大去對不對。
vgod:對,我一直到現在,我的成長歷程就是一直用一樣的態度在做事情,到現在養小孩也是一樣,我覺得我也是用一樣的方法在養他。我在台灣也是一個不上課的人,對老師也有點不好意思,我在台大的時候幾乎沒有去上課,大學四年,我唯一有去全部上完的課,我記得只有兩個而已,一個是 Compiler,Compiler 老師教得非常好,他讓我覺得我去上課,是真的有學到東西,而且比我自己學得還要快,還要有效的。
Titan:很明確的指標。
vgod:對,很明確的指標。因為我已經很習慣自己學東西,習慣自己看書,自己找資料,所以我知道現在有個科目,我應該要怎麼學好,可以用自己的方法很快學好,我可以同時看很多不同的書,Course reference 講的東西自己練習,因為大部分的科目,如果是寫程式的,我很喜歡寫程式,所以對那些需要寫程式,寫 project 的科目,我平常自己寫就好,一邊學一邊寫,這是我的學習方式。
我需要比較 hands on 我才有辦法學得好,我不是看書就可以學得好的人,看書對我來說,這個 input 沒有辦法留在我的腦袋裡,我看完以後很快就忘記了。對我有效的學習方式是同時看很多書,看不同的作者怎麼講同一件事情,你就可以用不同角度來學這個東西,學了以後一定要馬上自己動手做出來,去做 project 或即使是做練習題也好,練習過,做完了以後,我才真的會學會這件事情。
那時候我在大學時期也是,幾乎所有科目都是這樣學,所以我真的有去上的科目只有 Compiler,另外一個是軟體工程 Software engineering,軟體工程一直是我很有興趣的領域,所以那時候我有去上課,這個課其實不是在資訊系開的,是在台大土木系開的,有點奇怪,台大土木系有一個老師,他其實比較像是做電腦模擬的土木工程,他也接觸蠻多軟體工程的東西,他開一個軟體工程的課,我覺得蠻有趣的,因為資訊系反而沒有人開這個課,所以我就跑去那邊修,我也覺得有學到蠻多東西的。除此之外,其他課我都沒有去上,我就是自己寫作業,做 project,去考期末考、期中考而已。
Titan:我不知道要不要在這時候講說好孩子不要學,但秉持著剛剛 vgod 講的東西,因為你的經驗,我們之前有另外一位來賓詹雨安,Heptabase 的創辦人,他現在正在 YC 加速器裡面,努力他的新創公司,打造他的產品,類似的經驗,他也是按照自己的步調去學習,他後來得到的結論跟你比較不一樣,他就是決定直接先休學,也是一個很獨特的經歷,如果有聽眾還沒有聽過這一集的話,歡迎大家去我們的 Show Notes 找出來聽。(星箭廣播 127 集——他想改變 Internet,第一步是打造全新的筆記軟體(ft. 詹雨安))
想讓電腦自己寫程式:在MIT攻讀博士與「Sikuli」專案
vgod:後來我在台大畢業以後,我在台灣唸了研究所,碩士班,那時候留在台灣主要的原因是我還不知道我要做什麼,我不知道未來想要留在台灣工作,或者是出國繼續念書,所以那時候算是延遲我這個決定,留在台灣念研究所。
那時候我剛好碰到一位蠻好的老師,許永真老師,他是在台大做 AI 的教授,我跟他蠻契合的,他也非常支持他的學生,那時候在做研究也是讓我們可以自己選題目,這個並不是一個常態,其實在台大你去找老師做研究,有些老師是會直接把題目給你的,有一些他事先想好的題目,有的老師會去外面接一些 case,這個 case 可能是別的公司來的,或是學術機構來的都有可能,那他們會把這些 case 交給學生去做,讓學生把一些已經有想法的東西做出來而已。
那時候我比較不想要做這樣子的研究,所以我找的老師是讓我可以非常有自主性,我可以決定我想做什麼問題,自己把它的 project 做出來寫成論文,我在碩士班很幸運找到這樣的老師,然後這個老師給我很大的空間做研究,那時開始我慢慢發現做研究是一件挺有趣的事情,我可以解決一些沒有其他人想過的事情。這件事情影響我蠻深的,讓我在碩士班完以後決定應該要繼續念博士,因為念博士就是把這件事情鑽的更深,可以有機會找自己的研究題目,然後在這個題目裡面做一些沒有人想過的研究,這對我來說是一件蠻有吸引力的事情。
那時候碩士班完,我就決定我要申請出國念書,我申請兩個學校一個是 MIT,就是我要去唸博士班,另外一個我申請是 EMU 的碩士班,不是做研究的,如果要做研究,你一定要念博士班,碩士班比較像是念完就去工作,那時候我會選碩士班的原因,其實是因為裡面有個老師在做軟體工程這方面的研究,我對軟體工程一直都很有興趣,我對那個老師就是特別有興趣,所以我就決定他即使是只有碩士班,我也要申請。
後來我幸運的是上了 MIT,就決定去 MIT 開始做研究。到 MIT以後,我花了很多時間在找題目這件事情,找題目是一件比想像中難的事情,因為你可以做的問題實在太多了,每個老師雖然有一個領域,可是這個領域也非常大,像那時候我們老師做的是 HCI(Human – Computer Interaction),就是人機互動,它也有做一些軟體工程的東西,這是我找他的主要原因,他的領域剛好就是 HCI 跟軟體工程的交界,例如:你如何幫助軟體工程師,或程式設計師更容易寫程式,讓他們寫程式的時候變得更簡單,甚至讓電腦可以自己寫大部分的程式,像現在已經有做到蠻好,像是 GitHub 有一個東西叫做 Copilot, 那個 Copilot 其實已經非常厲害了。
現在AI技術跟十幾年前已經很不一樣了,有這些技術以後,你寫程式可以只寫函數的外殼,你只要把名字寫完,他可以幫你把內容填好大部分,這在以前是非常難以想像的,其實也是我以前在做研究的一個目標之一,那時候很多人在做這種讓電腦自己寫程式的研究,最終目的都是要達到這樣子,那時候我就開始跟我在 MIT 的老師往這方面走。
一陣子以後,那時候想到一個 idea,這個後來我們做了一個 project 叫做 Sikuli,Sikuli 這個 idea 是讓我們在寫程式的時候,可以不用透過電腦的這些 API,API 就是每個軟體系統,像是Windows 或是 Mac 會提供一些已經規定好的函式給你,這些函式規定好你要怎麼跟電腦溝通,讓電腦做特定的事情,例如:你可以打開一個程式,然後或者是執行這個程式以後,你要對這個程式下出什麼指令,按它其中一個 button 之類的。
這種寫成的方法並不是很直覺,因為你在寫程式的時候,你必須要上網找很多文件,例如:你要寫一個 Mac 程式,你要去 Mac 的系統讀它的手冊,知道它有什麼 API,然後你才能知道要怎麼讓電腦自動的做一些事情,這些 API 是需要一些知識累積的,或是大量的 Google 學會,那時候我就在想有沒有什麼更簡單的方法可以做這件事情,因為人在操作電腦的時候,其實你不需要去學什麼 API,打開一個程式它就有一個視窗介面,這視窗介面上有很明確的一些 menu,然後上面每個 menu 都有 item 跟你講這個 menu 可以開一個新檔案,或是你要存檔,或是你要打開一個新的文件,在 UI 上有很多 button,按下去你就會很明確知道發生什麼事情。
為什麼電腦不能像人一樣,只要看著這個電腦的 UI 就可以操作它?所以那時候我就是用這個想法開始去想,然後想出了 Sikuli,這個概念就是改變我們寫程式的方法,變成我只要在電腦上先截一個圖,例如:我現在想要讓電腦去自動去按一個 button,我就把這個 button 截一個 screenshot 下來,然後把這個 screenshot 放到我的程式裡面,所以我的程式裡面,我只要寫 click 這個 screenshot 放這個 button 圖進去,電腦就可以照著執行了,它就會去畫面上找到這個 button 所在的位置,然後幫你送出一個 click 的指令,模擬人類如何使用電腦,它的輸入基本上完全只有螢幕的 pixel,不需要透過電腦底層的 API 跟電腦溝通,所以它可以跑在Windows 上,可以跑在 Mac 上,任何平台都可以,甚至你在 Windows、Mac 上面跑 Android、 iOS 模擬器,甚至式 remote desktop 它都可以操作,因為你只要在螢幕上可以看得到,你就可以操作它。
那個時候 Sikuli 變成我在 MIT 主要研究的論文,那時候我寫幾篇論文都是跟這個主題有相關的,一直到最後,我還把這個 project 變成一個 open-source 的 project,讓全世界的人可以繼續貢獻它,後來才變成一個 community,有很多人主動加入,幫忙寫文件,maintenance 這個專案,到後來我在 MIT 畢業以後,沒有繼續做這個專案了,然後而是這個 open-source 的 community 繼續的傳播下去。
事後看Sikuli專案:不是真的團隊合作
Titan:這是你第一次花比較多時間去投入一個 open-source 的專案嗎?
vgod:算是,我以前在大學的時侯,有零星的參與過一些 open-source 的專案,比較小的,像是我以前參加過一個叫 OpenVanilla,一個輸入法的專案。
Titan:香草輸入法嗎?
vgod:對,香草輸入法。我在那邊其實做了一些輸入法的東西,那時候我用的輸入法叫行列輸入法,非常少人用,所以我就自己寫了一個碼,讓我可以在 Mac 上面使用這個輸入法,可是 Sikuli 算是我真正第一個自己開起的一個比較大型的專案。
那時候我其實不太知道要做些什麼事情,我跟另外一個在 MIT 的同學一起合作做這個 project,我們的專長不太一樣,他的專長是在做電腦視覺方面的,所以像是辨識畫面上有什麼都東西,或是把畫面上文字的 pixel 轉成真的文字,這些事情上面他是比較擅長的,所以那時候我們的分工其實很簡單,他可以做電腦視覺方面的所有東西,那我就是寫剩下來的程式,例如:做出這個程式語言的語法,把這個截圖可以跟程式語言融合在一起,還有這個 UI,程式語言的編輯器,要讓電腦可以真正的去執行這個程式,然後讓這些程式可以 run 在不同的平台上。
我們一開始只有兩個人,後來發現我們這樣沒有真的在合作,這個合作比較像是我把這個 project outsource 一小部分給他,然後我就不管他在裡面幹嘛了,他也沒辦法真的參與到我這邊在做的事情,我們沒有很好的平凡互動,或是溝通找出我們可以互相幫忙的地方,讓這個 idea 變更大、更好。
Titan:就變得有點像是生產線的這種感覺。
vgod:對,沒錯,我們切的太開,其實我在學校時候大部分的 project 都是這樣做的,學生的時候其實不太會在意怎麼合作,大家就是找個地方把它切開來,你做這個,我做那個。
Titan:聽眾應該都蠻有感的。
vgod:對,沒錯。在學校的時候其實不會教你如何跟人家合作做一個軟體,或是一個大型的軟體,所以合作這件事情就是讓學生自己自由發揮,到最後就會變成很簡單的切開來,一人做一半這樣子。
Titan:我覺得這個經驗應該你現在回過頭來看,應該會特別有感觸,可能比你當時感觸更深很多。
vgod:對,我在後來真的變成軟體工程以後,才真的學到這種大規模的軟體是怎麼開發,要怎麼跟很多人一起合作,軟體開發不是說把這個問題拿來切幾刀,一個人做一部分就可以解決的事情,這個是一個非常長的過程。
AI
Titan:等一下要請 vgod 來談一下他在新的系列〈軟體工程師的修煉與成長〉,一開始就在談的這個部分,把程式設計師跟軟體工程這兩件事情交代蠻清楚的,但在這之前我還是想要再停留在 Sikuli 一下,包含你高中時期,那時候去做了一個科展,這個部分請大家去讀〈程式設計之道〉的文章,你那時候在思考的問題是怎麼讓電腦自己去寫程式,後來你在 MIT 你在做 Sikuli 專案是希望把寫程式這件事情變得再更直覺化,再簡化一點,讓一般人去用程式來完成他們想要做的事情,把它變得比較簡單。
我想你背後的思考應該是學會寫程式跟要完成你想要做的事情,你是把它分開,看起來大家比較重視的應該還是這個結果能不能完成一個工作,寫程式才有它的意義在裡面,你回過來看,包含你剛剛有提到 GitHub 的 Copilot,還有像 OpenAI 做的 GPT-3,你會覺得這個進步是真的有在前進的,這對你心理的衝擊是什麼樣的?
vgod:我其實還蠻高興看到這樣的發展,因為我在高中的時候,做這個科展很大的夢想就是讓電腦可以自己寫程式,我想要電腦做什麼事情,電腦就會自己去 figure out 這些程式要怎
寫出來,現在 AI 可以變得這麼厲害,是因為前幾年的 Deep Learning 出來以後,大家發現 Deep Learning 可以很容易的收集大量資料,然後從裡面學到電腦應該要怎麼利用這些資料來做出正確的判斷,當時 AI 的做法全部都是用人去寫出一些 rule,條列式的跟電腦說,你什麼狀況要做什麼事情,這樣的東西其實完全不 ok,因為現實世界太複雜了,總是有各種千奇百怪的例外情況,沒有人可以舉出所有的 case。
所以在這種情況下,當時的 AI 其實只是在一個寒冬期吧,當時其實不太有人 care,大家已經覺得 AI 是一個死掉的領域了,電腦沒有辦法真的有什麼智慧,可是直到 Deep Learning 出現以後,完全改變了這一切,我們突然知道要怎麼餵給電腦大量資料,就可以從這些資料裡面做出正確的判斷,這是一件非常 powerful 的事情,像現在 Copilot 這些 tool 就是利用這些技術,讓當初想讓電腦自己產生程式的這個夢變得更接近了。
當初如果有這個技術的話,我應該也會用類似技術開始做類似的專案,像 Copilot 這種東西,如果在我高中時候,大學的時候出來,我應該就會把這個東西結合在一起,這其實是一個很直覺的事情,大家都會想同時在這個領域做非常多,Deep Learning 一出來,大家就會發現 Deep Learning 這麼厲害,我們要用它來讓電腦寫程式,讓電腦自己寫程式算是 AI 領域的一個聖杯之一,所以很多人其實都在想這些事情,只是沒有好的工具,Deep Learning 改變了這一切。
我也很期待接下來還可以有什麼樣的發展,因為實際上它雖然已經可以做到不錯,如果你去看最新 DeepMind,它們有一個 research 可以讓電腦自動的產生出之前講程式比賽的程式, DeepMind 自動解題的機器,已經可以做到跟 average 的這些選手差不多好了,因為那些程式比賽都有固定的輸入和輸出,所以它知道正確答案是什麼,它就是把這個題目的問題餵給它們程式自動的 solver,這個程式的 solver 拿這個問題的描述,就是人類的語言把它轉成程式,在這個比賽的網站,丟一些數進去看它跑出來是不是對的答案,就跟人去 submit 答案是一樣的。
DeepMind 其實可以做到跟 average 的這些選手差不多好了,這是一件非常驚人的事情,這個東西再發展下去,再幾年我覺得我們寫程式的方法會有很大的改變,以後我們寫程式就不需要每一行都自己寫,因為自己也是寫程式的第一個門檻,你要非常了解要怎麼讓電腦一步一步做你想做的事情,這每一步都要講得非常清楚,一點錯誤都不能有,你打錯一個字程式可能就 broke 了,DeepMind 的這種自動產生程式的程式,剛好可以補足這一部分,他可以讓你描述一個比較 high levels 的問題,然後你想要解決什麼問題,例如:你只要寫出函式的名字,然後跟它講你的 input 要什麼樣子,output 要什麼樣子,他就自動幫你把程式內容寫完了,這樣子可以讓很多程式設計師節省很多時間,不用再寫這些比較 low levels 的程式。
意思不是程式設計師就會沒有工作,我們還是有很多工作要做,重點不在於寫這些程式本身,而是在 figure out 我們到底要做什麼程式,我們想要寫程式來達到什麼樣的目的,這其實才是軟體公司裡面軟體工程師大部分在想的問題,把你有的想法寫成程式這件事情是需要人去做沒錯,可是這其實在軟體公司裡面,大部分都是剛畢業比較 junior 的人在做的事情,你到 senior 以上,其實就不太會親自去寫程式,寫程式變成是一個 optional 的東西,你可以自己寫,可是你也可以交給別人寫,因為別人寫其實也差不了多少。
Titan:這樣聽起來對 junior 的工程師還是有點危險啦,之前 AlphaGo 在下圍棋上面的突破,還有更之前大家早就已經算解決的問題,下西洋棋,大概用到象棋或其他大家想像的到的這種牌面上遊戲,我記得也有人在開發打麻將的 AI 等等,其實有點像是對於從事這個領域的人類來說,提供的一個問題是那現在如果這些事情電腦可以做的話,那我們從事這些事情的意義是什麼?或者是怎麼樣去改變這個運動,或者是達到下一個境界,有點像是我們先把人類可以學完的東西讓電腦幫我們處理完,接下來可以到下一個階段,我覺得人工智慧研究的突破很多領域都有遇到這樣的問題,比如說醫療、法律或者是記者,我們做文字工作的人,都有開始面臨相對應的問題。頂多可以說中文可能門檻高一點,研究的人少一點,所以進展可能會稍微慢一點,但我覺得面臨的問題的類型跟方向是很類似的,不過這是另外一個大的問題,改天有機會再繼續討論。
程式設計 vs. 軟體工程
Titan:接下來 vgod 來跟大家講他後來開始當全職軟體工程師之後,並不是大家想像的一帆風順,MIT 然後博士進到軟體公司之後,開始一路平步青雲,他其實中間有遇到一些掙扎的地方,先從程式設計跟軟體工程,這兩個關鍵字先請他跟大家解釋一下,我想當然是有必要,讓大家瞭解一下差別是什麼,但是我想即便是對工程師本身,就算是 vgod 他都要花時間去了解、去體會當中的差異,我覺得請他來講這件事情是很有價值的。
vgod:程式設計跟軟體工程以前我其實並不知道這兩個概念到底有什不同,對我來說程式設計師跟軟體工程師,這是兩個可以互換的名詞而已,很多人開始工作以後說他們是程式設計師,並不會特別去強調軟體工程這個部分,一直到我真的後來在矽谷比較大規模的軟體公司工作以後,才發現這兩個概念其實非常不一樣,程式設計比較像是一個個人的活動,一個人達到一個問題,他要想說怎麼用寫程式來解決這個問題,我們在學校裡面學的其實大部分也是這件事情,像我之前參加資訊的比賽,我們都有個問題,這個問題是交給我們的,我們拿到問題要去想如何解決這個問題,把程式寫出來,我們著重的點是這個程式要寫得快,程式也要跑得快,程式要能夠輸出正確的答案,就是這樣子而已。
對於當時在學生時期的我,這就是軟體工程,軟體工程就是我可以把程式寫得很好,然後可以讓我的程式處理很大量的資料,可以讓我的程式很容易被其他人維護,被自己維護,被其他人維護這樣,這就是軟體工程。真的到了矽谷公司開始工作以後發現,真的軟體工程比這個複雜很多,最主要差別是軟體工程在一個大型公司裡面,它是一個非常長期的活動,我們在學生時代的時候,我們寫的程式他的 life cycle 很短,期末專案好了,可能就是老師給我們一個題目以後開始做,一個月以後做完交出去,我們就再也不會打開這個程式了,這個程式就被忘在我們的硬碟裡,也沒有必要去維護他,因為這程式就是考完試就結束了。
可是在軟體公司工作很不一樣,因為軟體公司裡面的程式是需要花好幾年的時間去維護的,這個程式被寫出來以後,上線了以後,它就有真實的顧客在使用它,你就不能隨便把它拿下線,你甚至不能把它停掉,停掉會造成公司非常大的損失,所以你必須要在這些程式已經在上線的情況下繼續維護它,繼續增加新的功能,繼續修它的 bug,然後公司一個人不夠所以有很多人一起做這件事情,我對這件事的比喻,這是個團隊接力的馬拉松,你從這個公司開始把這個軟體開發出來,上線以後,需要花好幾年的時間持續跟這個團隊一起繼續開發,加新的功能一直維護它,修掉 bug,這件事情是要不斷持續以年為時間的單位在做的。
在這個情況下,我們寫程式的方法就變得很不一樣,因為在以前專注的是要讓我的程式跑得很快,所以越快越好,後來我才理解到在一個大型團隊裡工作,讓程式跑得快已經不是最重要的事情了,很多時候一個比較簡單易懂的程式更重要,你的程式寫完以後有很多人要看,不是只有你自己而已,程式的易讀性就變得非常重要,我們以前在比賽的時候,都會為了程式寫得快、跑得快,犧牲掉很多易讀性,可能會把程式寫得很醜,一個大函式裡面,所有的人的幾百行都擠在裡面,變數的命名我們也不太 care,甚至有時候會用一些很噁心的方法去寫程式,把程式寫得很短,故意寫的很漂亮,它可以很精巧的做到你想做的事情,可是你寫完以後沒有人看得懂它在做什麼,這種程式其實很多,以前我們還是學生很喜歡做這種事情。
當你真的到公司就會發現這是一件千萬不能做的事情,這是一個禁忌,你寫出來的程式如果沒有人看得懂,是一件非常不 ok 的事情,這個讓我的心態開始改變,在軟體公司工作你必須要能夠跟團隊配合,即使一開始是 junior 的工程師,你要知道你寫出的程式怎麼樣才可以讓其他人讀得懂,必須要 follow 一定的規範,在公司裡,每間公司都會有一些程式的 coding style 的規範,確保大家寫出來的程式長得樣子都一樣,所以很容易讀,這在軟體工程就變成是一個很必要的事情。
一般在學校我們不太會接觸到這一塊,甚至老師可能也不知道,因為老師沒有在軟體公司裡工作過,大學教授就是在學生時期一樣學會寫程式,念個博士就回去學校當教授,也沒有真的寫過大型的軟體,他們不知道要怎麼教學生這件事情,這可能也不是他們 care 的事情,在大學裡面,教授比較 care 學術方面的突破,你有沒有一個新的想法在這個領域,有一些沒有人想過的創新。可是軟體工程,畢竟它是一個工程,你必須要有一個很嚴謹、系統化的方法可以把你要做的事情 deliver 出來,這是一個工程的必要條件,你必須要能夠預估做一件事情要多久,要多少人,還有他的複雜度有多高,困難度有多少,你必須要做這些預估,你才有辦法跟團隊合作。
軟體公司裡的mentorship
Titan:我們剛剛聽完 vgod 初步跟大家講程式設計跟軟體工程的差異,以及他瞭解到軟體工程有很大一部分是一個軟體設計師,你必須要跟其他很多跟你一樣都是軟體設計師的人,甚至是不同職務的人一起工作,去完成這個軟體工程,我想問一下你在學習或是理解這個軟體工程的這個過程當中,你可以跟我們舉幾個例子,是你覺得跟你當年有相同狀況的人,他不需要注意的事情。
vgod:我覺得對於一個初階的工程師來說,剛進去一個公司,第一件事就是要學會怎麼navigate 這個程式碼,必須要找到對的地方嵌入,然後在那個地方改你的程式,說起來其實挺難的,因為你對於上一行的程式裡面,你要知道你需要改的在哪裡,是一件非常難的事情,這個複雜度太高了。
像 Google 之前就有公佈他們程式碼的數量,在 2015 的時候,它們就有 21 行的程式碼,是一個非常可怕的數字,他們有兩萬多的工程師,現在有超過十萬人了,十幾年的時間寫下來的程式碼,即使在 Google 裡面待最久、最資深的人也絕對不可能可以理解,所有的程式碼在做什麼,通常一般的公司都會有一個 mentoring 的機制,每個新加入的人會配一個 mentor,那這個 mentor 會帶著這個新人熟悉環境、工具還有 code base,他會給新人一些比較簡單的任務、工作,可能只是新加一個功能,或是對 UI 來說,改改一個 UI 的 button,甚至簡單到改顏色之類的,只是一個非常簡單的 task,這些工作可以讓你比較熟悉你的工具,你必須要能夠熟悉你用的工具以後,你要知道怎麼 check out 整個公司的程式庫,你要知道怎麼變異它,run 一些自動的測試,run 完以後你才能 submit,我們叫一個 diff ,叫做 Code review ,你要做 Code review 的時候,有一些規範你需要 follow。
前面有提過公司有規定的 Coding style,你寫的程式是要符合那個 Coding style 的,你符合Coding style 別人才容易讀,所以 mentor 會教你這些事情,讓你比較快可以熟悉狀況,比較知道現在你需要負責的範圍大概會碰到哪些程式的檔案,你一開始就可以從那些地方下手,你就比較知道以後要開始自己獨立運作的時候,你要怎麼從哪裡開始往外展開去學更多東西,去知道說跟你相鄰的系統,它們是怎麼運作的,那這些都是 mentor 一開始會教你的。
在我們公司其實 mentor 應該是會幫你六個禮拜,這六個禮拜會很密集的,甚至它就坐在你旁邊,然後跟你一起工作,帶你一步一步的做,跟你說現在要做什麼事情,可以去哪裡找答案,應該要用內部的哪一個工具來做這些事情,例如:我剛加入的時候,我完全沒有想到我們公司有非常多的內部工具,這些內部工具都是我們公司自己開發的,自然你在外面也不會先學過這些東西,可能進去你就會發現,也不是每個工具都有文件,很多文件其實就是那個程式碼本身也必須要去讀那個工具的程式碼,才知道要怎麼用那個東西,文件沒有做好的話,其實要學這個東西,門檻又變得更高了。所以那時候 mentor 很大的幫助就是在幫我學這些事情,讓我知道我要去哪裡找答案,去哪裡找我要的工具,學會這些工具到底要怎麼使用。
現在的軟體公司,像是 Google、Facebook,很多人都會覺得他們做的系統好像看起來不怎麼樣,比如 Google 看起來就是文字框打進去以後,它就給你一些網頁連結,連結到其他人的網頁,那些網頁還不是 Google 自己 host 的,表面上看起來很簡單,可是背後是需要非常多人一起合作才能完成這樣的系統,對於不是軟體工程師來講,其實很難理解為什麼 Google 要 hires 十萬個工程師在做這件事情,Google 雖然已經有很多產品,可是你聽到十萬個人,就覺得很奇怪,Google 產品也沒那麼多,你講得出來的 Google Search、Gmail、YouTube、Android、Google Map、Google Docs 比較大就這幾個吧,頂多幾十個產品好了,十萬個人到底要做什麼?
在學生時期,很難看到這背後的複雜度,因為你不在公司裡面的話,你看到永遠都只是公司提供給你的介面,這個界面介面其實只是最上面的薄薄一層,有點像那個冰山,下面其實有一個非常大的金字塔,在下面支撐這個介面,以 Google 來說好了,搜尋引擎你如果要讓一個這樣看起來很簡單的介面可以運作的這麼好,運作這麼快,打入一個搜尋的文字就可以在零點幾秒,大概是一百個 milliseconds 以內,就 show 出這麼多文件,在背後事先就要做很多工作,像網路的爬蟲,把世界上所有的網頁全部都爬進來,存到它的系統裡面,必須要把這些每個網頁,事先都先 scan 過一次,把它分割成比較小的一個一個 token,在把 token 存在 index 裡面。
如果你只是一個學生在做一個專案,做的東西可能都很小,你如果只是要爬,例如:1000 個文章,10000 個文章,這些東西都可以存在一台電腦上,可是如果今天 Google 面對的是全世界的網頁,這些 scale 是幾十億,幾百億個文章,一台電腦是完全沒辦法裝的下,所以當你規模變大的時候,你就開始碰到一些新的問題,這麼多文章你要存在哪裡?你就要開始開發一個很大的儲存系統,必須要利用很多台電腦,把這些不同電腦,幾百台,幾千台電腦,讓他們接在一起,可以同時儲存這些文章,那你解決儲存以後,也要解決運算的問題,你必須要能夠有一個大的運算系統,你不能只用一台電腦去讀這些文章,然後去分割文章,或是把它轉成 token ,你要很多電腦同時做這樣的事情。
所以像 Google 這類大型的軟體公司,他們有很大部分的工程師在背後做的是這些,我們叫基礎建設,例如:建一個很大型的運算系統,甚至大型的網路系統,一旦東西開始變大以後,所有的問題都會變難,很多是成指數成長的,以現在來說,很多公司可以比較簡單去解決這些問題,是因為像 Google、Facebook 這些公司已經事先把這些問題做掉了,或是 AWS,現在的雲端業者像 AWS、GCP,他們已經把這些系統變成一個產品讓你用,infrastructure 的 service,所以你可以直接去買到像 S3 這樣子的平台,你可以把你的所有的檔案全部都 dump 到 S3,你就不用管背後到底有幾台電腦在儲存這些東西。
可是如果你仔細想想當初 Google 或是 AWS 他們自己在做這些平台的時候,他們當時是沒有S3 的,所以他們必須要自己內部先做出這些基礎建設,這每一個的系統像 S3,後面也是幾十個,幾百個工程師才能做出來的,那當你的公司還小的時候,現在這個時代,有很多cloud provider,你可以直接用那個 cloud provider 比較簡單做好這件事情,可是你的公司一直 scale up,Facebook、Google 這種規模的話,你也不會用 cloud provider,因為他們太貴了,你必須要開始打造自己的基礎建設,所以這些基礎建設是不是需要幾百、幾千個工程師來打造的,像我們公司也是規模這麼大的公司,所以我們後面的基礎建設團隊也非常大,有內部的資料儲存系統、內部的測試系統,還有內部我們在 deploy 自己的 code,有自己的 deploy 系統,基本上你想到的所有事情,我們內部其實都有一個不同的版本,來符合我們的需求讓我們自己開發的。
那這個算是一個成長的必要之二吧,因為當初我們開始做這些東西的時候,沒有這些 cloud provider,他們提供的東西沒有辦法滿足我們的需求,或是他們的東西簡單說太貴了,所以我們就開始自己做,到最後就變的越來越多,那這個東西就會讓公司需要 hire 的工程師非常多,然後我們需要處理的問題也非常龐大,因為每個系統必須都要有人去維護它,然後一直保持它增加新的功能,讓它可以穩定的運作,這些東西就會變成額外的複雜度,複雜 dependencies ,隨著人數的指數平方一直成長,這就變成是一件很恐怖的事情,這也是外面比較看不到的事情,因為大家只會看到介面,介面永遠都很簡單的,因為那是要給使用者用的,可是在背後,除了一般人知道的前端、後端以外,後面的這些基礎建設其實都是非常龐大,而且又複雜的。
Titan:前端跟後端這個分頁,我想我們有蠻多聽眾應該對這東西有基礎的概念,我那時候在看〈軟體工程師的修煉與成長〉第四篇 Products vs Infrastructure 這篇,他有一個我自己沒有看過的劃分,前端跟後端,然後再利用這個前端跟後端的結構,對應工程師團隊內部的這種影響,那這個話題我想我們在第二集會再度的提到。
給mentee的建議
Titan:我知道你在寫這系列文章之前,你已經有寫過一篇文章在講 mentoring,我覺得可以先從初期,當你還是一個新進的工程師,這個 mentoring 對你的幫助,除了剛前面講到的,協助你上手公司工具,了解一些軟體工程在運作的規則之外,其他方面對你的幫助是什麼?那篇文章有一部分是說你尋找的 mentoring 跟你自己本身在公司,不管是公司的職級或者是職涯發展的階段,是要越接近越好?還是對方比較資深來指導你這樣一個新進的人,哪一個比較好?
vgod: Mentoring 這件情,有些人會覺得你要找 mentor 應該要找一些很資深的人,或是他們好像比較資深的人看的東西比較多,所以他的經驗比較多,他可能就可以比較好的教你更多事情,在我的經驗裡面,越資深的人,其實他們離新手的階段就越遠,這代表如果你現在是一個初階工程師,你是一個剛加入的新手,很多你遇到的問題,他們可能是十年前、十五年前遇到的,他們其實早就忘記了,隨著你職涯成長,你升上不同的職級以後,做的工作是完全不同的。
例如:你在初階工程師的時候,你要花很多時間寫程式,你到 senior 以後,你可能要花比較多時間在設計程式,寫一些 design doc,你必須要設計一些系統要如何運作,寫的部分會減少一點,可是如果你再往上升,變成 staff engineer、principal engineer 的時候,你幾乎就不寫程式,做的事情比較是 figure out 到底要讓團隊做什麼事情,當你不寫程式的時候,很多初階工程師遇到的問題都是一些比較 tactical 的問題,例如:這個程式遇到一個 bug,我應該要怎麼修它,我應該要用什麼 library,我要呼叫什麼 API 去做這件事,或是我現在遇到一個設計的選擇,如果是太 tactical 的部分,對於很 senior 的人來說,已經離他太遠了,他平常其實不太需要想這些事情。
所以找 mentor 的時候,找到對的 level 的人也是很重要,你如果找到太 senior 的人,他可以給你一些很 high level 的建議,可是他的建議不見得對你有用,因為你在新手遇到的時候,很多問題都是比較實作方面的問題,比較 tacnical 的問題,比較像是 hard skill,你必須先有這個 hard skill,過了這些門檻以後,你才有辦法去做比較 high level 的事情,所以我覺得最好的是找離你只有一兩年差距的,他已經做過你現在做的事情,他又稍微 senior 一點點,你現在是初階的工程師,我覺得差一兩年差距是最好的,如果再差多一點三四年的話,他們可能就開始有點模糊了,人的記憶是沒有辦法保存那麼久的,這也是軟體工程另外一個很難的點,雖然你說大家都是軟體工程師,每個人的專業,還有他熟悉的 scope 還是差很多的。
我今天在公司裡的假設我是做前端,你沒有辦法把我突然抓去寫後端的程式,或是做基礎建設的程式,這是完全不一樣的事情,甚至是完全沒有辦法換的,有的人就是待在前端,他就是只能一直做前端,做久了以後,你要叫他換,他可能第一是不想換,第二是學習的門檻太高了。
給 mentor 的建議
Titan:我們剛剛講的有點像是站在 mentee 的角度來看,所謂 mentoring 這件事情,我想你已經開始做了很多年 mentor 的角色,你有沒有什麼建議給我們的聽眾,如果他現在是正邁向這種資深工程師的階段,開始要當別人的 mentor,有沒有什麼建議是可以跟大家分享?
vgod:當 mentor 我覺得是在初階升上可能中階就是 L4 到 senior 這個中間一定要經過的一步,我們說資深工程師跟初階最大差別其實就在於你有沒有 leadership,你有沒有辦法帶領一個專案,不用很大,只要有兩三個人一起做的這種專案就可以了,可是你要有 leadership 之前,你必須要先能夠帶一個人,所以 mentorship 算是最初階的 leadership 吧。
通常在 L4 的時候,你就必須要開始帶新人,帶新人這件事情,對自己也有很大好處,有些人其實是會不想做這件事情,他會覺得好像這不是他本分的工作,可是這其實可以讓 mentor 自己成長很多。第一個是在一個團隊裡面,你如果變成一個 bottleneck,如果你是唯一知道如何做一件事的一個人,這其實不是一件好事,有些人會覺得這是他的技術的地雷吧,他好像有一個護城河,只有他會做這件事情,所以公司沒辦法開除他,可是其實並不是這樣。
以公司的角度來講,這對公司或是對團隊來講,都不是一件健康的事情,通常團隊裡面的人都會想要提升團隊的 Bus factor,這個 Bus factor 就是說今天一個團隊出去,假設有個人突然就被公車撞死了,怕有沒有人可以來接替他,Bus factor 是表示這個東西只有一個人懂,這是很糟的情況,所以一個健康的團隊都會盡量想要有至少大於一以上,可能兩個人、三個人都是懂同一塊東西這樣才好。
mentor 就是很重要的一步,你必須要能夠把你會的東西教給別人,你可以 scale 這個 team,你如果可以 scale 這個 team,你自己不是 bottleneck,其實可以把自己 free 出來,讓自己去做別的事情,你沒有必要一直做同一件事情,在同個 team 裡面成長,其實有一個很重要部分,你不能一直待在自己的一個小的 silo 裡面不跟人家合作,或是不去學新的東西,那你永遠就只能做自己的事情,對團隊的貢獻就會被限制在這個 silo 裡面,所以擴展自己的舒適圈的方式,其實很重要,就是 mentor 別人,讓別人學會你現在會的東西,把你會的東西交給他,他就可以做這些東西,你自己就可以跑去做別的事情。
這我覺得是非常重要的一步,透過這一點,即使在一個團隊裡面,你可以學不同專業、學不同系統,甚至換不同的領域,有的團隊也會有一些差別很大的系統,所以這是一個很好的方式可以讓自己切換熟悉的領域。
Titan:把自己的工作或把自己的 capacity 空下來可以做別的事情,這背後有隱含一個意思,也許你可以升職,可以升級,那這件事情,我們在第二集再跟大家討論。
先稍微回顧一下今天這一集,一開始我們先請 vgod 算是回顧一下他自己過去在寫〈追求神乎其技的程式設計之道〉這一系列的文章,順便讓一些我們比較不認識 vgod 的聽眾先了解一下他學習寫程式從自學,基本上來說就是自學,一路到高中參加資訊奧林匹亞,然後以及到台大,MIT 讀博士繼續研究電腦科學,然後到矽谷的軟體公司去擔任軟體工程師,他前幾年先學到程式設計跟軟體工程的差別,以及你還是 junior 工程師的時候,你在尋找 mentor 的時候要注意哪些事情,以及反過來講邁入資深的這個階段要怎麼教別人,教會別人意義是什麼?
我們第二集主要接下來要談的是 vgod 在他現在正在連載的這系列文章 〈軟體工程師的修練與成長〉裡面有談到幾個重要的議題,比如有一篇標題,我看那個一定是最紅,點閱率最高的文章 — 1:1 該談什麼才能讓職涯起飛?我想這個部分大家應該會很有興趣。
另外還有一個我覺得也很重要,但是在台灣比較少見,我覺得很值得 vgod 來跟大家分享,大型的軟體公司裡面,我們講所謂的 IC(Individual Contributor)跟 EM(Engineer Manager),如果大家對這個詞還有一點印象的話,其實我們 Star Rocket Blog上面,之前 Julie 有寫一篇文章在專門跟大家介紹 Individual Contributor,職涯在美國的軟體科技公司裡面,是怎樣的一個職務以及它的發展性、它的特點,跟我們平常認為的升職就必須要擔任管理職的這種概念有什麼差異。(Individual Contributor:工程師不當帶人主管的職涯選擇 | Star Rocket Blog)
或者是大家也可以去聽我們之前訪問過在 Robinhood 擔任 EM(Engineer Manager)的 Zero Cho,主要在談他等於是從一個主要工作寫程式的軟體工程師角色,平行的轉換到 EM,他要做的工作是什麼,當時他大概是剛轉職半年,大家可以去聽聽看他那個階段的想法。(星箭廣播 94 集——從 Twitter 到 Robinhood,新手工程師主管初體驗(ft. Zero Cho) | Star Rocket Blog)
第二集的部分我們可以先跟大家講 vgod 他選的並不是 EM 而是 IC 這條路,到時候可以請他多跟大家分享這個部分,包含他在現在任職的公司觀察到他們的這個產業是什麼樣的環境跟條件,讓公司可以用 IC 這樣的職涯的的發展跟選擇,搞不好會有第三集就先講到這邊,剛剛 vgod 跟大家談到的問題,我會請他再提供一些參考的,不管是書或者是文章附在 Show Notes,我們今天很高興邀請到 vgod 來跟我們連線,請大家不要忘記回來聽我們的第二集,今天先跟大家聊到這邊,我們下一集見,Byebye。
vgod:Byebye,謝謝大家。
(文章代表圖來源:Photo by Alexander Milo on Unsplash)
本文為星箭廣播 154 集——連載再開!從程式設計之道走向軟體工程師的修煉與成長(ft. vgod) 訪談逐字稿,為了方便閱讀,內容經過編修。本集節目介紹與相關連結請到此頁面閱讀。
本文依 CC 創用姓名標示 - 非商業性 - 相同方式分享 4.0 國際釋出