天天看點

《逆襲大學》文摘——9.1 一切讓代碼行數說話第9章 讓專業學習更有效

  程式設計是一門藝術,這門藝術隻有通過實踐才能掌握。檢驗計算機技術學習成果的标準是實踐,我們對此寄予厚望。隻有代碼量達到足夠多時,量變引起質變,才能夠有機會見識到足夠美麗的風景,水準才能真正提高。有業内人士描述:當你寫過一百行代碼的時候,對程式設計有了一個朦胧、感性的認識;當你編碼的行數達到一千的時候,差不多掌握了程式設計的基本結構;當你寫過一萬行代碼的時候,可以做自己喜歡的小玩意兒了;超過了十萬行代碼的時候,你會對自己編碼能力充滿自信。

  開車也是一個實踐性的工作。要評價一位司機的開車水準,拿出一個硬名額,那就是裡程數。一千公裡還算是新手,兩萬公裡算出徒,要說自己是老司機,開完十萬公裡先。

  學計算機的你要去求職了。面試官很忙,要用一個簡單的名額代表你的水準,說出你在大學編過的代碼行數。這是一個讓人服氣的名額,李開複的建議是,四年寫完十萬行代碼。

  好司機,用裡程數說話;好程式員,就用代碼行數說話。

  有一位網絡工程專業大一學生小a在給我的來信中談道:

  我在程式設計課程中每次課都很認真聽,甚至期中考試的成績是專業第一。不過因為期中考試更多的是選擇題,程式設計隻有一題,還是隻需要自己填幾空就能運作的。我現在覺得力不從心是因為我忽然發現,我隻能看懂程式,卻不能很容易地敲出屬于自己思想的代碼,甚至是不能敲出。有時候我覺得這是因為自己敲的代碼太少了,基本上隻有課堂上老師讓練習的時候才練習。一個學長說重在思想,關鍵不是做的多不多的問題。我不知道自己究竟問題出在哪裡,真的很困惑。

  小a的困惑,其實是應試出來的“好學生”們共同面臨的疑惑:跟着老師的學習遠遠不夠,需要課後再拓展。要知道大學裡,考試成績高往往也說明不了什麼。小a提到的期中考試隻有一道程式設計題,并且“填幾空”就能做出,這是老師的不妥。我知道我的一些同行們,在教學難以達到目标要求的情況下,他們不敢考學生,常用容易讓學生得分的方式進行考試,以避免成績單上的尴尬,也讓學生不至于“有意見”。但這樣的做法,根本上是誤人子弟,又間接地鼓勵了學生不去改變學習方式,其實也掩蓋了他自己教學不力的事實。學生在不會程式設計的情況下,也能得到高分,這樣的成績讓學生都覺得好笑。

  考試方式的問題按下不表,單說小a隻重視了看書、做作業的學習形式。他在學習中的問題實際上自己已經給出了答案,“敲的代碼太少了,基本上隻有課堂上老師讓練習的時候才練習”。小a需要做的是,需要将實踐充分重視起來,需要自己安排另外的練習,在程式設計體驗中學會程式設計。别人喂不飽,就得自己去找食吃。關于程式設計實踐的内容,可以從很多途徑得到。

  在學長的建議中,前半句“程式設計重在思想”說對了,“關鍵不是做的多不多的問題”也對,但是他是要講給一位做程式設計題做不下去的學弟學妹,最多算對一半。我要對此更正:要建立程式設計思想,離不開足量的實踐。大學的各門課程,尤其是各種專業基礎課,目标都是針對着對計算機的了解、對程式設計的了解,是用于建立程式設計思想的,看來這位學長真也繼承他的老師的衣缽,程式設計課的考試隻考一道填空型程式設計題就夠了。程式設計要在程式設計思想的指導下進行,但程式設計思想可以從日後的學習中得來一些,這是學校傳授的套裝知識中的一部分,但一定要有個人足夠的體驗,這是獲得學習興趣,将個人經驗與套裝知識中前人經驗結合起來,形成自己的程式設計思想的過程。

  在程式設計思想建立起來之前,足量的實踐必須堅決貫徹。程式設計的實踐,就是讓學到的知識,轉換為可見的代碼。在我的教學實踐中,大一的學生,一年的c++代碼行數平均可以達到一萬行左右。到了這個平均數的同學,即使随後的學習程序會有小的停頓,但任何時候想要回歸,都有資本再次上路。為了達到這個代碼行數,跟我的學生要付出不少精力,課外有很多的時間得花在機房裡,有時還為找不到機位而發愁。我曾經教過的學生和我講,大一跟着我忙了一年,習慣了圍繞課程積累代碼行數,到大二後,同年級的不少同學覺得沒有事幹,而他們盡管不跟我了,但知道要做什麼事,仍然在忙。每到這時,我都暗喜,這就是大學,忙就對了。

  父母對孩子有着高尚和無私的愛。這種真愛是從“一把屎一把尿将孩子拉扯大”的過程中得來的。隻有在不計代價的程式設計實踐中,才能得到對程式設計的愛,才能夠享受到學習程式設計的樂趣。對程式設計的愛,有人挂在口頭,有人是自心頭湧出,還有人,是用指頭敲出來的。隻挂在口頭的愛,轉眼可能就會見異思遷,有其他好玩的立馬走人;發自内心的愛,必是有所體會,這種好感覺能伴人走得很遠;而程式設計如過日子,其中有苦有樂,隻有在踏實的工作中,才能見到平凡中的偉大。程式設計中,唯有用指頭敲出來的愛,才是摯愛。

  未來的程式員就是在代碼行數的積累中成長的。然而新的問題是,為了代碼行,要做些什麼?有些同學,盡管心急如焚,卻也等不來誰布置作業。要想到大學有幫助的自學了,其實,要做的題目和項目有的是,但需要自己用心去把握。

  每上一門課程,老師備課、講課、布置作業、檢查作業,學生預習、聽課、做作業、複習,這是一個固定的套路。作業中,是老師要求學生完成課外學習的内容,最常見的形式就是題目。在大學,每個專業都會安排一系列的實踐環節,有各種實習、實訓。根據專業不同,開展的形式各有差異,工科的還有課程設計,文理科的做學年論文,所有的大學生都要完成畢業設計或畢業論文。

  培養方案内的設定可以算是周全的了,有不少同學按部就班地完成這些學習任務,獲得了該有的能力提升,将理論與實踐聯系起來。無論是做作業中的題目,還是完成實踐,我們可以看見大學中的衆生相:有人輕松完成,有人知難而進,有人伺機搭車,有人坐享其成,有人知難欲進卻無奈退卻,有人置之不理,有人心生得意,有人暗生悔意,有的人是另外一種的洋洋得意。就在不同的學習程序中,衆生在熱鬧的大學中各自找定了位置。我見過不少“能幹”的同學想在分組的實踐環節中與兄弟們并肩找到不孤單的感覺,最後卻也在無奈中獨自拉起大車,捎同學一程。我也見證了這些“負重”而行的學子,在走出校園時的輕松,在就業市場上的自如。如果有人和他們一起拉車,原本車的分量可以更沉一些,他們能得到的體驗更多一些。培養方案的安排本是周全的,事情本來應該是什麼樣子,就應該如何去處理,這大概是我們共有的選擇。明知走偏了,還要那樣走下去,留下的隻能是遺憾。

  作為老師,我曾經是不願意給學生布置作業的。課後做什麼題都需要老師指定,這樣的大學,沒勁。但後來發現,不布置作業,給有些學生傳遞的信号就是沒有作業,就是意味着課後不用學習。于是我開始布置作業。再後來,我不敢給學生多布置作業,當我控制不住抄襲的時候,何必要在這樣一個群體内部制造虛假的繁榮呢?我想起自己在上大學的時候,大部分老師都不布置作業,但預設教材中的習題是要全做的,做完以後自己找資料核對答案,這也是不少同學的選擇。

  大學的課内要求,無論是理論學習,還是實踐能力的培養,都隻是一個基本要求。對于想真正學有所成的大學生,我更看重他們在課外可以從事的題目和項目,這注定了大學生活各具特色的精彩。

  羽翼未豐的it菜鳥身單力薄,寫代碼的課外習題成為首選。我在課外專業學習指導中,極力鼓動學生擺脫隻靠着一本教材學習的習慣。看同類的教材或著作,與讀書同步,完成其中的習題,這是課外題目的一個來源。課外的讀物要瞄準經典的教科書,有位同學感歎道:“狠狠地讀,認真地把書裡的習題都給做了,對于打下紮實的基礎有極大的幫助。”

  有些同學選擇了将看過的書中的例題自己做一遍的做法。這種模仿對于起步無門的初學者很合适。隻不過,我不贊成照着書抄下來的做法,在“抄之有道”的建議中,我談到可以采用先看懂,然後自己寫出的做法。可能需要多次的重複,但如果繞開該有的重複采用所謂的捷徑,效果并不能保證。

  目前網絡很普及,想多做一些程式設計題目的同學可以很容易地從網絡上找到合适的題目做。最好的資源,莫過于各個學校建設的線上評判(online judge,oj)平台了。本校沒有oj平台的,可以使用别的學校的oj平台,略加搜尋,會找到一大批這樣的資源。本着acm競賽開放、共享的理念,隻要去完成注冊,有網際網路在,各個學校的oj平台上有做不完的題目在等待。刷題可以從“水題”開始,高手眼中的“水題”,可能恰是你正需要的寶貝。回頭看,哪個高手不是從做水題開始的?找到一個可以歸宿的oj平台,也就找到了一個可以依賴的組織,大家一起營造在實踐中進步的氛圍。刷題,參加線上的周賽、月賽,與未謀面的學友們共同進步,這是一條成為高手的可行之路。

  做程式設計題目多了,會對算法提出新的要求。在算法類知識的學習的階段,也要有針對性地對某類資料結構和算法進行實踐。教科書中的算法一般用僞代碼描述,将之用某種具體的語言實作,建立自己的算法庫,這是一類非常好的題目。在實作算法的過程中,會在抽象的層面上,得到更大的提高。

  做題目最高的境界,是自己給自己寫題目。有個段子,說某人考試隻做60分的題,多1分不要,少1分不可能。傳說中的這種人,是真正的高手。如果能夠在學習中給自己拟出題目來,那是真正在學習中掌握了主動。在我的學生中就有這樣的人。做完了7位評委打分的歌手大獎賽計分程式,他想到了評委人數不是7個怎麼辦?評委打分要求不是0~10分,而是百分制,又将如何?運作一次程式隻計算一個歌手的成績,要20名歌手不間斷計分又如何處理?如果歌手人數不定時,怎麼辦?評委人數很多,要去掉兩個最高分和兩個最低分,又有事做了。輸入各評委的打分得到正确的輸出結果了,比賽結束最後還有要彙報平均成績之類的任務,輸出結果如何儲存?比賽結束後要對于成績進行複查,以防止在計算中有意無意的差錯,對資料存儲提出了新的要求。順着這樣的思維,任務還可以拓展。一個題目,或者在現實生活中遇到的一個問題,就可以一直拓展下去,俨然有點形成一個“項目”的趨勢了。而在完成這些題目的過程中,各種技術都可以融合進來,學習中的激情何愁不來?“不知道這些東西學了有什麼用”之類的問題,怎麼會對這些善于自我探索的同學造成障礙?

  做題目,能夠針對具體的方法和技術,解決小型的,精心設計限定了範圍的問題,進而獲得學業上的提高。這是一種見樹木,而不見森林的做法。這種做法是需要的,一口吃不成胖子,需要有這樣的耐心。這樣做的時間久了,有了更大的野心和更多的疑惑。

  有學生在我的部落格中留言問道:

  老師,能給說一下連結清單、隊列、樹、哈希表等資料結構實際工作中的用途嗎?怎麼把理論和實際聯系起來?

  面對這個很泛很大的問題,我先“呵呵”一個,說一千道一萬,不如指路一條,回複道:

  看來你是已經學過了這些知識,面對這個到處都有答案的問題,我建議你現在可以接近實際工作自己去體會了。試着做點小項目如何?小遊戲、通訊錄、圖書管理系統一類的題目就不錯。

  有了做題目的積累,實踐能力得到提高,就應該到做項目的層次上去小試牛刀了。面對初學者,我們對項目不作嚴格的定義,那些規模稍大一些,需要的代碼行數稍多一些,具有相對完整功能的系統都可以稱為是項目。能用百十行代碼搞定了題目,做千餘行的項目,會面臨新的問題和挑戰,在積累代碼行數的道路上也将會有新的體驗。

  做題目和做項目也并不是兩個截然分開的階段,沒有一個标準規定題目做了多少才能做項目,時機合适就可以開啟一段新的體驗。例如,在大一,為學習c語言而做題目,與此同時,自學了一些dreamweaver和html,可以考慮做一個班級首頁,這可以算作是一個小項目了;而在大二初期,用c語言做課程設計的項目,同時開始學java語言,又要做一些題目了。這種交叉的體驗,将不斷将你推向一個個新的高度。

  項目從何而來?課程設計、大作業的内容可以視為一個練手的項目。自己做,不搭車,這是應該把握的一個底線。做不出來,說明學得不夠,可以選擇熬夜突擊。要為此早做準備,平日的學習也就有了動力。套用做題目中的思路,從教材、參考書中可以獲得練習項目的來源,從網上能找到别人拟好的項目需求,還可以自己提出創意自己開發。記得我在大三時,想用剛學的foxbase+編一個小型資料庫系統,完成母親負責的農村信用站存取款業務。這樣的開發永遠不會有人采納投入實際應用,但對一名大學生而言,還是一個可選的好項目。最終這個項目半途而廢了,但我從中獲得了不少的感悟。

  做程式設計題目中可以利用acm競賽與oj平台,做項目也可以抓住參加一些專業性比賽的機會。我所在的山東省每年都有齊魯軟體設計大賽,吸引了不少學子參加,學院也給這項門檻不是很高的專業競賽以場地、資金方面的大力支援,主要看重的就是同學們的參與經曆。很多大學生選擇利用暑假的時間,完成一件具有創意的作品參賽,收獲了專業學習中的第一個項目,找到了專業學習的目标。由于有共同的目标,幾個人能夠團結在一起,共同攻克遇到的難題,這樣的合作學習曆程也令人難忘。現在類似的比賽機會非常多,隻要在搜尋引擎中輸入“軟體大賽”、“應用大賽”之類的關鍵詞,你會發現政府部門、行業協會、著名企業組織的各種比賽。微軟、阿裡、騰訊、百度等企業更是常年不斷地推出與前沿技術相關的應用大賽,參賽者借此增加閱曆,提高水準,赢得資金及實習機會,甚至得到了進入大企業的入場券,這些都是額外可能的回報。

  企業在組織相關的比賽過程中,一方面意在增加自己的影響力,另一方面也希望能夠從思維活躍的年輕人中間找到發展業務的好點子。這形成了參賽者與企業之間雙赢局面的可能,我提倡參賽者能夠自己提出獨特的需求,并展現在作品中,這是另外一種能力,也是當代的技術人員應該具備的素質,需要在實踐中形成。未來的工程師應該有能力自己提出需求和創意,想想蘋果公司通過改變互動方式進而重新發明手機的成功案例,就知道創意的價值了。最前沿的工程教育方法cdio中,也将構思(c)作為工程師必備的能力。而不少熱衷于技術的同學隻顧着要學習的技術,往往對創意卻不太在意。大學生需要觀察周圍人們的生産、生活還需要點什麼,有什麼以後會更友善,更有趣,更有效。用一個好的創意,而不是現有擅長的技術,帶動起課外的自主性學習,這是一個能站得更高的方式。

  除了競賽,可以圍繞着各種開放開發平台找到機會。現在,很多it企業和學術機構已經在雲計算平台、社交網絡、電子商務、微網誌、多媒體、安全等領域建立了不少開放資源,如新浪雲平台、google developers等,用于支撐web應用、移動應用等領域的開發。當程式設計經驗積累到一定時候,可以借此起步,開啟一段新的探索之旅。

  通過網際網路,大學生還可以找到真正的做項目的機會。很多網站和社群提供項目交易的平台,比如隸屬于csdn的csto是一個中文軟體外包和項目交易平台,目标是為企業和個人提供各類軟體外包解決方案。在csto中,展示了數不清的項目需求,從幾百元到幾十萬元的項目等待着開發者去競标,内容涵蓋移動應用開發、網站建設,應用軟體開發及多媒體等各種項目。作為在校大學生,從簡單、廉價的項目開始做起,積累技術開發經驗,同時也了解了市場,在未來求職的履歷上,放下一枚重量級的砝碼。類似的項目交易平台很多,這不由得讓人感慨,生在這個機會多多的時代的幸福。

  在開源項目日漸深入人心的今天,參與開放源代碼運動也是大學生積累項目經驗的一個很好的途徑。開放源代碼對程式員來說意義非凡,從開源代碼中,不僅可以學到多種程式設計方法,提高程式設計能力;還能獲得好的思想,激發程式設計靈感。對于大學生而言也是這樣。在學習開源的過程中,通過閱讀、測試、修改bug等環節,将學得架構與模式,以及相關領域的結構與算法。參與開源項目之前可以通過閱讀簡短的程式積累一些經驗,標明自己感興趣的領域,從簡單的項目入手。圍繞開源,還有不少開源軟體競賽和針對大學生的暑期代碼夏令營,可供大學生選擇。

  大學生課外做項目面臨的一個實際問題是缺乏指導。事實上,周圍的老師,他們并不是所有人都不願意幫助學生。學生主動一些,會發現身邊的好老師。在我的身邊,就有大學生通過前期主動的技術積累,而後,與老師取得聯系,獲得了參與老師科研工作和項目開發的機會。老師的項目需要人手,而大學生需要積累開發經驗,這是一個雙赢的局面。即使學生不能為老師直接提供什麼,大多數老師還是願意為追求進步的大學生提供資金、場地等有形的條件,以及指導、鼓勵等無形的幫助。其實要獲得指導的途徑也不限于老師。高年級的學生、研究所學生都可以請教,現在社交網絡很友善,找到已經畢業的師兄師姐,在論壇中找到某領域中的專家,這些全都是可行的途徑。畢竟在課外學習中做項目,如同未來的獨立工作,要立足于自主,找到合适的人,能夠指點一二,其餘的事情都需要自己去做。

  無論是做題目,還是做項目,如果能夠有一個小型的團隊,互相鼓勵和支援,共同克服學習中的困難,這都是難能可貴的事情。有大學生給我寫信,講起了他們的團隊和在選擇題目中的考慮。的确,人多了,事也就多了。

  我現在已經大三了,我們班有幾個基礎差不多的同學,組建了一個團隊,其中有學圖像識别的,有學java的,有學c的,還有學網絡的。我們想在畢業前自己做做項目,這樣對我們所學的知識做一個總結,也希望能在找工作時給我們提供幫助。我們剛組建起來,不知如何做項目。想請老師指導一下我們如何利用自己的長處,做什麼樣的項目好。

  到大三了,組成團隊做項目,非常好的做法。不過從他的描述中,“有學圖像識别的,有學java的,有學c的,還有學網絡的”,我擔心他們已經過早地給自己貼上了标簽,這樣會限制住他們的發展空間。我在回複中表示了這樣的擔心,并提示了他們另外一種設計項目的思路,這樣前述的自編項目、參賽項目、開放平台中的項目、服務外包交易平台中的項目,統統可以納入考慮範圍。下面是我回複中的一部分:

  網絡可以算作是一個專業方向,圖像識别是一個研究方向,java和c,隻是程式設計語言層面的一個基礎,這隻是你們各自已經具備的能力中的一部分,不是你們未來的全部,我建議你們的學習還要從深度和廣度兩個方向分别進行下去,千萬不要讓現有的一點專長,封住了通向其他的可能的途徑。

  形成小團隊做點事情,他們想要利用好幾位同學現在的優勢去設計項目,這是“因人做項目”的思路。我建議了另外一個思路,要結合但也要先放下這些已有的基礎,標明一個項目以後,再确定大家怎麼分工,還需要補足各方面不具備的知識和技能。這是“因項目決定人如何參加”的思路。這符合工程中需求驅動的原則。在實踐中,也幾乎沒有“因為會做什麼就幹點什麼”的情況,而更多的是需要做什麼,安排人去做,能發揮的優勢最好,不懂的需要去自學,這也需要參與者在知識、能力上作必要的擴充。這種思路對學習階段的學生而言,顯然其價值更大。