軟件工程師成長手冊
筆者經常都强調軟件工程師有高下之分,不論技術或是解難能力都可以隨時日改善,亦曾大力鞭撻專家級初學者的無知,對軟件開發造成破壞。 初出茅蘆的軟件工程師及編程初學者想要改善自己技術,在茁壯成長的話,對自己技術層面有一個準確評價是至關重要,以免墮入「識少少,扮代表」的認知偏差。
開始之前,先講講本文不是關於甚麼:
本文不是關於軟件工程師晉升之路
本文不是談論軟件工程師的職場晉升道路,因為時至今日,不少公司還是傾向將編程作為入門職位看待,軟件工程師晉升後,就會改為以專案管理工作為主, 而綜觀現實,專案管理與編程本身大相逕庭,所需能力也不盡相同,因此筆者認為以職位討論軟件工程師成長,沒有很大的參考價值。
本文不是關於如何將程式設計師由差變成好
軟件工程師固然有好壞之分,天資也是人人有別,不同個人選擇,不同的習慣,也會導致不同的結果,而受限於達克效應(Dunning-Kruger Effect),欠缺能力的人也難以觀察得到自己的不足,因此對一般中規中矩,有一定技術的開發者而言,也沒有參考的意義。
本文旨在提供一個參照系,方便軟件工程師判斷自己技術的層次何在,看看距離下一個目標,又差多少。
開發者五層次
筆者上次提過的德氏模型(Dreyfus Model of Skill acquisition),描術一門技術有專家(Expert)、熟練者(Proficient)、能勝任者(Competent)、進階初學者(Advanced Beginner)、初學者(Novice)五個層次。筆者認為這個概念其實亦可應用在軟件工程師之上。
初學者(Novice)
顧名思義,初學者就是剛開始學習編程的一群。嚴格來說,也不正式算是軟件工程師。如果你曾經在 Codecademy 完成過一些練習,又或是參與過一些Python工作坊,動手寫過一些程式,那你就屬於初學者級別。初學者級別與完全不懂編程的人,差別很少,初學者大概能理解如何架設簡單的開發環境,如在網上學習平台寫過JavaScript,又或是用Anaconda在Jupyter Notebook 寫過一點點Python,在簡單功能以外,就無從入手了,要解決簡單如FizzBuzz問題,也更不可能了。
初學者層次特徵:
- 只理解一種程式語言的基本功能:例如迴圈、條件運算式、變數及常數等概念
- 能夠理解簡單函數應用,不能理解函數遞歸(Recursion)等概念
- 大多不能理解類別(Class)的應用
- 不能使用教程以外的開發環境(Development Environment)架設,例如使用Anaconda學習Python的同學,卻不能理解使用Python Shell及Jupyter之間的分別
- 不能以一人之力完成一個基本應用
- 除錯(Debug)能力有限,無法獨力解決問題
- 嘗試解釋問題所在時,無法準確表達
值得注意的是,以上特徵並非指初學者技能不足,是因天份的問題,正如學習踏單車一樣,人人皆有不會平衡的時候,是學習必會遇到的問題。要到達下個層次,是時間及努力的問題。
進階初學者(Advanced Beginner)
進階初學者層次相當廣濶,由汲汲營營的學習者、電腦科學系的學生、又或是將編程作為興趣的人,都是算是進階初學者層次。進階初學者層次的開發者,對本身所學的程式語言基本熟悉,無需再經常翻查語法。進階初學者層次與其後的層次有一個最重要的分別,就是進階初學者層次開發者亦不以開發軟件為業,也就是距離成為專業的軟件工程師,還有一段明顯的距離。
進階初學者層次特徵:
- 理解一種程式語言的大部份基本功能:迴圈、條件運算式、變數等必須理解透徹
- 理解函數的應用,也能理解何謂函數遞歸(Recursion)等概念
- 能理解物件導向設計,理解類別(Class)、物件(Object)、方法(Method)等概念
- 開始理解不同的開發環境架設的關係,不只受限於教程所教授的架設方法,例如理解到Jupyter Notebook也有使用Python Shell
- 能以一人之力完成簡單應用,如待辦清單或基本的 CRUD應用,然而由於缺乏專案開發的經驗,較複雜應用也難以完成。
- 除錯能力有改善,常見的問題也開始能獨力解決
- 解釋問題時,開始能以技術用語解釋心中所想,對複雜技術用語則仍是一知半解
進階初學者層次是最難突破的一個,很多編程學習者都會因為缺乏專案開發經驗,難以開發有充夠專業水平的專案,卻也恰恰成為了面試最大的障礙。可是對很多公司而言,有很多實際專案開發經驗的面試者,比大學學位往往更有價值。因此出現了一個矛盾的狀況:公司沒有合乎要求的求職者;想入行卻入行無門。
而有讀過專家級新手一文的朋友,也大概記得自以為是的進階初學者,正正會成為日後的專家級新手。
能勝任者(Competent)
能勝任者層次,對應的就是初出茅蘆的軟件工程師,初級軟件工程師通常在頭一兩年的職場生涯都在快速學習,所以使用科技至關重要,筆者認識一些從事編程的朋友,就是因為在生涯初期使用了一些較為冷門的科技,影響了後來生涯選擇的可能性。
能勝任者層次特徵:
- 理解所有進階初學者層次的知識
- 對本身工作所使用的技術棧(Technology Stack)有一定瞭解
- 懂得發掘新技術,同時有能力學習新技術
- 對完成專案所需時間有大概估計
- 在有足夠時間下,能完成複雜的CRUD應用
- 大多數情況下能夠獨自除錯,只有非常困難的問題才需要他人幫忙
- 透徹理解接口(Interface)及父類別(Superclass)及子類別(Subclass)的概念
- 已理解技術用語的真正意義,亦能靈活使用技術用語以描述心中所想。
- 學習多於一種程式語言
- 學習多於一種的資料庫,理解不同儲存資料的方法之優劣。
可見能勝任者層次,是一個著重於學習的時期,未來發展的方向也取決於這時候的一些決定。這亦是為何在軟件工程師生涯規劃上,頭兩年必須將學習與成長放在第一位,如果一開頭學壞了習慣,就很難在未來的日子再更上一層樓。
熟練者(Proficient)
當一個軟件工程師從事軟件開發有一定年期,累積了足夠經驗之後,就進入了高級階段的階段。經歷了快速學習的能勝任者階段。處於熟練者層次的工程師,由專業的開發經驗,開始形成了自己的見解。大家可能聽過專業知識應該有兩個方面的發展,分別是深入(Deep)及廣濶(Board)兩個方面, 熟練者層次的工程師,可以說是完成了一個範疇(Vertical)的深入發展。
熟練者層次特徵:
- 理解所有能勝任者層次的知識
- 對本身工作使用的技術棧有全面深入的理解
- 對完成專案時間估計準確
- 在有足夠時間,更能解決絕大多數技術問題
- 有獨自除錯的能力
- 理解大部份物件導向開發所需的設計模式(Design Pattern)
- 能以多於一種程式語言撰寫程式
- 能操作多於一種資料庫
- 能根據軟件實際要求,設計適合的架構(Architecture)
處於熟練級的軟件工程師,由於技術早已熟練,開發軟件的效率很高,相較能勝任者之下,是開發團隊中重要的一員。不過亦由於技術熟練,熟練者層次容易由於對自己能力過份自信而失卻了堅持學習的動機。因此不少軟件工程師成長到熟練者後,就會開始停滯不前。
專家(Expert)
如果一個熟練者層次的軟件工程師,開始嘗試以完全不同的技術棧開發軟件,亦因而累積了截然不同的開發經驗,就可以理解為已經到達了專家的層次:專家級軟件工程師,不拘泥於使用那種科技,那種框架,奉行"Use the right tools for the right problem"的精神,因此可以客觀地權衡各種科技之優劣,較少受個人偏見影響。
專家層次特徵:
- 擁有熟練者層次的知識
- 會使用多種程式語言,能隨心所欲按需要時使用
- 對多於一種技術棧有深入全面的瞭解
- 靈活運用不同程式開發範式(Paradigm),例如物件導向(Object-Oriented)、函數式(Functional)、又或是將數種範式混用(Multi-Paradigm programming)
- 由於透徹理解技術背後的原理及理念,能夠快速學習新的技術
- 開發軟件時有大局觀念,決策時會考慮維護性(Maintainability)及擴展性(scalability)的問題
專家層次,是德氏模型中最後層次,這當然不代表軟件工程師進步到這一點就再無進步空間;真正的專家,必然會不斷學習,更臻化境。
總結
可能有人會問,最高的層次,標準似定得太低了,那一眾享負盛名的軟件工程師如Linus Torvalds、Donald Knuth、James Gosling、Guido Van Rossum又在那個層次呢? 筆者認為,這些軟件工程師之所以享負盛名,是因為他們都作出了非常突出的貢獻,有如在奧運會擊敗其他世界級運動員,成功奪金一樣,因而名留青史。但層次上而言,難以斷言這些著名軟件工程師比起其他專家級軟件工程師有何本質上之不同。因此本文想帶給大家的,正正是為了令各位更容易理解何謂一個「世界級」的軟件工程師,就唯有暫時忽略討論「大神級」的軟件工程師了。