致想轉職軟體工程師的新手們—第一封信

你有一個很棒的 idea,想要創業,你看了所有關於精實創業的方法論,擁有創業家精神和準備冒險犯難的生活態度,現在只缺一件事情—你不會寫 code,你沒有把產品做出來的能力,這個新手正是兩年前的我。在學習寫程式之初,我多麼希望能夠有一個人告訴我該學什麼,需要學到什麼程度,該怎麼面對學不會時的挫折,與怎麼培養獨立解決問題的能力,這些心情我都經歷過,現在我想寫這封信給你,告訴你未來會遇到什麼事,該怎麼克服,以及你可以成為什麼樣的開發者。

在開始學習寫程式之前,我想分享幾個心態上的建議,它能幫助你走過未來無數困難的時刻,因為這將是條困難且漫長的路,我希望你能用最少的時間,學會你所需要學會的知識和技能。

  • 沒有人規定你要花多久才能學會什麼,學會了最重要。
  • 學習分為知道,會做和熟悉三個階段,每學到一個新的觀念和技術,都要想辦法和已知的知識做連結,才能變成自己能獨立運作的技能。
  • 專注在學會新的概念是最重要的,網路上有非常多的資源,但不同資源適合不同學習階段的人,如果一篇教材用你還沒有學會的概念為例去解釋你正在學的概念,請忽略它,我們沒辦法用我們不知道的知識去記憶新的知識,能用你理解的話教會你的教材,才是適合你的教材。
  • 大腦裡負責選擇和學習的位置是在不同的區域,當你在選擇要學什麼的時候,你並沒有在學習。
  • 希望我能以過來人的身份幫助你選擇,而你只要專注在學會這件事,我將會告訴你需要學習什麼和為什麼需要學它,但不會告訴你它運作的方式,因為獨立學習一個新的觀念也是你需要培養的能力。

    看到這裡相信你已經準備好了,那我們開始吧!

    學習基本語法(Syntax)和運算思維(Computational Thinking)

    1. 選擇第一個接觸的語言是很重要的,語言的設計影響到你對程式的理解和寫作的習慣,更重要的,會影響你學習的樂趣與成就感,這個階段你的學習目標有三個:

    • 第一個是要是要熟悉語言基礎語法 if、 for、while、swtich 要怎麼使用。
    • 第二個是要學習語言的 Data Type 與理解 Primitive Type 和 Reference Type 的差別。
    • 第三個是要理解物件導向的概念,能夠熟悉 class 的使用,並清楚地解釋 Encapsulation、Inheritance、Polymorphism 是什麼, 其中 Inheritance 最為重要, 請務必理解它。

    [以Java 為例子] Java 是一個嚴格規範的語言,沒有正確宣告資料類別和正確的使用 class 程式都會執行失敗,現在這個階段對你來說也許很不方便,卻也保證你可以建立更正確的觀念,而剛開始學習程式,建立正確的觀念是最重要的做到以上三件事,你在這個階段的任務就完成了,但是這個時候的你,還不能說會寫程式,一個軟體工程師必須要有運算思維的思考習慣,用更簡單的語言說,就是熟悉資料結構與演算法的運用。

    2. 從熟悉語法到能夠用演算法解題是你會遇到的第一個門檻,因為你還沒有建立一步一步拆解問題的能力,沒關係,讓我幫你整理你會需要用到的方法:

    • Big O notation:首先你會需要理解用來分析演算法的方法,這個概念和微積分中多項式極限的概念很像,是用來分析時間和空間複雜度的方法,也是我們之後討論不同演算法之間權衡(trade off)的重要依據。
    • Array、Stack、Queue、Hash、Linked List、Tree、Graph、Heap。
      Java 內部已經幫你實現 Array、Stack、Queue、Hash 和 Heap, 但 Linked List、Tree 和 Graph 需要自己建 class 或是用前面的資料結構組合而成,請務必熟悉各種資料結構 Java 內建的操作方式,因為我們未來為需要用它實現我們的想法。
    • Binary Search、Recursion、BFS、DFS、Backtracking、Dynamic Programming。
      學習演算法有一個重點,不同演算法的複雜度不同,請依照上面的順序去學習它,如果前一個概念沒有搞懂就去學後面,你會感受到前所未有的痛苦,並非常容易想放棄,例如 DFS 會用到 Recursion、 BFS 會用到 Queue 和 Array、 Backtracking 會用到 DFS、 Dynamic Programming 會用到 Recursion、DFS 和 Hash,觀念是累積下去的,按部就班一步一步學下去,你會更容易理解它們的概念。

    具備基礎能力前的三個階段

    目前為止,你已經知道資料結構和演算法的基本原理了,但是你還不會使用它,為了幫助你練習各種演算法運用在實際的問題上面,我會建議你到 leetcode 照分類題型練習,解題的平台我建議複製 leetcode 的題目到 coderpad 上練習,自己想 test case, 通過之後,再將解法放到 leetcode 用別人寫好的 test case測試。為了有效熟悉並活用各種演算法和資料結構,你會經歷三個階段:

    一、第一次做題目,你會完全想不出來,就算是最簡單的題目你可能都沒有想法,這是很正常的,因為你還沒有建立起運算思維,請堅持自己想十分鐘,忍住去看解答的衝動。我明白這個過程是很痛苦的,但這十分鐘是連結你學到的演算法和解決實際問題的重要過程,也是必經之路。十分鐘了,你還是想不出來,沒關係,你可以上網找解答看看其他人是怎麼做的了,然後試著在了解他的想法之後, 用你的方法再寫一遍,你不需要有任何沮喪的感覺,參考別人的答案也是學習的一部分,每種演算法和資料結構你需要做至少五到十題去熟悉它。

    二、所有分類的題型都做過之後,你會發現自己重複做第二次居然還是做不出來, 這是非常正常的,因為運用演算法解決實際問題這個過程,你只是知道,還不會做,所以你需要熟練你的技術。這個階段訓練的方法就不一樣了,你需要重複做同一題好幾次,第一次 accept 之後,請全部清除掉重寫一次,你會發現還是有卡住的地方,試著做完,也許你還是需要看解答,沒關係,每一次做完之後就清除掉重寫,直到你可以獨立在不看解答的情況下,一次 bug free,現在,你才真的搞懂了這一題。

    這樣重複寫的過程,你會自己歸納出來其中的 pattern,這將會是屬於你自己最珍貴的東西,因為這代表你能獨立使用演算法去解決實際問題的連結,而這個 pattern 在網路上別人的解答裡沒有,任何部落格也找不到,因為每個人腦中的 pattern 都不一樣, 這才是能夠跟著你一輩子的東西。

    三、這個時候你對做過的題目已經非常熟悉了,然而世界上的問題何其多,這個階段你需要的是大量瀏覽不同類型的題目,現在你不會知道哪一題要用哪一種演算法,所以會試著嘗試組合不同的演算法去解決它,並討論時間和空間複雜度,思考在不同情況下你會用哪一種方法,熟悉這個過程後你就會理解,為什麼人家說每一題沒有標準答案,因為實際工程問題其實都有其條件與限制,工程師在做的是討論各種解法的權衡(trade off),熟悉這個過程將可以培養你和其他工程師溝通的能力。

    到這裡,恭喜你具備了 Junior 軟體工程師的基礎能力,大部份的人在走到這裡之前就放棄了,但你沒有,你堅持下來了,恭喜!接下來,為了成為初階的網站開發工程師,下一封信我們要來談談學習新的語言 JavaScript 和網站開發所需要的知識點。

    Image Credit: Erik Trautman