學寫程式為何甚艱難?
2019-06-13
如果你想學寫程式,在網上搜尋一下,不難找到不少「輕鬆學習XXX」、「YY天輕鬆學會Python」的教材及影片;去電腦書店逛一圈,很容易就可以找到「七天學會Java」等的書籍,這些教材其實都在推廣一個信念,也就是: 學寫程式很簡單,人人都可以學會。 筆者對此信念後半部深表認同,但是對前半部所謂「學寫程式很簡單」,卻真是不敢苟同。
筆者深信No pain, no gain
的哲學,世上大部份有價值的事物,都必須努力才能達到,如果真是可以「YY天輕鬆學會編程」,那豈不是明天所有軟件工程師都要失業?學寫程式,就像練馬拉松一樣,人人皆可做到,只是必須要付出努力。將一樣要付出努力才能達成的事物,簡化成「XX天就可以輕鬆學成」,會令初學者初遇困難時,誤以為自己無甚天份,繼而失去學習動機。反而一早說明學習時會遇上的困難,才能為初學者提供正確的心理準備。就像你要去挑戰一座高峰,你找了一個曾經登上該座高峰的朋友請教,那朋友卻說:「很簡單的,不用訓練,人人也可以上去」,這可不是安慰說話,而是害人不淺。
你必須學習新語言
程式語言之所以稱為程式語言,原因是因為程式語言確是一種語言,而且皆是專為向電腦說明步驟而發明的。因此本質上與自然語言有很多不同的地方,一個經典的Programmer笑話是這樣的:
A programmer is going to the grocery store and his wife tells him, "Buy a gallon of milk, and if there are eggs, buy a dozen." So the programmer goes, buys everything, and drives back to his house. Upon arrival, his wife angrily asks him, "Why did you get 13 gallons of milk? " The programmer says, "There were eggs!"
妻子明顯的意思是想丈夫買一加侖牛奶,如果有雞蛋的話,就多買一打雞蛋,但丈夫卻理解成以下的程式碼。
buy(1,'gallon','milk'); if(has('egg')){ buy(12,'gallon','milk') }
就創造了這個經典笑話。當然笑話的內容不足為信,但程式語言與自然語言的差距卻是確實存在,現今出現了不少學習編程遊戲,幫助沒有任何編程背景的人理解一步步來的程式思維方式,算是為減低學習編程門檻的一大進步。當然為了提起玩家之興趣,亦只包括了較為基本的程式語言語法。
Picture of Human Resource Machine
當代常用的程式語言,除了基本的流程控制結構,如if-else
條件判斷式、while/do-while/for loop
迴圈外,還有function
函數、class
類別、interface
接口等高級概念,這些詞語在英語都有原來的意思,在程式語言的意思與英語相似而非完全一樣,因此對初學者而言,是要從零學起,就像重學外語的基本語法一樣。再加上很多希望學習程式語言的人,未必以英語作為母語,使學習門檻更高。幸運的是,程式語言與自然語言不同,一旦學成了一種程式語言之後,要再學習其他程式語言,斷不會像學習外語一樣又要從零開始,因此精通數門程式語言,遠比精通幾門外語要簡單得多。
你必須學會抽象式思維
寫程式常常需要運用抽象思維,例如所謂的佇列(Queue)結構,對應現實生活的就是大家不論買早餐、搭地鐵、搭巴士時都會排隊的隊列,佇列在電腦世界很有用,常常用作將任務順序執行,這種佇列因此又名為任務佇列(Task Queue)。排隊是日常常見的事,但是將排隊的概念應用於電腦程式之上,正是抽象式思維(Abstract Thinking)的典型。除了愛好數學、科學的朋友之外,大多數初學者甚少以此角度思考問題,因此覺得困難也是自然不過。
又例如函數(Function),如果你將函數理解成數學的函數如f(x) = x * x
一樣,也就是將一些輸入(input)x
,轉換成輸出(Output),那尚算容易理解。但當你將函數作為其他函數的參數(Parameter),形成所謂的回調函數(Callback Function)的時候,就需要抽象式思維了。
function square(x){ return x*x } // Callback function in use setTimeout(function(){ // This function is called after 1000ms },1000)
抽象概念另一大難處,在於難以用日常生活例子類比理解,筆者在教學時常常花九牛二虎之力,讓學生理解回調函數及非同步的概念,初學者直覺上不習慣以此方式思考。正因日常生活難以鍛煉抽象思維,於大多數人而言,唯一受過對抽象思維有系統訓練的地方,就是中小學的數學課(低年級科學課通常重直觀,非抽象思維),不過很多人不喜歡數學課就是了...
你必須分毫不差
很多職業都要求高度的精確性(Precision):醫生用藥必須準確,否則病人就有性命之虞;土木工程師需要準確計算建築承托力,否則建築物就會成為危樓。編寫程式也是一樣,一個標點符號的錯誤,就足以令整個程式錯誤,甚至停止運行,而且回報的錯誤更常常令人摸不著頭腦。 大家一定對以下的經典畫面,不會感到陌生。
當大家自己學習軟件開發時,錯誤就更加常見。曾經學習過JavaScript作網頁開發的人,都一定見過以下的錯誤:
驟看之下,該錯誤就如不知所云,只是告訴你Uncaught ReferenceError: people is not defined
,其實這個錯誤的真正原因,在於上邊定義的是person
而不是people
,因此當瀏覽器嘗試運行時,只是發覺people
未定義,因此就直接回報people is not defined
的錯誤。
電腦不是人類,不能準確指出:「你把person
寫成了people
」的錯誤,只能夠重覆告訴開發者people is not defined
。正因電腦並不真正「理解」(縱是當今最先進的人工智能,也難以稱為真正理解)人類背後行事目的,因此無法準確回報一個常人能夠即時理解的錯誤。要成為程式開發者,就需要將相關的錯誤訊息(如people is not defined
),聯想到常見的錯誤(串錯了變數名字)。因此可以說,程式開發本質需要分毫不差,任何最微細的錯誤,都不能夠出現。 然而相對於電腦的分毫不差,人類可謂天生就常常犯錯,除非經過後天大量訓練,否則難以習慣。
你必須持續練習
有留意筆者之前文章的讀者,都知道筆者常常强調軟件工藝的重要性。要學成一門工藝,必須要持續練習,才可以精益求精。
正如學會廿六個英文字母不等如成為莎士比亞一樣,學會程式語言的基本語法,也當然不是學習軟件開發的終點。單元測試(Unit-Testing
)、設計模式(Design Pattern
)、程式碼結構(Code Organization
)等,都是需要多寫多想,才能融會貫通。
筆者在軟件工程師成長手冊一文中,提過開發者有五個層次: 初學者(Novice)、進階初學者(Advanced Beginner)、能勝任者(Competent)、熟練者(Proficient)、專家(Expert)。要算是達到職業水平,起碼要到達第三層次能勝任者的級數。也就是對本身工作所使用的技術棧(Technology Stack)有一定瞭解,以及懂得發掘新技術,同時有能力學習新技術。而科技發展日新月異,技術推陳出新,程式開發亦自然如是,要能夠掌握新的技術,也一定需要持續學習。對絕大多數初學者而言,學習程式最難跨過的障礙,正是缺乏足夠時間去持續練習。因此這個因素簡單易明,卻也是癥結所在。
你必須有創造式思維
由普羅大眾角度看來,編程是一個只與電腦、數字打交道的職業,其實創造思維(Creative Thinking)在編程中,也是不可或缺。編程的本質,就是由無到有,創造(Create)一個能夠解決問題的程式。天底下沒有兩個程式設計師會寫出一樣的程式碼,就正如不會有兩個寫出一樣文章的作家。
編程果真需要創造思維嗎?其實對一個專業程式設計師之日常工作而言,從沒有兩個問題是完全一樣,因為如果該問題已經解決過一次,就再沒有解決的必要(除了教學用途外),這也是著名的DRY原則(Don't Repeat yourself)。例如為物件排序(Sorting),也許你會認為方法只有一兩種,但光是維基百科的Sorting Algorithm條目,就有超過二十種不同算法,而且每個方法,也有各種優劣之分。
為物件排序如此目標明確的問題,都可以有超過二十種算法,真正現實世界之系統,例如會計系統、倉存系統、客戶資料管理系統,就更可謂有無限種解決方法。程式設計時要選擇最佳最有效率的方法,就如一個畫家創作時選擇最美的表達方法,都必須有創造思維在其中,只是編程稍為限制,程式碼必須正確才能運作,筆者認為,這實是一種基於邏輯之創意(Logic-based creativity)。也正因如此,學習編程,也代表必須學習如何運用創造思維。
總結
一口氣講了學寫程式之困難所在,絕不是為了使各位正在學習編程的人卻步,而是正正因為學習編程的中途,會有不少障礙攔路,早早準備,就如攀登高山前充份準備一樣,才是合適的學習心態。
Comments
Read More
好Programmer是怎樣煉成的?
2018-12-20
有一個大部份僱主都面對的難題,在芸芸履歷之中,如何萬中挑一,找到好programmer呢?聘請程式設計師很難,不像其他行業,打開 履歷就一目了然:有時履歷上滿滿証書的,其實連FizzBuzz也寫不了;有時看起來像個fresh graduate的,卻又有無限潛力。 如果你是一個要聘請程式設計師的僱主,你應該如何是好呢?
新年願望:學寫程式懶人包
2019-01-02
剛剛過了2019的新年,大家許下了甚麼新年願望呢?也許大家會希望在2019年學會寫程式,突破自己
專家級新手
2019-03-19
今次要介紹的,是一個非常常見之現象,不論你是學寫程式、學做甜品、學寫文章,又或是練習球技、體能訓練等,都會經常窺見其身影。 想像一下:你的朋友問你:「你的駕駛技巧好嗎?比較起其他司機來說如何?」如果你本身有駕駛執照,但是不常常駕車,大概你會回答:「中規中矩吧,平均水平」;經常駕駛的人,因為經驗豐富,會覺得自己是中上甚至良好之水平。然而,這個想法人人都有,卻與現實完全相悖:因為任何羣體之中,必然有一半個體在中位數(Median)以下,而一項經典的調查發現,八成的司機都認為自己的駕駛水平在平均之上,這明顯代表在駕駛技術的世界上,大部份人都有自視過高的問題,也代表其實大多數司機,無法準確判斷駕駛技術之高下。
軟件工程師成長手冊
2019-04-29
筆者經常都强調軟件工程師有高下之分,不論技術或是解難能力都可以隨時日改善,亦曾大力鞭撻專家級初學者的無知,對軟件開發造成破壞。 初出茅蘆的軟件工程師及編程初學者想要改善自己技術,在茁壯成長的話,對自己技術層面有一個準確評價是至關重要,以免墮入「識少少,扮代表」的認知偏差。