在〈You Know Nothing About Code〉(http://goo.gl/uRIHD8)這篇文章之中,Alex Parker說到:「習慣它吧!別想要無所不通!」然而,程式人總是得隨時隨時精進自我,這似乎是種矛盾,只是在現今的技術洪流中,我們又能跟得上多少技術呢?
這麼多感應器,怎麼學得完?
由於在軟體領域的時間浸淫的時間比較多,對一門技術完全從無到有的感覺,相對來說已經沒有那麼強烈。
學習新的程式語言時,即使語言中標榜著多麼與眾不同的新語法,然而憑藉著已熟知的程式語言,要再獲取一門新語言總是沒麼難的感覺,學習一個新程式庫,新的框架、新的工具等,基本上不會遇到什麼大問題,憑藉著過去的經驗,多半都得以解決問題,是否學習一門技術,除了工作需求之外,多半是基於興趣罷了。
不過,最近一陣子接觸微控制器以來,發現心裡總是時不時地問自己:「這麼多感應器,怎麼學得完?」或許是在這領域荒廢了十幾年,在這個領域的基礎幾近於歸零,各方面知識完全從無到有的感覺就被突顯了出來,而且,某些程度上,各種感應器模組,可以比擬為軟體領域的程式庫,而微控制器大概就是框架了,我開始明白,為何在軟體領域總是會有人問我:「這麼多的技術,接下來我該學什麼?」
相對其他領域來說,軟體領域的技術進展可說是異常的快,想要成為程式設計者的條件之一,就是能不斷學習新技術,除了工作上會用到的技術之外,有餘力的情況下,也得學習工作上暫時用不到的技術,到PTT的Soft_Job搜尋標題中有「下班」的文章,就會發現許多人在下班是否還要學習相關技術上糾結,這多半也反應出能不斷學習新技術,對身處軟體領域來說,絕對是必要的能力。
這麼多的技術,怎麼學得完?這麼多感應器,怎麼學得完?我很明白,漫無目的地學習,只會迷失方向,最後只會學了一堆,卻不知道怎麼整合與應用,因而最近我在工作之餘,開始了一些小的Side Project,先是試著仿做Plotclock(http://goo.gl/fA4gR5),接著試著自己設計六足機器昆蟲,然後遇上些問題,接著想辦法克服它們,無論是用上新學到的東西,或者是需要一些稍稍超出我目前程度,但又能進一步掌控的知識。
學著將廣度化為深度
在《The Pragmatic Programmer》書中第一章,對程式人在知識投資組合(Knowledge portfolio)上給的第一個建議是:「每年至少學習一門新語言」,其理由是不同的語言會以不同的方式解決問題,因而可以學到不同的解決方法,藉此保有想法上的活力,避免一成不變。
就我學習各種語言的經驗來說,確實是如此。從JavaScript中,可以學得基於一級函式與基於原型的設計;從Python中,瞭解到保持簡潔與一致性的重要與方法;從Ruby中,習得meta-programming的作法與彈性;從Haskell中,學到了純函數式中隔離副作用的好處與思路。
不過,當想要解決問題時,在可以的情況下,我還是會選擇使用Java來解決問題,而曾經在其他語言中學到的想法,將會成為使用Java過程當中可能運用的元素。
即使是學習各語言背後生態圈中各自衍生的技術或工具,也是如此。像是Rails快速開發框架的概念,Node.js的非同步設計等,學習的同時我都會思索,在Java的領域中,有沒有對應的產品或者設計方式,有沒有辦法將各語言生態系中獲得的廣度,深化到Java之中。
另一方面,我並不是對各種技術有興趣,而是對這些技術背後要解決的問題有興趣,以及它們是如何被解決;知道這些之後,當在Java中面對類似的問題,若情況適當,我就可以用最熟悉的語言或工具,但採用另一個領域中更好的設計方式來解決。
有趣的是,語言之間總是會互相學習,而很快地,某個技術領域解決問題的方式,會在另一個領域實現,無論那是透過語言本身的新特性,或者是程式庫、框架等方式,在此同時,被深入到Java之中的知識,就得以獲得應用。
辨識問題,並解決問題
這年頭,想要成為一名程式設計師,要懂的東西還真的是不少,實際上除了技術之外,還得懂演算法、資料結構等理論基礎。
前些日子就發生了Homebrew作者Max Howell 在面試Google時,因為沒能在白板上反轉二元樹,而被Google拒絕的事(https://goo.gl/s8uy3E),儘管各方對這件面試事件有各種不同的角度與看法,然而也表示了演算法、資料結構這類理論基礎,對身為程式設計師來說,仍是件值得被重視的事,對了,也有不少人建議,寫程式最好要懂數學!
如果沒有具體待解決的問題存在,討論寫程式要不要懂演算法、資料結構甚至數學這個問題,基本上就不會有交集存在,總有人會聲稱寫程式至目前為止,從沒有(直接)用過演算法、資料結構或數學。
其實,如果他過往遇到的問題不是演算法、資料結構或數學要解決的對象,這種說法並沒有錯,如果他今天遇上的問題是要往圓錐水槽注水,且必須用程式來控制水面的上升速率,就很難不用上數學。
有一定經驗的程式設計師,遇上問題,往往能第一時間就知道根源在哪,有時第一時間雖不知道根源何在,基於過去的經驗來推敲,也能找出並解決問題。這種「Debug的直覺」,不少人都有過類似經驗,這其實是因為過去面對過足夠多的問題,並累積了多個解決問題的思路與方向,方能有這類Debug的直覺。
無論是數學、資料結構、演算法或者各種技術,不過就是解決問題時可運用的工具,因為,手邊有的工具越多,解決問題的方法就越多。
學習更多技術,是為了辨識出有哪些問題並解決問題,學習演算法、資料結構、數學等理論基礎,也是要辨識有哪些問題並可以用這類理論來解決。
因此,辨識問題是一個很重要的能力,不少人應該都有這類經驗,明明在你眼中顯而易見的問題,為何有些程式新手就是看不出問題,學的技術或理論越多,就要能辨識更多的問題,也才越能基於廣博知識來解決問題。
動手做並面對失敗
這陣子接觸微控制器有不少感想,其中之一是,學習硬體比學習軟體,在金錢成本上比較顯而易見。軟體上要嘗試程式庫、框架、工具,網路上有取之不盡的資源,而且通常(表面上)免費,學習微控制器要玩個感應器或電路模組,總是得花錢購買,在銜接各模組時一個不小心,還會「碰」個一聲,看著電路模組冒出一縷輕煙。接觸微控制器時,學會面對這類的失敗,是個必要的過程。
實驗需要成本,相對來說,軟體上一開始面對失敗時的金錢成本比較低,因此別浪費這種機會了。在學習各種技術的同時,你應該儘可能地動手做各種實驗,實驗若失敗了其實應該高興,每面對一次失敗,就多一次經驗,每解決一次失敗,就多一份能力。在程式設計這領域,特別強調Get your hand dirty,就是這樣的道理。
在Maker領域中〈想靠3D列印創業嗎?〉(http://goo.gl/Yh3v7I)中,有句話寫道:「列印想法,而不是列印產品」,這讓我在學習各種感應器使用或電路模組原理的過程中,能時時承認「學不了所有的東西」,這樣我就能知道該學習的是辨識問題與面對失敗,而不是學習所有的技術,無論那是在硬體上的技術,或者是軟體!