二月 23, 2011
» 追求神乎其技的程式設計之道(番外篇)

一月 31, 2011
» 追求神乎其技的程式設計之道(十一)- 抽象化與命名

追求神乎其技的程式設計之道系列: 一 二 三 四 五 六 七 八 九 十 休眠已久的神乎其技系列又復活了!這篇文章其實寫很久了,只是一直斷斷續續到今天才完成它,久到讓很多人覺得這系列已經完結了…。但我想只要我還有在寫程式,這系列就永遠不會結束吧。 簡潔、彈性、效率 我一直覺得寫程式是一種藝術活動。程式語言是一種要求極度精確的表達方法,只要少打一個字母就可能造成完全不同的結果,但同時卻又不限制你要如何達到目標。 程式設計師有極大的自由來讓一個程式按照自己的想法「活起來」,不同人針對同樣的目標所寫的程式也一定不同。有人會用極簡主義來把變數命名為a、b、c,也有人會把用匈牙利命名法讓變數前後長出鬍子和尾巴;有人堅守DRY原則(Don’t repeat yourself),只要類似的程式出現兩次,就把他們抽象化成一個函數,也有人用copy/paste寫程式,不管怎麼page up或page down都一直看到一樣的東西還能泰然自若;有人寫程式把所有東西都塞在main裡面,也有人寫個Hello world就要搞一個class HelloWorld(雖然有些時候是被囉嗦的J語言強迫的…);有人沒聽過Big O也寫程式寫得很開心,但也有人嫌stdlib的qsort太慢硬是要自己重寫一個…。 儘管每個人的信仰和原則不同,但大體上程式藝術家也不過是在「簡潔」、「彈性」、「效率」這三大目標上進行一連串的取捨(trade-off)和最佳化。 「簡潔」的程式也「易讀」,沒有多餘的敘述或重複的程式碼,每個概念都只有唯一的一段碼在描述它。如果多了,就容易產生不一致的行為,如果少了,就是沒做到該做的事。有「彈性」的程式容易修改和擴充,只要在一個對的地方彈彈手指,不用因為老闆朝三暮四或是需求改變就得把整個程式重新翻修一次。有「效率」的程式會用最適合的資料結構存放每一樣資料,用最快的演算法做每一項必要的計算,並去除任何不必要的間接行為 (indirection)。 雖然目標很明確,但程式設計之所以像藝術就是因為大部分時候我們都沒辦法兼顧這三項目標:為了效率,可能就得犧牲彈性和簡潔;反過來說,為了彈性或簡潔,也常得犧牲效率作為代價。幸運的是,效率的追求在電腦硬體和編譯器技術的進步下已經不像20年前那麼重要,只要選對資料結構和演算法,幾乎已經沒有必要手動做低階的最佳化。除去效率之外,彈性和簡潔其實是比較容易同時達到而又不互相衝突的目標。要達到這目標,其中關鍵的能力就是今天的主題:「抽象化」(abstraction)。 最簡單但也是最難的事情 很多人沒聽過抽象化這個詞,甚至以為自己不會這件事,但其實從我們宣告第一個變數起,抽象化就已經開始了。 「這個變數要叫什麼名字?」 幫變數命名時,其實就是在賦予那個變數一個「意義」。人的記憶力有限,很難記住大量且沒有意義的資訊。但如果資訊有了一個固定且有邏輯的名字,我們也就有一個容易記憶的符號來代替整個複雜的概念。換句話說,我們可以把非常複雜的概念濃縮為一個容易處理和記憶的小單位,這個過程就叫做「抽象化」。 抽象化可以讓程式變得簡潔。好的程式設計師會習慣從重複的程式碼中找出共同或相似的部份,並且把這個部分提取出來變成一個更通用的概念。任何複雜的概念都可以被抽取出來替換成一個變數、一個函數、一個類別、一個模式、一個模組、甚至是一個系統,並加上適當的命名,就能讓這個程式「一看就懂」,任何註解都不需要寫。抽象化也能讓程式有彈性。經過適當抽象化的程式,每個概念都有一個獨立的「單位」(可能是變數、函數、類別、模組、或系統)可以表示,每個概念中包含的細節也被隱藏在適當的範圍內,不管要修改或擴充原本的程式都能讓需要碰觸的地方減到最少。 雖然抽象化是讓程式簡潔又有彈性的關鍵,但出乎意料的這是一個容易理解卻很難精通的能力。抽象化做得太少,程式會變得凌亂不堪,不同層級的概念和資訊互相交雜在一起,不僅讓程式變得難讀也難改。抽象化做得太多,就是所謂的over design,明明需求只有印一個Hello World,卻用了10種design patterns蓋起101大樓以應付根本就不會出現的「未來需求」。 抽象化這個主題可以講三天三夜講不完,但今天我只想提其中最簡單也最難的事:「命名」。 命名可以說是寫程式時最簡單但也是最難的事了。這件事沒什麼人會教,沒多少書會寫,因為這件事看起來非常容易,即使你把程式裡的變數照字母順序a, b, c, d, Continue reading

一月 30, 2010
» Sikuli帶來的意義與無限的潛力

這禮拜真是我人生中最瘋狂的一天了..。

自從Sikuli發表後,我本來還打算一封封回覆所有的問題,後來發現排山倒海而來的郵件和留言速度遠大過我能閱讀和回覆的量。前幾天我優先把Sikuli比較大的bug和一些平台問題修掉,昨天釋出了0.9.7讓各平台都提升到同樣的版本(只剩Linux還是沒有抓圖的快捷鍵了),整體運行的速度也提昇了不少,並且新增了一個.skl格式讓人能透過command line或double-click直接執行script。如果之前下載過舊版的朋友強烈建議升級到0.9.7。

修完緊急的bug後,我們會再陸續補上一些文件和教學,說明一些常見的問題要怎麼解決。例如說,畫面上有多個一樣的元件(像check box, radio button)要怎麼處理如果按特殊鍵或是在不同的鍵盤排列上使用(用dvorak的人還真不少,一堆人跟我說type()在dvorak上會有問題)..。

但這篇文章中我想談的不是被上萬人盯著的壓力,而是關於Sikuli能帶來的改變,以及未來的潛力。

有些人說Sikuli看起來只是另一個按鍵精靈或是AutoHotkey,但其實Sikuli還有許多在這個直觀意義之上的潛力我們沒直接說出來。

第一,Sikuli最重要的革命是程式碼的可讀性(readability)和易用性(usability)。把螢幕截圖直接放在程式碼裡面,讓人能直接「看到」他想控制的東西,這是從來沒人想過的事情。以往的方法,不管是透過應用程式自己的程式介面(API)或是透過XPath拿到網頁裡的某個元件,都是只有程式設計師才能寫、才能讀懂的神秘外星語言。機器喜歡精確的語言,人類花越多力氣把事情描述的越清楚,機器就越容易讀懂。

可是,有沒有人想過,人類發明這麼多程式語言來操控電腦,究竟是便利了人類還是便利了電腦?現在我們每天用的程式語言,不管是C++、Java、C#、Python、Javascript..都是只有程式設計師才能寫才能讀的語言。更諷刺的是,這些「現代」語言跟五十年前就有的LISP、Fortran本質上並沒有什麼不同,一樣都是純文字,一樣要求精確嚴謹的語法,一樣是架在百層高塔的系統架構上。即使是訓練有素的程式設計師,要寫程式做些有用的事情也都得先翻翻充滿黑話的說明文件,看看需要的功能對應到什麼函式,運氣不好可能還得學個COM+之類的鬼東西才能使用。

如同我在追求神乎其技的程式設計之道(十):程式設計師的生產力之謎中提過的一樣,即使同為程式設計師,運用電腦的效率依然會有數十倍甚至百倍的差距。如果每天都要按一百個按鈕,程式設計師可以找到適合的命令列工具使用,或是自己寫程式呼叫應用程式提供的函式,就可以用一個按鍵取代這一百個按鈕。那完全不懂程式的一般使用者呢?恐怕只能兩手一攤任由別人寫好的軟體擺佈。也就是說,即使一個人掌控了鍵盤和滑鼠,但實際上卻是被別人的軟體限制住,如此使用電腦其實完全沒有自由可言。

Sikuli的革命把寫程式的門檻降低了,人們和系統或應用程式溝通不再需要讀用黑話寫的文件,也不用搞懂底層的架構是怎麼做的,只要把平常使用鍵盤滑鼠的方式,再加上想控制目標的螢幕截圖,就可以輕易寫成能自動執行的程式。

Sikuli Script範例

除了好寫外,任何人看程式和圖都能很容易讀懂程式到底做了什麼事,於是Sikuli很自然就能成為一種寫教學文件的最佳媒介。以往的教學文件常常step by step列出使用者要做的事,加上使用者應該要看到的畫面,很巧的是這兩者Sikuli script都有。但比傳統的文字描述更好的是,只要把Sikuli的指令混用在文件中,或是透過簡單的對應把文字描述轉成script,這樣一份文件不只人能看懂,連電腦都能執行這些步驟並且一步步告訴你要按的按鈕在哪裡。

第二,除了直觀上的GUI自動化外,其實Sikuli更重要的意義是提供了一種把使用者操作UI的互動過程記錄下來的新方法。以程式設計師的黑話來說,這可以說是GUI操作過程的serialization,如果用一般人的方法說,這就是把人機互動過程「數位化」的一種方法。

電腦發展的過程中,一條必經之路就是把人類周遭的一切資訊全部數位化。一旦資訊被數位化,就可以輕易儲存在電腦裡,或是透過網路分享給別人,電腦科學家也才能發展更多方法來處理、分析、運用這些資料。在21世紀的今天,人們把聲音、影像、文字全都數位化了,所以我們可以輕易的複製、傳播、使用這些資訊。但在人們如此依賴電腦的今天,人和電腦的互動過程其實一直沒有一個好方法可以記錄,所以更別提要複製或是分享這種互動過程。

而Sikuli在這個人機互動領域開了一條全新的道路,這也是為什麼Sikuli的論文是出現在「User Interface Software and Technology」的會議上,而不是在討論程式語言的會議上。

人機互動的過程一旦能被一個標準的方法記錄下來,接著就能複製,就能分享,就能讓電腦自動執行或是演算這些過程。未來的應用方式有千百種,唯一的限制只是看我們的想像力而已。

第三,Sikuli把電腦視覺的研究領域,從真實世界延伸到電腦的桌面上。這點說起來真是很有趣,電腦視覺的研究人員數十年來嘗試想讓電腦能像人一樣「看」這個「真實世界」,可以像人一樣認得別人的臉,或是認得馬路長什麼樣才能讓電腦自動開車,但卻沒什麼人想到讓電腦「看」電腦自己輸出的畫面。在技術上來說,電腦螢幕上的資訊全都是電腦自己產生出來的,沒有光影問題,沒有角度問題,辨識上的難度遠低於真實世界所需的難度。以現在的電腦視覺技術來說,辨識螢幕上的東西簡直可以說是殺雞用牛刀。

Sikuli把電腦視覺和人機介面兩個研究領域打通了,有很多古老的問題(例如OCR,文字辨識)在真實世界很難解決,但在電腦桌面上卻可能可以發展出又快又準確的方法。Sikuli也可能激發更多人把電腦視覺應用到軟體介面上的創意,讓使用者介面不只是簡單使用,也能讓每個人能真正隨心所欲的操控電腦。

第四,建立在Java平台上並且open source的Sikuli,很有潛力能讓每個人都能打造給自己的專屬程式。

Sikuli不只是提供了一堆自動按滑鼠和按鍵的指令集而已,每一個Sikuli script都是一個和Python語法相容的程式。這意味著你可以使用任何的Python語法,不管是迴圈、if、定義function、或是定義class,每一個Sikuli script都是一個真正的Python程式(嚴格來說,應該是Jython,但這中間的差別並不太重要)。除此之外,Sikuli核心是跑在Java平台上,所以可以輕易的使用任何Java的函式庫。例如說,你可以用swing建立一個新的視窗包含了兩個按鈕,按下第一個就用Sikuli執行每天上班前的例行工作,而按下第二個紐則執行下班前的例行工作。會寫程式的人可以輕易混用Sikuli和現有的函式庫,把Sikuli當成和系統或其他應用程式溝通的媒介,並在上層建立自己的新介面。也就是說,這就是桌面環境的mashup,可能的應用是無限大。

雖然不懂程式設計的人,難以撰寫複雜的GUI程式或是資料處理。但Sikuli結合了現有的平台並且open source,這樣的好處是會有來自世界各地有閒有能力的人幫忙讓Sikuli變得更簡單更好用,並結合其他的程式語言或是函式庫讓寫程式的整體門檻大大降低。

雖說Sikuli現在還不是那麼完美,但我相信open source會加快Sikuli的發展,讓更多有興趣的人進來幫忙。很多技術上的問題其實都好解決,例如有人問到是不是桌面換個skin後script就廢了,或是能不能在背景執行script。這些問題其實都有好幾種可能的答案可以解決,只是有沒有必要現在就做而已。技術問題向來都不是能阻擋我的絆腳石,真正困難的只有突破自身創意和想像力的界線而已。

每個人使用電腦的方法都不同,軟體公司設計的軟體也只能按照大部分使用者的需求和習慣所設計。但不論有多少功能,總是不可能涵蓋到每個人的大大小小需求。讓每個人都能寫程式(不論他們是不是知道他們正在寫程式)是我一心嚮往的目標之一,或者說是我希望每個人都能100%按照自己的意願花最少力氣完成最多工作。但在今天的電腦環境上,不會寫程式就有太多事都無法做到,即使會寫程式的人,也不見得願意花那麼多力氣去研究讓自己未來更省力的方法。

這個問題的癥結不在於使用的人太懶惰或是不夠聰明,而是電腦太難用。一個人得經歷幾年的訓練才能熟悉這種用程式「掌控」電腦的感覺,實在太不合理。或許沒有人想研究讓寫程式變得更簡單是因為怕丟了自己的飯碗,但我偏偏就覺得每個人應該要有聰明使用自己工具的自由,而不是反過來被工具限制了自己。所以,我希望Sikuli能讓更多人把使用電腦的自由搶回自己手中,而不是被軟體工程師們掐住脖子動彈不得。

寫到最後,能參與Sikuli這個project其實最需要感謝的人是和我合作的Tom Yeh,在我進MIT前他就在跟我老闆Rob Miller討論用螢幕截圖來搜尋文件的可能性,所以其實在我還在當兵時我們就已經搭上線開始合作了。後來我到了MIT後,一連串的討論就激發出許許多多混合螢幕截圖和電腦視覺所產生的點子,其中第一個成果就是現在的Sikuli。

Sikuli Script只是這一串研究的開端和基石,在這之上其實我們還做了很多東西。例如說我們已經有一個能錄製螢幕和使用者動作的程式,可以把使用者的動作自動轉換成Sikuli Script,也就是說使用者一行程式都不用寫,只要把想做的步驟做一次,程式碼和螢幕截圖就會自動產生出來讓你修改或直接使用。用這個錄製程式,我們可以輕易的在現有的GUI系統上觀看全系統的操作歷史,甚至是自動redo某一部分操作。有這些系統做基礎,我們能做的事情實在太多了,我只怕自己時間和能力有限,沒辦法把所有的點子都做出來。所以,這也是我們把Sikuli公開的目的,希望開放這塊寶石後,能有更多人發揮想像力發明出更有趣更有用的東西來,並徹底打破現今使用電腦的方法,一起來改變世界吧!


十二月 23, 2009
» 追求神乎其技的程式設計之道(十)

追求神乎其技的程式設計之道系列:

程式設計師的生產力之謎

很多人都聽說過,同樣是寫程式,一個頂尖程式設計師和一個普通程式設計師之間的生產力可以有十倍甚至百倍的差距。這是其他行業很少見到的現象,於是不禁令人納悶,為什麼會這樣呢?

其實單就解決同一個問題的coding能力來說,差別還不至於這麼巨大。我在高中參加奧林匹亞和大學參加ACM比賽時,已經遇過全世界數一數二的coding高手,這些人每天都在練習解題和實做各種複雜的演算法和資料結構,隨便說一個演算法都能直接把code透過肌肉記憶反射出來給你。他們能在數十分鐘內想出高效率的演算法並寫成程式解決一個複雜的難題,即使我高中時已經花了一整年在訓練,依然不是他們的對手。這些人除了絕頂聰明外,每個人在高中時少說也寫過至少十萬行的code。但我發現,即使他們能解一般人解不出來的問題,打字快到鍵盤會冒煙,在做一個大系統時,這方面的差距還不一定會如此明顯。

所以我想,除了先天的智商和後天對於寫程式的熟悉度與經驗外,一定還有什麼因素造成巨大的生產力差異。

我後來發現,程式設計師和其他行業有個很大的不同點:一般行業只能在現有的工具上磨練自身的技術,但程式設計師除了磨練技術外,還可以獨自創造、修改自己使用的工具;換句話說,程式設計師的能力就是在電腦上創作出更好的軟體,不但能便利他人,也同時能增進自身使用電腦的工作效率。舉例來說,理髮師能磨練使用剪刀和設計髮型的技術,但理髮師並不知道怎麼發明及製造新的剪刀讓自己更有效率的剪頭髮;電機、化工、土木工程師要設計IC、化學製程、建築結構,但他們得依賴電腦軟體才能設計,並且靠許多大型機器和工具才能生產,即使想提昇自身的工作效率,也不是自己一個人想做就能辦到的。但軟體工程師就不同了,我們只靠一台電腦就能工作,我們的工具是軟體,我們的產出也是軟體,我們的所依賴的一切都是軟體,只要自己願意投入心力,隨時可以修改每天使用的工具和系統讓自己更有效率的工作。

這一點可以說是程式設計師的先天優勢,也是頂尖的程式設計師和普通程式設計師的生產力差距的關鍵。

Eat Our Own Dog Food

我發現厲害的程式設計師常有種共同特質:寫工具給自己用,解決自己日常工作碰到的問題或改善自己的工作效率。英文有句話叫eat one’s own dog food,字面上意思是說一家公司應該要吃自己做出來的狗食,實際上是引申為一家公司應該要在內部用自己的產品解決自身的問題,才能發現真正的問題,並且說服人這東西真的很實用。Google是奉行「吃狗食」原則的典型公司,Google內部有一個獨立的搜尋引擎搜尋公司內部網路的資料,新技術也都能在上面先行測試;Google內有獨立的gmail、google docs,都在對外公開前先讓內部的人實際用上好一陣子;Google甚至做了自己的Linux distribution給工程師用、自己的compiler、自己的瀏覽器…。

會這樣做的動機其實很簡單:如果我每天都要花10分鐘手動做同樣的事情無數次,為什麼不花一個小時寫個程式把這件事情自動化,以後可以省下更多時間做點真正有意義的事;如果我每天都要用這個彆腳的軟體,忍受他設計上的不便,為什麼不想法辦改善它或自己做一個呢?

程式設計師每天都用電腦在工作,尤其做一個系統時常常需要花時間做一些瑣碎的工作,像是編輯設定檔、把一些檔案搬來搬去、重開伺服器、清除暫存檔…等等。這些工作通常不難,但可能步驟繁雜,或是每個步驟都要等待它慢慢完成,累積起來每天就很容易浪費許多時間手動做這些無趣的事情上。

出於「懶惰」的美德,頂尖的程式設計師工作時想的不只有產出最終產品就好,而是如何花最少力氣最少時間把產品做到最好。但這件事說來容易做來難,能不能實行往往跟程式設計師工作的系統環境有很大關係。

UNIX是Programmer的天堂

如果要說我高中時期最大的收穫是什麼,我想有兩件事的重要程度不相上下:一是我確認了自己對寫程式的熱情,並且花了足夠多時間打好基礎;二是我在這段時間內摸熟了Linux,並且愛上了UNIX世界工作的哲學。

UNIX可以說是一個非常適合程式設計師工作的天堂,UNIX的工作哲學(泛指所有UNIX like的系統,像是Linux、BSD、Mac OS X..等等)是提供許多小工具,每樣小工具只做一件事,使用者可以合併使用多種工具完成複雜的工作。此外,UNIX的工具都是以command line為介面,非常適合寫script做自動化的操作。而在Windows的世界中則完全不同,Windows上的軟體傾向於提供整合式的GUI環境,把所有相關或可能會用到的功能全都一手包下,雖然方便使用者,可以點幾個按鈕就自動做完所有事情,但對於程式設計師來說其實不是一件好事。

以寫程式的工具來說,在UNIX下可以選自己喜歡的文字編輯器,不管是Vim或Emacs,也可以選自己喜歡的compiler,可以用makefile加上command line工具自動化整個程式編譯、測試、執行的流程,並且隨時都可以加入shell script或是perl script把開發流程中瑣碎的工作一併自動處理,不管需求有多麼特別,這種完全自訂的流程彈性可以說是無限大。

但在Windows環境,主流開發軟體以整合開發環境(IDE)為主,像Visual studio這種無所不包的巨獸,對於新手來說按一個鍵就能搞定一切,不用去想底下的細節,實在方便得很。可是依賴於IDE卻有個致命缺點:只要是IDE的設計者一開始沒考慮到的事,你就沒辦法做。

舉例來說,早期visual studio不支援版本控制系統(version control system)時,程式設計師就很難把版本控制整合到開發過程中(例如說在編譯成功時自動commit、或是自動加入新的原始碼…);即使到現在visual studio已經支援了一些常見的版本控制系統,用它的人依然要看這個支援的清單包含哪些系統,如果是想用新的系統,或是用非標準的方法使用這些系統,恐怕只能遺憾的兩手一攤什麼事也不能做。有些IDE雖然有提供plugin功能(像是Eclipse),但其實也沒好到哪,因為IDE龐大無比,寫plugin的難度和所需時間遠高於使用者手動完成這些日常瑣事所花的力氣,自然不會有多少人願意去做。

簡單來說,用IDE的話,程式設計師沒辦法掌控自己用的工具,也沒辦法改善開發流程中的問題,開發效率的極限很自然會被IDE限制住。但UNIX上的環境就不一樣了,採用多種工具的組合讓自己能掌控開發流程中每個步驟。因為每個步驟和所用的工具都是透明的,只要有需求或是發現哪裡可以改善,很容易可以從滿手的工具中抓出一個來解決,或是寫個迷你的script來自動處理較複雜的工作。即使哪天有新的小工具出現(例如說一個新的版本控制系統),因為每個小工具都是獨立運作,靠程式設計師自行整合的,所以也比較容易把舊的「零件」替換掉。除此之外,open source興起後,帶有原始碼的系統更帶給程式設計師一個「完全控制」的機會,除了能替換零件外,有能力的人還能直接對零件本身做修改以符合自己的需求。種種因素加起來,讓程式設計師不再被單一個工具能力所限制,而是手中握有無數可以自由運用的籌碼,唯一的限制只有自身的創意和熱情而已。

狗食是生產力的關鍵

我一直覺得念資訊系的人不應該依賴於用IDE寫程式,當然這並不只是因為「用command line才是真男人」這種geeky的理念,而是念資訊系的應該要能擅長於「把電腦能做的事交給電腦做」。今日的軟體介面大多是以多數的日常使用者為目標,雖然方便操作,但設計者不可能把所有使用者可能會想做的工作列表做出各種排列組合放在選單裡。如果是設計者沒考慮到的功能,使用者往往也只能手動慢慢處理。但程式設計師和一般使用者是不同的,程式設計師的能力就是和電腦溝通,讓電腦用我們想要的方式幫我們完成工作。如果我每天要重複按照順序按100個不同的按鈕,為什麼不寫個程式自動按這100個按鈕?

我跟一些人聊過這個想法,但典型的反應是「正事都做不完了,哪裡有時間先做一個工具?」

但我覺得很諷刺的是,正是因為抱持這種觀念才會讓生產力低落,所以讓正事做不完,時間越緊迫就越不敢花時間做這種沒有立即產出的事情。相反地,如果在意識到自己已經三番兩次手動重複執行同樣的冗長工作時,就應該靜下來好好想想是不是有什麼辦法可以讓電腦來做這些事,只要常有這種想法,寫這些script和小工具所節省下來的時間和自己得到的經驗是一輩子都用得上的。

現在有許多open source軟體一開始都只是程式設計師為了方便自己所寫的小工具,在做正事的時候撥出時間先做好工具,然後不知不覺可能就成了偉大的軟體。最有名的例子是Knuth為了寫他的The Art Of Computer Programming,他竟然先重頭自己打造一個針對數學環境設計的排版系統,最後就成了著名的TeX。他不但完成了電腦科學界的聖經,還「順便」完成了一個經典的排版系統並分享給全世界使用。

如果持續抱持著這種態度寫程式,說不定你我也能成為下一個Knuth呢? (笑)

(待續)


» 追求神乎其技的程式設計之道(九)

追求神乎其技的程式設計之道系列:

最近被很多人提醒這個神乎其技系列停在第八集很久了…(汗)。其實這集草稿已經存很久了,今天總算決定要把它告一段落後貼出來。

先來個題外話,台灣最近遭受莫拉克颱風帶來的巨大災難之苦,雖然我人不在台灣能幫上的忙很小,但還是希望災區的所有人都能平安度過這次災難。

高中到大學

春天的國際科展結束後,我的高中生活也即將劃下句點。回顧高中三年,從校內的資訊比賽一路走到奧林匹亞的國際舞台,在保送大學資格的保護下,到高三又誤打誤撞變成國際科展的代表。雖然從結果看來一切都是如此美好,但在我剛升上高中時,沒有人知道未來會發生什麼事。我爸媽只想要我好好唸書,考上好大學;而我對學校教的科目早已失去興趣,每天都只想泡在電腦前探索這個神秘盒子的內部。於是每次考試結束,家裡就會因為我的爛成績而引發一次大戰,我爸媽也會一再的限制我坐在電腦前的時間。

就像七龍珠裡的標準情節一樣,悟空總是可以和敵人奮戰到垂死邊緣才爆發出最後一擊取得勝利,我總覺得在逆境時才能看出一個人真正的意志力和求生能力。雖然我爸媽能不斷縮減我能用電腦的時間,但他們可沒辦法限制我在學校做什麼或是面對課本時心裡到底在想些什麼。我還記得高一時,我天天都帶著Introduction To Algorithms(當時還是第一版,很多人叫它白皮書)到學校,不管上課時老師講得多麼口沫橫飛或是下課同學們玩得多開心,我都是看我自己的書。有時碰上管得嚴的老師,我就不看書開始想ACM的題目,用筆在白紙上寫code。我還記得當時為了手邊要隨時有充裕的題目可以想,我把ACM online judge上所有的題目全都印了出來放在一個資料夾裡隨時帶在身邊。

現在想想我那時瘋狂的程度真是難以想像,我當時心思幾乎完全沒放在學校課業上,就連體育課我都躲在樹蔭下想題目的解法。於是到了要升高二選類組時,家裡又爆發了第N次的世界大戰。

還記得升高二前有個考資優班的機會,我爸媽非常想要我去考考看,但我死都不答應。我很堅持的原因是,中一中的數理資優班非常奇怪,進去後就自動變成第三類組,也就是要多念一科生物,但我已經很確定未來我只想念資訊相關的科系,所以我只想選二類,不想浪費時間多念一科生物。就為了這件事,爭執的戰火延伸到我花太多時間在電腦上未來會考不上好學校之類的陳腔濫調上。

台灣父母似乎都想要孩子選擇他們覺得的安全、穩定的路,但我大概天生叛逆了點,說什麼都只想堅持自己的路。不管成功的可能性有多小,或是風險有多大,我覺得我就是應該照著心中的聲音去走。跟他們吵了一陣子後,我決定跟他們立下一個約定:讓我完全自由到高二,如果我沒辦法在資訊比賽拿到夠好的成績足以保送大學,那我到聯考前就都不碰電腦,即使我考不上大學也是我自己的決定所造成的。

從此以後,我就更認真的拼命研究演算法,研究歷年來所有大大小小資訊比賽的題目,只要我醒著的時間,腦袋就全速運轉放在這些東西上。雖然理論上我應該是背水一戰,但那時心裡其實沒有太大壓力,反而覺得可以每天都在玩自己有興趣的東西很幸福很開心,如果比賽結果不好,那可能只是說明我沒有這個天份和這個命而已。

現在回想起來,我覺得當時的我真是不怕死到了極點。要靠資訊比賽保送,至少也要進入奧林匹亞的培訓營,並成為留到第二階段的最後十人之一才有機會(有機會的意思是大學有可能會拒收…)。簡單的說就是實力大概要在全國高中生的前十名就是了。

我想我當時一定沒有想這麼多,只傻傻的做自己想做的事,所以才會這麼有勇氣立下聯考前都不碰電腦的可怕約定。還好我運氣很好,上了高二後從第一場校內賽就把我累積一年的力量爆發出來,就這樣一路打進培訓營甚至還選上國手。

順利拿到保送資格後,父母鬆了一口氣,於是就完全放任我花更多時間泡在電腦裡了。到高三時,我誤打誤撞說要參加國際科展,於是就有了正當理由請公假,各科老師對我的缺席也見怪不怪。高三我幾乎每天都待在教官室裡玩Linux、架各種系統和server來玩,雖說要做科展,但其實也是對什麼有興趣就玩什麼。(可能很多人覺得奇怪,為什麼會待在教官室… 因為教官室是少數有電腦有網路,我又能自由進出的地方。再加上當時有教官找我幫忙做網站,所以….)

到了要畢業的時候,我才發現我高三幾乎都沒踏進教室過,班上的同學我也幾乎都不認識。雖然在自己的世界裡過得很開心,但要畢業時才發現我的高中生活和其他人都不一樣。班上老師們對我也頗有微詞,所以畢業前我還碰到了一個可怕的畢業危機:我高三的學科被當了九科……。(現在想起來還真難想像,到底有哪九科啊orz…)

這件事大概是我一帆風順的高中生活中最驚悚的一件事了。雖然台大已經張開手等我進去,但要是高中不能畢業,那我不就變成比櫻木花道還悲慘的笑話了嗎…。(註:櫻木花道在全國大賽前發現被當太多科無法參賽,所以只好閉關唸書準備補考,當然最後還是順利過關去參賽,不然灌籃高手就畫不下去了。)漫畫中的主角當然不會被要補考這種小事打倒,但現實生活中誰知道呢… orz

在畢業前遭受到如此巨大的危機,實在完全出乎我的意料之外。還好當時帶我們參加比賽的指導老師非常挺我,幫我跟各科老師要一個補考的機會。學校也很好心不打算找我麻煩,就讓我把考卷帶回家寫一天。隔天交出去後我就沒再得知過關於成績的事,我甚至不知道我畢業時每一科的成績,但總之我還是拿到畢業證書了(汗)。

回想起年輕時的瘋狂,真是覺得很不可思議。如果我當時沒有堅持自己的想法,而依照爸媽的意思「好好唸書」,我想現在的我一定過著完全不同的人生,至少不太可能憑聯考進入台大資訊系,而現在也不會在MIT了..。

(待續)

十二月 16, 2009
» 給程式設計師的Vim入門圖解說明

12-09 Update: The English version of Vim Visual Cheat Sheet is also available. PNG, PDF)

(更新: 在圖內加入基本指令表和說明以及PDF版,方便大家列印出來貼在牆上隨時查看。)

剛在寫那篇關於vi和文字編輯器的文章時,本來想附上一個vim的超簡單入門連結,但找了一下都沒有很滿意的,所以決定自己動手先來畫個入門用的說明圖。

vim-cheat-sheet-full
PDF版下載

vim-cheat-sheet-diagram

這個圖把vim中基本的移動方法都畫上去了,為了方便programmer,特別列出了很多只有寫程式才會用的按鍵。除了這些以外,其實還有一些好用的東西我還沒想到怎麼畫上去比較好(像是tags、沒有標準快速鍵的tab、man..),如果大家有idea歡迎提供。

這些圖示依照移動的單位大小分為以下幾個種類,分別用不同顏色標示:
(注意,這不是完整的vim快速鍵列表,只是我覺得比較常用的鍵而已。)

字元(character)
h
j
k
l
單字(word)
w
下一個word
W
下一個word(跳過標點符號)
b
前一個word
e
跳到目前word的尾端
行(line)
0
跳到目前行的開頭
^
跳到目前行第一個非空白字元
$
跳到行尾
段落(paragraph)、區塊(block)
{
上一段(以空白行分隔)

">
">}
下一段(以空白行分隔)

">
">[{
跳到目前區塊開頭

">
">]}
跳到目前區塊結尾

">
">%
跳到目前對應的括號上(適用各種括號,有設定好的話連HTML tag都能跳)
螢幕(screen)、絕對位置
H
螢幕頂端
M
螢幕中間
L
螢幕底部
:x
xG
跳到第x行(x是行號)
搜尋(search)
/xxxx
搜尋xxxx
#
往前搜尋目前游標所在的字(word)
*
往後搜尋目前游標所在的字(word)
fx
在目前行往後搜尋字元x
gd
跳到目前游標所在的字(word)的定義位置(寫程式用, 跳到定義變數/函式的地方)
分割視窗
:split
分割視窗(可加檔名順便開啟另一檔案)
:diffsplit xxx
以分割視窗和檔案xxx做比較(diff)
Ctrl-W p
跳到前一個分割視窗(在兩個分割窗來回切換)
Ctrl-W j
跳到下面的分割窗
Ctrl-W h
跳到左邊的分割窗
Ctrl-W k
跳到上面的分割窗
Ctrl-W l
跳到右邊的分割窗
自動補齊(Auto-completion) (在Insert Mode中使用)
Ctrl-N
自動補齊檔案內的下一個可能字(word)
Ctrl-P
自動補齊檔案內的上一個可能字(word)
Ctrl-X Ctrl-F
自動補齊檔名


八月 14, 2009
» 追求神乎其技的程式設計之道(八)

追求神乎其技的程式設計之道系列:

第八集終於寫完了…。雖然我寒假過得很輕鬆悠閒,但不知道為什麼人就是會在很閒的時候不做平常一直說沒空做的事,然後硬是要在很多作業和工作時開始寫blog….。雖然開學後又開始變忙了,但我到目前還是每個禮拜都跑去滑雪,這樣看來這一系列最後突然會變成追求神乎其技的滑雪之道也說不一定XD

前言夠多了,本集將繼續我在高三時朦朧無知的學習故事…。

Intel ISEF國際科展

第五集裡提到我一直以來都夢想著讓電腦學會自己寫程式。就在我把這個想法的雛型用基因演算法實做出來後,沒想到竟然真的看到了一點結果,電腦真的能透過基因演算法來產生出一個能夠正確運作的程式!

在高三時,已經取得保送資格的我對學校的課業時在沒什麼興趣,於是我想閒著也是閒著,乾脆就把這個點子拿去參加科展看看,這樣一來我就又有理由可以請公假了(笑)。當時似乎是因為已經來不及報名全國科展了,所以我就跑去報名了國際科展,但那時我其實完全不知道這兩種科展有什麼差別。後來查了一下才知道,原來台灣的國際科展除了是一種比賽外,主要的目的其實是要選出代表去參加其他國家(如美國、法國、加拿大…)的科展活動;而一般的全國科展就是一個區域至全國性的展覽兼比賽,在全國選出前幾名後就結束了。

2001年時,那時科教館還在建中對面,那也是我第一次踏進科教館的大門。在展場內把自己的海報貼上看板後,我就到處逛逛欣賞別人的作品。因為資訊科在高中不是正式科目,參加的人比起其他科來說少了許多,但其中還是有些非常驚人的作品出現。當時有個建中的學弟Eric,他寫了一個用類神經網路辨識並動態追蹤影像中人眼位置的程式,於是他就用了個普通的攝影機加上這程式,就變成可以用眼睛控制滑鼠游標的神奇裝置。

除了Eric的作品外,其他的作品看起來大多只是某種現有產品或課本上習題的複製品,並沒有什麼令人特別印象深刻的東西出現。說起來這其實也不奇怪,因為在高中階段要自己學好一個程式語言其實並不容易,在基礎還未打穩前,即使有再多創意也無法發揮出來。而很可惜的是,很多人上了大學終於學會寫程式後,創意和熱情也被磨損的差不多了;而畢業後雖然已經有了基本功力,但卻只能照著老闆開的規格刻畫死板的功能與介面,與其說是程式設計師不如說是程式工匠。

我覺得台灣人的能力並不差,但社會中卻瀰漫著一股抄襲與仿冒的氣息,從最近的酪梨壽司事件(相關抄襲事件還可參考MMDays的整理),可以看出抄襲風氣在台灣並不只是小時候在學校抄抄作業而已;媒體工作者在報導中任意抄襲及轉載是種不尊重自己專業的表現,不但隱含著一種應付了事的心態,更代表著這些人對於自己的工作沒有熱情,更沒有著一點堅持。如果要說我在美國看到這邊和台灣有什麼最大的不同,我想關鍵的差異就在對自己的工作有沒有熱情和堅持而已了。

在評審的過程中,有兩個教授一起來聽我介紹我的作品。因為我沒有任何參加科展的經驗,也沒做什麼講稿或準備就去了,一切只能靠臨場發揮,還好教授們還蠻喜歡我的作品,一來一往的討論之下才讓我不至於太緊張而說不出話來。

自己的介紹結束後,終於鬆了一口氣,教授們對我的作品似乎感到非常新奇和有興趣,後來還問了我「如果再給你兩個月,你能做出更好的結果嗎?」這問題聽起來像是要給我個機會再繼續深入研究下去,難道是意味著要選我當代表嗎?當時我對於得獎其實是沒什麼興趣和期望的,只是想看看別人對這個東西的意見,但如果有人喜歡當然是很棒的事情。這問題無非是給我挑戰的機會,我腦中還有很多改進的想法,如果有更多時間,一定還能做出更棒的結果。所以,我就毫不猶豫的就回答了:「可以,當然可以!」

到了頒獎典禮時,司儀一一宣佈每個學科的獲獎人以及之後要代表台灣去哪個國家參展,同時也頒發一些企業贊助的特別獎。我原本一直以為Eric的作品應該是穩拿第一的,畢竟相較之下我的作品並不夠成熟和完整,甚至連個能稱上科學實驗後的結果都沒有。但這個新奇的點子威力還是很大,我完全沒預料到無心插柳參加科展竟然讓我拿到了Intel頒發的電腦科學最佳獎,並且還選上了美國代表,之後可以代表台灣去美國參加Intel主辦的國際科學暨工程展(ISEF, International Science and Engineering Fair)。

程式設計之內功心法

得獎當然很開心,這是對於我這個想法和努力的肯定,但隨之而來的也是一股很大的壓力。我得代表台灣站出去,到美國跟來自世界各地的教授、學者、參展代表用英文介紹我的作品,那不能像在台灣這樣輕輕鬆鬆跟教授聊聊天就好,我要用不熟悉的語言跟不熟悉的外國人介紹我這個只花一兩個月做出來的雛型作品… 光想到這個背都涼了。

選上科展代表跟選上奧林匹亞國手是完全不同的感覺。奧林匹亞對我來說是個已經努力很久的目標,我很清楚自己的實力有多少,我對自己花了將近一年所打下的基礎很有信心,而且我對比賽本身已經非常了解,出國比賽不過就是做我已經很擅長的事情而已,一點都不需要害怕和擔心;但選上科展代表真的完全是意料之外的事情,我自覺還沒有花足夠的功夫在這問題上研究,就像一個腳底有油漆還到處亂跑的小鬼,糊里糊塗的鬼畫符被長輩當成畢卡索的作品一樣。

驚恐之餘,我還是警覺到我得開始做很多事來讓我能充滿信心出國去參展。我得趕快把英文練好,至少要能流利的跟人介紹作品,還要能回答各種問題;我還得了解Intel ISEF到底在幹麼,參展代表要做些什麼事;最重要的是還得繼續在這個作品上做更多研究,看能不能在兩個月內做出更好的結果。

參加科展讓我意外領悟到一些事,我發現我高一開始花了一年多投入資訊比賽所得到的並不只是那塊獎牌與一堆獎狀,在練習的過程中,我把台中圖書館所能借到的演算法和資料結構的書全都看過了,就連冼鏡光當初在微電腦傳真雜誌上的專欄也被我從圖書館地下室的陳年庫藏中挖出來,一本一本的影印裝訂起來。我收集了我所能找到的所有大大小小資訊比賽歷年來的題目,加上當時ACM Online Judge上做過的四百多題,我當時參加比賽幾乎都是看完題目馬上就能想完所有可行的演算法和所搭配的資料結構,並用直覺挑出能最快寫出來且又最有效率的解法。除了解決問題的方法外,我也能輕易的把任何想法寫成程式碼,只要能把過程講出來,就能毫不猶豫寫出code來。

這個花了一年多練出來的功夫,讓我到今天都受用無窮。這種感覺就像唸完九陽真經後內力大幅提昇,之後不管再練什麼武功都是易如反掌。在高中時,我改以Linux作為我主要的工作環境,同時也幫中一中架起BBS,並自己架了web server、mail server來玩玩。這些系統底層的功夫乍看之下跟寫程式沒什麼關係,但我後來發現要做各種能在現實生活中應用的軟體系統,總是會碰到這些現有系統的細節問題。

我以前在大學時常觀察別人的project會碰到什麼阻礙,而開發不順利的原因幾乎都是被一些瑣碎的細節所絆住而導致嚴重的進度落後。這些細節都是些小事,甚至跟寫程式沒有直接相關,但總是會讓人陷於泥沼之中。舉一個簡單的例子,假設要在Linux上寫程式需要用到某個library,動手前得先安裝一下。這個看似簡單的安裝其實牽扯到許多瑣碎的細節,像是:distro有沒有提供package可以直接透過網路安裝? 沒有的話就要自己編譯,那就得知道如何用configure、make等工具;編譯中可能還會發生缺少其他相依的工具或package的情形,這時還要能從錯誤訊息中看出到底少了什麼東西,並且想辦法先安裝起來…。這些事情跟寫程式的理念其實一點關係都沒有,但很殘酷的是,有許多人都會被這種細節所絆倒而中途放棄。

紮實的內功和熟悉系統底層的基本武功帶給我非常有效率的實做能力,我可以在想出新的idea的同時馬上勾勒出實做上大大小小的細節;我可以很快設計出核心的高效率演算法,也知道系統各部份的功能有什麼現有的library或系統可以利用,這兩種能力讓我能快速完成prototype。我只怕沒有夠好的點子,完全不會擔心是不是真的能做得出來。

不久前有位數字先生開了一個程式速成班,號稱能在4堂課內教會web程式的開發,只要帶著點子過去就能在上完課後開始創業。我覺得學寫程式本身其實不用很久,我也曾教過一個12歲的小朋友寫程式,兩個禮拜總共約十小時就足夠讓他掌握基本的程式邏輯概念,包括變數、迴圈、if、陣列、抽象化..。但認真說起來這些東西只是基礎內功,有了內功後自己還是要花很多時間去學相關的底層武功,像是要做web程式還得摸熟web server的架設和管理、UINX的shell和系統管理、各種相關網路傳輸協定、資料庫的使用和管理、前端的HTML和CSS設計….。光web程式所牽扯到的實做細節就多如牛毛,如果要在完全沒有穩固基礎的情況下同時學這麼多東西,只要一旦出現問題,一個對系統從上到下每個環節都不熟悉的人是完全沒辦法鎖定問題發生點的。而debug的基本概念就是要先鎖定問題發生的地方,要做到這件事的先決條件就是要很有信心的先排除一些不可能的地方,再做些假設並驗證假設是否成立來判斷可能問題。如果對每個環節都沒有充分的經驗,我不覺得這樣的人有能力清楚的定位出問題所在,更別提是否能獨力完成一個像樣的完整系統。

每個人都聽過成功是一分的天才加上九十九分的努力,如果說天才是能想出絕妙idea的能力,那我覺得還有個關鍵是,要在有點子前先做過夠多的努力打好基礎,等到靈光一現時才能把握住機會馬上實現它。如果等到一分的天才出現時,才準備開始做九十九分的努力,那很容易就會被許多基礎能力不足所帶來的挫折感和障礙所壓垮。

(待續)

十二月 27, 2008
» 追求神乎其技的程式設計之道(六)

追求神乎其技的程式設計之道系列:

最近新玩具太多,差點讓我的blog被N82系列文章淹沒了。幸虧即時看到qing兄兩篇不錯的文章 程式設計的兩個觀點 (1/2)程式設計的兩個觀點 (2/2),讓我決定還是來早點把這個系列寫完,不然就快變富奸了。

qing兄的兩篇文章指出程式員的兩種型態,一是重視演算法、資料結構、執行效率的「效率魔人」,二是重視程式架構、擴充性、彈性、可理解性的「架構狂」。這兩種人其實都很好,要完成一個偉大的軟體,團隊中兩種人一定都要有。比較糟糕的是,有很多「第三型態人」,他們的信念只有一條:「程式只要會動就好」。第三型態人不在乎效率,也不管架構漂不漂亮,上面要求他做什麼,他就想辦法東湊西湊,從Google找程式剪貼,從MSDN抓範例來用,反正只要能隨便測過一個case就能交差了。

其實第三型態人也不一定是不懂演算法、不懂design patterns,他們常常只是因為火燒屁股了,就不管三七二十一先弄出可以動的程式再說,效率或架構等到下一階段再來改就好…。問題是,下一階段又有新的功能要做,這些人再度面臨抉擇時還是會決定先讓程式「會動再說」。我看過很多各式各樣的程式員,只要碰到這種人,同樣的過程是履試不爽不斷出現。

所以要成為一個優秀的程式設計師的關鍵是什麼?關鍵不在於coding速度有多快、懂多少演算法,或是背了多少patterns,最重要的是「熱情」!

偉大的程式設計師都非常喜歡寫程式,寫程式的過程是一種絕妙的享受,他們執著的地方或許不同,可能是程式的效率,也可能是開發的效率,甚至是架構的彈性或是程式碼的精簡美觀程度,但他們都非常想要並堅持自己應該寫出「好程式」。熱情能驅動他們把軟體的某一個面向雕琢到極致,這需要超乎常人的毅力和堅持,以及絕不向壓力妥協的精神。只要具備這種熱情,不管你在乎的是什麼,都可以成為一名偉大的程式設計大師。

P.S. 雖然這篇文章講的東西很八股,但我發現這真的非常重要,看一個人的熱情就能知道他做出來的成品是什麼樣子。如果是我來面試,我一定會在面試時觀察這人有沒有喜歡寫程式的熱情,沒有熱情的人容易向現實壓力低頭,也不會要有不斷精益求精的信念,在如此競爭的時代是很難生存的。

P.S.2 要追求神乎其技前,當然要先知道自己的目標是什麼樣子,所以我本來想在這篇寫一個優秀的程式設計師應該要有的特質和能力,但才寫了第一項就落落長。所以還是等待下一篇再繼續這個主題好了。(路人:「這不就是擺明要當富奸嗎!」)

(待續)

十二月 26, 2008
» 追求神乎其技的程式設計之道(七)

追求神乎其技的程式設計之道系列:

這次拖稿了很久,雖然下禮拜就要期中考了,但我決定還是要趁這個作業都剛交出去的忙碌低峰期來補上一篇,不然真不知道下一篇要等到什麼時候了…(泣)

思考的高度

上一篇談到了優秀程式設計師的第一要件:「熱情」,這一篇我想要談我覺得熱情之外最重要的能力:「思考」,特別是抽象化的思考能力。

寫程式可以說是一件進入門檻很低的工作,拜現代的GUI開發工具以及大量的open source library所賜,很多低階、跟硬體和作業系統直接相關的細節都被隱藏起來了,所以說其實只要學會某種程式語言並且會把自己的想法鉅細靡遺的轉換為程式碼,就可以說自己會寫程式了。到達這個階段並不困難,只要有心學習的話即使是國中生自己看看書或到巨X電腦上上課都能學會。那麼究竟要如何跨過這個階段,讓自己能和巨X電腦的畢業生有所區隔呢?我認為關鍵就在思考的高度。

寫程式需要的思考能力第一是邏輯思考,主要其實就是用正確、清晰的邏輯表達想法而已,說來簡單但要做好也是需要一定時間的訓練。第二是抽象化思考,這是許多人忽略掉的一點,也是我覺得區隔一個平凡與偉大程式設計師的重要特質。

我覺得所有的程式都可以看成一個巨大的金字塔,頂端是這個程式的最終目標,一個模糊的概念;底部是細節的程式碼。而中間是一個經由不斷切割與抽象化所構成的高塔,每一個程式都是切割為許多的元件、模組,再切為更細的class和function,再來是最底下的變數與邏輯判斷式。

很有趣的是,不同的人看這個塔就會有不同的樣子。初學者看到的塔只有兩層,他們和人溝通的方法是鉅細靡遺的描述程式碼:「我在這裡寫個for,第一次把i設成0,在迴圈內每次檢查這個陣列的第i個元素…」,在他們眼中只有程式的目標和程式碼本身,所以還可能會寫出下面這種讓人哭笑不得的註解:

  1.  
  2.  a = 1;  // 把a設為1
  3.  

有些經驗後,會再多看到一層,利用function把一段程式碼包裝起來,賦予一個名字和獨特的意義。學會這個後,就可以利用抽象化後的function名稱來溝通,例如:「我在這個迴圈裡每次都用isCaptial來檢查這個字串是不是都是大寫…」再接下去呢,可以再利用class,利用design patterns,利用更大的模組、子系統來溝通,認真說起來,這其實是一個無止境的切割。

在資訊科學這個領域,抽象化是個無窮無盡的必要行為。因為世間萬物實在太多太複雜,我們只好不斷把東西歸類,並賦予一個名稱、一個意義,經由這樣的過程我們才能用抽象的語言和符號來溝通,避免每次都要從最底層的瑣碎細節開始說起。而平凡和偉大的程式設計師,我覺得他們之間的差別就在於能看到多少這個高塔中間的分層。厲害的高手都很善於切換自己思考的高度,一下能跟你討論高階的系統架構設計,一下又能深入到最底下的組合語言和二進位除錯。他們腦中除了有這高塔每一層的詳盡平面圖,甚至也非常了解不同樓層之間的交互關係。而平凡的程式設計師大多只能專注於自己所開發的範圍,對於其上的架構或其下的細節都不一定能理清頭緒,萬一出現bug也會搞不清楚到底是哪一層出了錯,而被完全無關的細節絆住手腳。

程式語言決定了思考的高度

大部分資訊系學生接觸的第一個語言是C語言,其實我覺得到了21世紀還從C語言開始教是非常值得商議的一件事。我在台大時曾當過兩次計算機概論的助教,雖然大一學生同時還在修計算機程式設計(也就是教C語言的課),但我在課上也同時教他們學Python。

有人問我:「只學C語言不夠嗎?」。如果是為了畢業後能找工作,其實學C就夠了,因為幾乎所有公司都只考基本的C語言能力,也就是說他們認定只要會寫C就能勝任日後的工作。事實上大部分大學都不太教程式語言的,會教C也只是因為大一總得選一個語言教,而C還是老得辣,加上大部分教授也只會這個,所以自然就決定是它了。近年來因為物件導向風行,所以大部分學校還會教個Java或C++,但這也是因為要教物件導向的概念,而不是以教這個語言為目的。除了這兩種外,大概就剩下組合語言了,而這也是因為要教電腦最核心的CPU運作方式,所以才會順便教到的。

程式語言的地位在資訊系其實一直很卑微,大部分教授覺得這只是一個基本工具,就像螺絲起子和鐵鎚一樣。但我一直覺得程式語言是很重要的工具,它不只是讓人用不同語法和電腦溝通,而是讓人能用完全不同的思考方式來解決問題。簡單的說,我覺得程式語言就是決定思考高度的一個關鍵因素,而這也間接決定了寫程式的能力。

舉一個簡單的例子,高階的script語言幾乎都內建map這個資料結構。(也就是一對一的對應表,給它一個key,就能很快的找到其對應的value。有的語言稱為dictionary、hash、或associative array。)如果寫習慣Python或Ruby的人,一定會很直覺的用map來儲存任何對應關係,甚至用來表示會動態變更欄位的struct。但是,在C語言裡沒有這種東西,這讓很多只會寫C的人直覺的用陣列加上linear search來存放這種對應關係。如果資料結構學得好的人,會知道這樣寫效率很差,但很多時候因為沒有方便的library,也懶得自己寫一個高效率的map(不過是存一個電話簿,我難道要先寫一個紅黑樹嗎?),就妥協於沒效率的儲存方法。

這就是一個被程式語言限制住的典型例子。在高階語言用map存東西實在太容易了,所以這會變成思考時的一個小單位,跟人溝通或是規劃架構時都能隨時拿來用。但相反地,在低階語言裡,要有效率又簡單的儲存這種對應關係實在很麻煩,所以人們在思考時會傾向選擇容易的方法來做,而自然忽略掉了以map為基礎的解決方法。

除了script language外,functional language也是另一個進化到神乎其技路上必備的技能。functional language是以function為基礎來思考的程式語言,典型的代表是LISP、Scheme、Haskell。(這邊所說的function是higher order function,可以以其他function為參數的function,和C語言裡的function是不同的概念。)在functional的世界最棒的特性是程式可以只靠function間的相互組合而生成,不用迴圈不用if一樣可以達成同樣的目的。

舉例來說,如果我要要從一個電話簿中挑出所有姓張的人,並傳回他們的電話,用低階語言(其實我指的是imperative language,但這裡就不要這麼講究了)寫起來大概是這樣:

  1.  
  2. PhoneData contacts[N] = {…..};
  3. String number[MAX_NUMBERS];
  4. int count = 0;  
  5. for(int i = 0; i < N; i++){
  6.   if( !strncmp( contacts[i].name, "張", 1 ) ) // well, 讓我們假設這個strncmp支援unicode
  7.     ret[count++] = contacts[i].number;
  8. }
  9. return ret;
  10.  

用低階語言寫程式必須不斷處理瑣碎的細節,像是要開多大的陣列、要弄一個額外的counting變數、要用迴圈一個個檢查陣列….。當腦袋裡充滿這些細節時,是很難切換到更高的角度思考的。而functional language提供完全不同的思考方式來解決同樣的問題,以下我用Ruby的語法寫同樣的程式(Ruby具備許多functional language的特性,但不全然是個functional language):

  1.  
  2. contacts = [ { 'name' => '...', 'number' => '...' }, ... ]
  3. return contacts.find_all{ |c| c['name'][0,1] == '張' }.map{ |c| c['number']}
  4.  

是的,你沒看錯,就只有兩行,而且真正做事的只有一行而已。這裡用到的是functional language的基本工具:filter(Ruby裡叫find_all)和map。這兩個function特別的地方在於他們能用來取代一般需要迴圈才能做的事,並賦予除了「迴圈」以外更高階的抽象意義。filter的意思是過濾,可以從一個陣列中用一個給定的function為條件來去除不合條件的元素;而map的意義是對應和轉換,可以用一個給定的function作為規則把一個陣列中的每個元素全轉換成另一個樣子。

多了這一層抽象化後,寫程式的思考方式會變得完全不同。迴圈不再只是迴圈,而是可以根據它的目的將之區分為map或filter(其實還有更多,這邊只是先舉兩個做例子),思考時便能以組合這些小元件的方式來構思程式的寫法。這裡提供的不只是語法上的簡便而已,而是整個思維的大躍進,以及思考高度的提昇。

這就是為什麼我要教大一新生Python。Python融合imperative language、object-oriented language、以及functional language,語法簡單清楚威力又強大。雖然他們學過後不見得會繼續用Python,但有了不同語言的概念後,思考的高度會完全不同,寫出來的程式品質自然也不同。

(待續)

八月 6, 2008
» 追求神乎其技的程式設計之道(五)

讓電腦自己寫程式的夢

在高三突然對於讓電腦自己寫程式產生興趣後,我每天就都想著這件事,夢想著未來某一天的電腦能跟我一起寫程式,當我把程式目的說給它聽時,它就一邊把細部的程式碼產生出來:我不用想如何命名變數,或是要用什麼演算法,還是我到底要不要把這個功能變成獨立的class…;我只要動動嘴巴:「我想寫一個橫向捲軸的射擊遊戲。玩家操縱著會變形的飛機,還有四種武器。第一關要長這樣這樣……」,然後電腦就幫我把遊戲寫出來了!如果真的可以這樣,那該有多好啊!(如果真的成真,恐怕我也要失業了?)[註一]

這個想法實在太讓人興奮了,雖然說這是一個遙遠的夢想(其實那時候我並沒有覺得這麼遙遠,只能說自己太不自量力XD),但也開啟我對於人工智慧、程式語言結構、軟體工程等領域的高度興趣。

寫程式很難?

在高中時代頗不知天高地厚的我,一邊嘗試著利用基因演算法(Genetic Algorithms)讓電腦自己產生程式碼,一邊研究各種程式語言的結構和特性。靠直覺摸索出利用tree作為中介來描述一個程式後(那時沒唸過compiler,不知道這個其實就是Abstract Syntax Tree),我突然就對這個想法的可行性信心大增,所以一時衝動就去報名了國際科展,打算把這個想法實做出來。

真的做了以後才發現,最難的部份不是產生出程式碼。如果你把程式語言的基本元素,像是if、for、變數、運算符號等東西做成一塊塊磁體,然後拿給一隻猴子玩,那麼牠其實也能拼出一堆程式給你,問題是:「你要怎麼知道這些程式碼真的達到了你想要的目的?」

悟出這個道理後,我突然了解寫程式最難的部份是在驗證程式碼真的跟你所想表達的事情完全相同。(所以說我對於各家軟體公司的QA地位都低於RD其實感到很不平)

基本上,我們只能設計大量的可能輸入值丟進程式裡,並比對程式跑出來的結果和我們想要的輸出相不相同。即使在這種情況下,我們也只能說這個程式在測試過的這些輸入值上所產生的結果是正確的。也就是說,除非我們測試過所有可能的輸入(這意味著無限多種可能),不然永遠沒辦法知道某個程式是對還是錯。除此之外,即使只測試一個輸入值,也還有個很嚴重的問題:「我們怎麼知道這個程式要跑多久?」換句話說,當你程式跑下去,你怎麼知道他是掉入一個無窮迴圈,還是其實正在拼命計算當中?

我在參加國際科展時,認識了歐陽明教授,他告訴我這個問題叫做Halting problem,Alan Turing在70年前就證明了這是一個無解的問題。知道這件事後,才發現自己所知實在太少,對於資訊科學的基本知識實在非常不足,但這次經驗其實也給了我一個明確的方向,讓我把書中的理論和實際的目標連結在一起。

見樹又見林的學習之道

提到書本中的理論,有很多人問過我要怎麼學習寫程式或資訊相關的知識,我順便在這邊分享些心得給大家參考。

常看到許多人抱怨大學裡學的東西都是理論,畢業後找工作時才發現什麼都不會都得重學;當然企業也會抱怨,大學應該多教一些實務課程,不然出社會後還得重新訓練。說來說去,一致的口徑指向理論和實務是打死也扯不上關係的樣子,尤其念資工的人更常這麼說:「學校為什麼不教C#?為什麼不教我做網頁?好歹也要教個HTML嘛!」


我覺得學習任何事物,一定要有充分的興趣才會有效率,在不知道所學為何的情況下被逼著學習是非常痛苦且沒有效率的。最近看了一本書:沒有資優班,珍視每個孩子的芬蘭教育,書中提到芬蘭教育成功的秘密在於「見樹又見林」,這句話也是我對於如何學習最想分享的秘訣。

台灣的教育方法是「先見樹,再見林」,也就是先教你細部的方法和技術,等你都學會之後(或是硬背起來之後),出社會後就會知道為什麼要學這些東西。(很多人小時候都聽過「等你長大就知道唸書有多重要」吧。可是現在比較多人畢業後反而說「我不知道之前念那麼多書有什麼用」)在這種體制之下,許多人在還沒見到整片森林的美景前就被一棵棵大樹搞得暈頭轉向,痛苦萬分,在不知道「學了這個可以做什麼」的情況下,不管學什麼都會覺得沒有意義沒有動力。

而「見樹又見林」的學習方式,是先找到能引起自己興趣的目標,讓自己有個理由去認真學習,之後再往細部的技術和理論去學習。我從小就很想自己寫遊戲,為了達成這個目標,我就四處尋找相關的資料,慢慢的我就知道自己應該要學好一個快速的低階語言(像是C++),如果要寫繪圖引擎可能還得學一點圖學的理論和技術,如果要做網路連線還得學網路相關的技術…。

這裡有個重點是,不要看過森林後就忘記它,而又迷失在幾棵樹幹上,要讓自己一直重複見樹又見林的過程。

這跟如何有效開發軟體的秘訣是一樣的。一個有效率的軟體開發方式是用iterative process,把包含設計、實做、測試的iteration時間縮短,但要一直不斷重複這個iteration無數次來改進現有的成果。同理,在已經有目標的狀況下學習時,每當學會一些新東西,就要馬上試著把它實現出來,即使是只有幾行程式碼的prototype也沒關係。只要一直不斷的學,這個prototype就會一直被改進,一直加進最新學到的知識和技術而更接近最終的目標。

同時動腦也動手(註二),用這種角度來學習就能充分了解自己學會的東西可以用在什麼地方,馬上得到回饋的成就感還會刺激自己繼續向前進,形成一個非常有效率的學習循環。用這種角度看學校教的東西,就能知道書本上的理論可以用在哪,並且又欠缺哪些實務知識讓自己無法做出想要的東西。

這方法理論上可以擴展到任何事物的學習,重點在找到有興趣的目標和書本裡知識的連結,我覺得這是老師應該要出力的地方,無奈的是台灣的教育體制把中小學老師們變成出考題和改考卷的機器人….。

註一:
其實,現在真的有這樣的研究,而且驚人的是目前已經有了非常接近我想像中未來的雛型。最讓我興奮的是MIT Media Lab的Hugo LiuHenry Lieberman做的Metafor:只要對電腦用英文描述你要的程式,電腦就自動把Python code生出來給你….。

註二:
話說,MIT的校徽上就是一個拿著鎚子的工匠和一個拿著書的學者,所代表的意義就是 “Mind and Hand”,也就是期望每個學生都能手腦並用,除了做夢外也要實做出來才算數啊。

七月 15, 2008
» 追求神乎其技的程式設計之道(四)

程式設計到底是什麼?

2000年IOI在北京舉辦,這年台灣的代表隊成績還算不錯,拿到三銀一銅,比較可惜的是我第一天表現不理想而落到了銅牌,雖然不至於兩手空空無顏面對江東父老,但也知道自己的實力大概就在銀牌和銅牌的邊緣處吧。IOI結束後,我又回到了學校,但因為已經取得大學保送資格,在學校其實也是輕鬆寫意,成天就看自己的書或研究自己有興趣的東西。

在這段時間中,我開始有所警覺,我發現我雖然很會寫程式解題,但那都是一兩百行以內的小程式,真實世界的程式根本不是這個樣子的!雖然我能很快看出一個問題該用什麼演算法效率最高,並且在很短的時間內把自己的想法正確地轉換成程式碼,但我還是不知道市面上的軟體或遊戲是怎麼做出來的。

我這時才開始接觸C++和物件導向的概念,我突然發現要寫個大程式還真不是簡單的事,除了程式語言外,還有好多瑣碎的函式庫得學。像是要畫圖就要學2D的SDL或是3D的OpenGL,要做Windows GUI程式就要學Windows SDK或是MFC,要寫網路連線就得學socket,要讓遊戲執行順暢甚至得用組合語言寫某些部分…。好多好多東西不斷湧出來,學這些東西很有趣,因為我一邊學就會一邊聯想到學會這個功能後可以用在遊戲裡的什麼地方,於是整個學習過程就像把我夢想中的拼圖一塊一塊拼上去一樣,非常有成就感。

邊寫這種實用性的程式時,我也發現以往在比賽中累積了很多不好的習慣,像是濫用全域變數、變數隨便命名、把整個程式塞在main裡…。這些壞習慣在寫小程式看不出來有什麼差別,但隨著程式規模變大,這就變成了很致命的習慣。而這種習慣一但養成,之後會變得更難改,所以強烈建議初學程式設計的朋友們,一開始就不要偷懶,從認真幫變數想個好名字開始吧!

這段期間也讓我想了很多關於程式設計的有趣問題,像是寫程式到底算是科學+工程,還是藝術?寫程式必須要非常非常精確,任何一個字打錯都可能會讓整個程式跑出完全不同的結果,這對於天生就容易犯錯的人類來說實在是艱鉅的挑戰。為了避免錯誤太多,我們只能用一些固定的流程並強迫程式設計師遵守,讓可能的錯誤減到最低,這就是所謂的軟體工程。雖然有工程的影子,但寫程式卻是很難精確管理的工作,因為面對同樣的問題,不同的人絕對會寫出不同的程式,甚至是提出不同的解決方法﹔有的程式可能要跑三天三夜,有的程式卻能在瞬間得到正確解答﹔有的程式碼雜亂不堪,也有的程式碼井然有序清晰易讀﹔有的人要花三天寫1000行,也有人能在一天寫100行就達到完全相同的效果﹔這些程式的目的可能完全相同,但呈現方法卻有千萬種,軟體工程難道可以限制每個程式設計師大腦運作的方式和速度嗎?

從程式碼的觀點來看,不同的人寫出的程式碼也一定不相同。從程式碼的排版、命名、段落安排、抽象化程度、運作流程可以看出作者的個性、態度、思考邏輯及深度。從這個角度來看,寫程式更像是種藝術,就像是畫筆或樂器一樣是一種表達自我並將思想具體化的工具。

另外我很感興趣的是,人一定要寫程式才能叫電腦做這麼多複雜的工作嗎?能不能教電腦寫程式,讓人只要告訴電腦要寫什麼樣的程式就好?或是有沒有更簡單更方便的方法能和電腦溝通,並且保有同樣的控制力?

就在被這個問題困擾著的同時,我意外從一本書看到基因演算法(Genetic Algorithms)這個名詞。稍微研究過後讓我大吃一驚,因為我發現基因演算法是一個超級有效率的搜尋演算法,可以在幾近無限廣大的可能解裡面很快找到接近最佳解的答案。所以,我很快想到了,如果想要讓電腦寫程式,其實就是告訴他要寫的程式要達到什麼目的,並讓他在幾近無限大的可能程式中找出能跑出我們需要答案的那個程式。這是一種把寫程式視為搜尋的概念,我當時想到這件事非常興奮,但我並不知道其實早就有人想出同樣的概念(這叫Genetic Programming),並已經做了許多研究。

其實有時候無知是件好事,這樣才會有勇氣在不知道這個問題有多難的情況下去嘗試看看。如果我當初就知道這問題其實是能拿好幾個博士學位甚至是得到圖靈獎(Turing Award, 資訊界的諾貝爾獎)的難題,我可能連繼續嘗試的勇氣都不會有了。

(待續)

七月 12, 2008
» 追求神乎其技的程式設計之道(三)

勁敵

熱血的少年漫畫都有一種標準公式,熱血但什麼都不懂的主角,加上一個天才勁敵的刺激,讓主角能在不斷遭遇的困難和挫折中不斷爬起來進步。就像火影忍者中的鳴人和左助,或是棋靈王中的進藤光與塔矢亮,要進步最快的方法就是找到一個遠遠超過自己的勁敵作為目標並且努力打敗他。

我在高一時參加校內的資訊能力競賽初賽,在都還搞不太清楚要比賽什麼東西時就去參加了。當時只會用BASIC,知道要用筆寫程式時還嚇了一跳,還懷疑閱卷老師難道能在頭腦裡執行程式嗎? 我記得那題目不難,我每題都有寫,但最後只拿了個佳作,離學校的代表隊還遠得很(話雖如此,我也是唯一有得獎的高一生了)。過了幾個月,我非常驚訝的發現台北市的資訊能力競賽,竟然有一個建中的高一生SBB拿了一等獎,更可怕的是他接下來又在全國能力競賽拿到二等獎,才高一就已經有能選上奧林匹亞國手的氣勢,前途無可限量。

受了他的刺激,我非常拼命學習,先花一個月自己把C語言學起來,接下來就到圖書館借回所有有關資料結構和演算法的書,每天都拼命看。這是我進步最快的時期,當時我在家自己跟著已經進入IOI培訓營的選手們一起練習ACM Online Judge上的題目。每天到學校都在看Introduction to Algorithms,因為沒有電腦,只好用紙筆練習解ACM Online Judge上的問題。白天在學校想解法,回家就在電腦上把程式寫出來,並submit上去看看結果對不對。透過這種方式練習,可以看到自己解出問題的數量不斷增加,強烈的成就感能刺激自己不斷練習不斷思考,如此循環之下真的進步得非常快。

很快地,在我升上高二後,我發現我已經寫了三百多題,進入ACM Online Judge世界排行榜的前幾名了。同時我也發現有另一個跟我一樣每天都增加好幾題的人,沒想到竟然就是跟我同年的建中SBB。雖然我每天都能寫兩三題,但SBB的解題數仍遠遠在我前面,逼得我只好印出所有題目,帶去學校不管上課下課都在紙上解題。就這樣我們的差距慢慢拉進,不知不覺我們也站上排行榜的前兩名。如果我今天多寫一題,我就能暫時站上第一,但隔天馬上又會被他超越過去,彷彿他早就已經囤積了數十題起來等著慢慢折磨我一樣。

就在這樣的刺激下,我就像漫畫中的熱血主角一樣快速成長,進入了勁敵所在的境界。我順利從校內初賽、中區預賽,一路拿第一進到全國決賽。非常戲劇性的是,在這年全國能力競賽,SBB拿了滿分得到第一,我錯了半題排名第二,而全國能力競賽一向是前兩名都為一等獎,也就是說我和SBB原本應該都是一等獎,沒想到評審說我和第一名的滿分有個落差,所以一等獎就改成一名,而我就變成了二等獎第一…(實在很嘔,但也不能怎樣Q_Q)。比賽雖然輸了,但我沒有很難過,因為我知道自己還能再進步,還能變得更強,繼續努力下去我很可能可以選上奧林匹亞的國手。

國手之路

高中各學科的奧林匹亞是每年一度的國際盛事,奧林匹克運動會比的是人類體能的極限,而各學科的奧林匹亞比的則是運用腦力的極限。我第一次是從YJL那聽到這比賽名字的,但那時覺得非常遙遠,因為我看到連他這麼厲害的人都選不上國手,可見這不是一般人能輕易踏進去的領域。

改變我想法的是中一中穿堂的一張照片。中一中有個不錯的傳統,只要代表學校參加比賽或科展獲獎,學校就會把獲獎學生的照片掛在穿堂的榮譽榜上。還記得高一時在穿堂閒晃,一個個欣賞歷屆學長們偉大的功績,突然間發現有個叫CLK的學長厲害得不得了,不但在中區能力競賽拿第一,到了全國也還是第一,而且他還選上了97年IOI的國手。後來我才知道他以前也是中一中電研社的社長,而那屆的副社長也非常厲害,自己寫了一個microkernel作業系統代表台灣去美國參加國際科展。有這些如傳奇一般的學長,給了我很大的激勵作用,我這時突然覺得自己或許也能像他們一樣有照片被掛在上面的一天。現在想起來,還真不知道當時自己怎麼能這麼有信心,其實有種不知天高地厚的感覺。但或許也因為如此,才沒有被這種「看起來很困難」的目標嚇到而連嘗試的勇氣都不敢拿出來。

很有趣的是,在我剛上高一時,CLK是中一中第一個也是唯一一個資訊國手。但就在我高一下的時候,有三個高三的學長竟然同時選上99年IOI的國手。因為一年資訊國手名額只有四個,一直以來都是建中學生呼聲最高,這年我們一口氣拿下三個名額簡直是不可思議的奇蹟。我也因此而信心大增,彷彿我每天在他們旁邊練習也能受到逸出的強者氣息感染而變強一樣。

就在我在全國能力競賽拿到第二名後,我就開始為IOI培訓營做準備。IOI培訓營大約收30人,要關在師大內集訓四週,每天都請教授來上課,每週進行一次模擬考。第二個禮拜結束會先淘汰一次,留下來10個人再繼續廝殺,直到四個禮拜結束。培訓營過後不是馬上就能知道成績,還要過一段時間才會知道四個國手是誰,但因為留到第二階段基本上就等於有了保送任何大學資訊系的資格,所以第二階段的氣氛其實還比較歡樂一些。

在師大集訓的四週讓我認識很多在這個領域頂尖的強者們,我覺得這更勝於實際上在課堂上學到的東西。這些強者們如今都還持續在資訊界的各個領域活躍,常常覺得不管到哪參加活動或研討會都還是可以碰到這些有相同背景的人,可見這個培訓營真的也訓練出許多資訊界的中堅份子。

在集訓時,大家也不是每天各自悶著頭寫程式。其實很不好意思說,當時在培訓營進步最多的可能是魔法氣泡對戰的戰術…。雖然有電腦就會被拿來玩電動,但培訓營的學生還是比較特別。每年培訓營都會流行一些能用程式寫AI來決鬥的遊戲,像是坦克大戰、俄羅斯方塊等等,我們那年流行五子棋,大家利用空閒時間寫五子棋的AI,碰在一起時就讓各自的程式互相決鬥分個高下,玩起來比自己親自下去玩還刺激很多。

經過四個禮拜的集訓,每天討論演算法,每天寫程式,到最後連睡覺都會夢到程式碼。當時因為才高二,也不會覺得壓力很大一定要留到第二階段甚至要選上國手,一直抱持平常心反而意外表現得不錯。結訓過後,我每天沒事就盯著培訓營的網頁看,希望能趕快看到國手名單公佈。就在名單公佈的那天,我盯著螢幕驚訝的說不出話,我竟然真的選上國手了!這真的是平常完全不敢想像的事情,真的沒想到我竟然也有一天能讓自己的照片被掛在中一中的穿堂上….。

(待續)

七月 7, 2008
» 追求神乎其技的程式設計之道(二)

(本來沒有想寫這麼長的,哪知道一下手後欲罷不能…。看來這系列文章會變成長連載了。) 資訊奧林匹亞與程式競賽 在升上高中前,我因緣際會透過一個國中的同班同學認識了他的哥哥YJL。YJL比我大三年,我要進中一中時他剛好畢業,很巧的是他很會寫程式,一直都是中一中的資訊能力競賽代表隊成員。剛認識他時,他就demo給我看他用QBASIC自己寫的橫向捲軸射擊遊戲,當時看得我目瞪口呆,我完全沒法想像QBASIC竟然能寫出這麼順暢且華麗的遊戲。這個demo如果不說,我一定會以為這是市面上在賣的商業遊戲(我那時還以為一定要學C才能寫出這種遊戲)。 透過YJL我也得知原來高中還有資訊能力競賽和奧林匹亞這種比賽,聽他述說跟全國的高手一起比賽寫程式時,讓我不知不覺也熱血沸騰起來。我把他高中時留下的各種參考資料全帶回家,並透過他認識了更多還在中一中的強者學長們,就這樣在踏進高中校門的同時也決定了我這三年的方向。 這裡我先介紹一下對於高中生最重要的資訊比賽。高中的學科能力競賽是教育部主辦的比賽,包括數學、物理、化學、生物、地球科學、資訊,每間高中通常會先辦個校內初賽來選出代表選手,再由這些選手參加各區...

[MORE...]

七月 5, 2008
» 追求神乎其技的程式設計之道(一)

最近有讀者問到我學寫程式的方法和經驗,讓我一下掉入時光隧道回想起當初用VB寫出自己第一個遊戲時的成就感,但當初沒料到的是我真的就此迷上了電腦和寫程式的快感,不知不覺也過了10年的光陰…。在這篇文章中,我想寫出我對程式設計的看法和我一路學習上來的歷程和經驗。寫程式是一條無止境的道路,不只是科學和工程,更是一種藝術。而我還在追求「神乎其技」的半路上,雖然還有很多要學的,但我也希望能讓初學者更容易看清楚這條路是什麼樣子,避免陷入盲目追求新技術的死巷中。 一切的開始 如果是從DOS時代開始玩電腦的玩家,應該都知道當初DOS有兩個內建的QBASIC小遊戲:貪食蛇和猩猩丟香蕉。這兩個小遊戲是許多人兒時共同的回憶,我還記得我國小時曾有幾堂電腦課,當時老師在台上嘰哩瓜啦的不知道在教什麼,而台下每台電腦都是貪食蛇或丟香蕉的畫面(老師對不起,其實我就是帶頭做亂的罪魁禍首…)。 微軟把這兩個QBASIC遊戲附在DOS內對我產生了莫大的影響,那是我第一次發現到原來QBASIC和不只是像PE2能打打字而已,QBASIC竟然能把一堆看起來像咒語的文字變成遊戲!幸運的是我家剛好有本第三波的Q...

[MORE...]

biggo.com.tw

A Django site.