三月 19, 2012
» 我為什麼要念博士

最近好像很流行討論要不要念碩士, 像是xdite的我不會念碩士和彭明輝的不甘不願地念碩士。在美國則是看到Matt Welsh寫了Do you need a PhD?討論該不該念博士。

我在MIT博士班已經念三年半了,預期今年六月要畢業,剛好可以在30歲前畫下一個值得紀念的里程碑。在畢業之前就順便利用這篇文章總結一下我的感想,也可以讓未來更多迷惘的人看清未來的各種選擇。

簡單的說,如果讓我重來一次,我還是會念碩士班還有博士班。我知道很多人在選擇要不要念研究所時,是看對未來的就業有沒有幫助,甚至是沒有選擇的空間而被家長強迫升學。我從國中起就很清楚知道自己想做什麼,但我並不是會做長遠規劃的人,而是走一步算一步,因為我覺得世界變得太快,提前規劃五年十年後的職業道路並沒有太大意義。所以我雖然很早就知道自己喜歡寫程式和研究新東西,但我一直到大四才決定要念碩士班,到了碩士班才決定要念博士班。

念書一向不是我的興趣,高中沒認真上過幾堂課,然後靠著程式比賽混進台大。在台大時我也都不去上課,整個四年我唯一全勤的課是大三的compiler,因為這是唯一一堂讓我覺得去課堂裡聽課比自己念還要有效率的課。但雖然沒去上課,我可是很認真寫作業的,尤其是程式作業我都會做把所有可以做的bonus全做完,有空的話還會自己多加一些有趣的功能。也因此到了大四時,我的成績還能勉強進入推甄台大研究所的門檻,等於可以免試直升碩士班。但除了學校生活外,我從大一時就在學校外的網路公司兼差寫程式和做顧問,同時也在系上的工作站實驗室幫忙管理一堆伺服器和Linux主機,到大四還同時在另一個startup公司打工兼差,所以生活其實還蠻多采多姿的。在當時(2005年)這種情況下,其實不太難決定要不要念碩班,因為 1) 我還不想當兵 2) 我當時這些打工的收入其實比一般大學畢業生起薪還高不少,而且我花在這些工作的時間很少,每個禮拜還有很多時間可以自由運用 3) 我找到了一個好老師,給我很大的空間可以在碩士班做任何我想做的題目。於是我就這樣繼續待在台大念了兩年的碩士班。

在碩士班時,我最大的收穫是打開了眼界,透過世界頂尖的論文知道了這領域中最先進的研究和問題是什麼,也慢慢了解MIT、Stanford、Harvard那些世界頂尖的大學都在做什麼研究。我雖然喜歡寫程式,但也不喜歡老是一直寫簡單的留言板或是blog這種書本上的萬年範例程式,只有一直做新東西才能激起我的熱血。慢慢的我也發現念博士班可能是最適合我的路,可是同時我也有幾個掙扎的地方 1) 要念博士班就要去國外念最好的學校才有意思,那就得先花一年當兵,而不能找個公司做四年國防役而不當兵 2) 博士班平均要念六年,同樣的時間如果我在台灣工作,損失的機會成本是台幣一千萬以上加上六年的年資 3) 出國唸書要離開熟悉的地方,熟悉的朋友、家人,要用很破的英文在獨自國外生活 4) 博士畢業實際上會減少就業機會的選擇,尤其是在台灣,真正需要博士的企業非常少。

我在台大認識很多人都有出國唸書甚至在國外工作的夢想,所以對他們來說這些障礙都不是問題。但對我來說,出國唸書最大的誘因只是有機會在世界頂端的學校做自己喜歡的研究,和全世界最厲害的人一起工作,至於是不是要在國外工作則是想都沒想過。

想清楚這點後,我立定一個目標,我只申請我最想去的兩家學校,如果上了而且有獎學金我就去念,不然就算了。

最後的結果是我幸運的申請上了MIT CSAIL,指導教授也能給我獎學金,所以我現在才會在這寫這篇文章。

回過頭來看,現在很慶幸我有決定要嘗試一下申請MIT,即使當時看起來成功的機會渺茫。而這幾年念博士班帶給我的收獲,也遠大於當初的想像,在美國可以得到的各種機會更是在台灣一輩子也碰不到的。

雖然一開始看起來在經濟上會損失很大的機會成本,但實際上美國各種科學和工程科系的博士班都有獎學金(RA、TA、或fellowship),以MIT這種私立學校來說,一個教授每收一個人就要幫他付一年總共七萬美金的學費和生活費,當初我即使在竹科爆肝做不是很喜歡的工作,一年的收入也不會比七萬美金多多少。當然,以帳面上的收入來說,博士班念完是存不了多少錢的,因為七萬美金一半是要拿去繳學費,剩下的生活費也大半要繳房租和吃飯過生活。在台灣工作六年可能可以買個房子,但在美國念完博士班只會得到一個博士學位和少少的存款。

那話說回來,這個博士學位到底值不值得?如果在四年前還在台灣時的我來看,我會說我不確定,但在MIT待四年後,我會說「200%值得」。

首先最大的「福利」是在完全自由的環境下(包括經濟上的自由,選題目和選合作夥伴的自由),和全世界最聰明的一群人一起研究各種既有趣也有挑戰性的問題。這種機會非常難得,如果大學或碩士畢業就去工作,一定會在題目和合作夥伴上受限;如果自己創業,就會在經濟和合作夥伴上受限;於是念博士班成為唯一可以同時得到三方面自由的最佳選項。至於對於能力的增進方面,最大的收穫是英文變好了,可以輕鬆跟來自世界各地的人溝通,讀寫英文論文也是跟吃飯一樣簡單。另外就是「做研究」的能力,雖然我覺得我本來就是一個靠自己學習和研究新知的人,但博士班的訓練是把這件事變得系統化,讓我可以幫更多人學會這樣的能力。做研究的能力還有一個更重要的面向,是判斷什麼題目才是有研究價值的,而什麼是沒有的。如果沒有這項能力,不管未來做什麼事都很容易瞎忙,例如說花很多時間做一些簡單瑣碎的小事、研究一個一百年前早就有人完全想透的問題、或是卡在一個早已被證明不可能有解的問題上。

至於念博士這幾年的年資和可能減少的工作機會,現在看來實在一點都不重要。因為一旦畢業後,打開的門是「全世界」頂尖企業和研究機構的機會。資訊科學的博士在美國出路非常廣,我都還沒畢業就一天到晚收到各式各樣獵人頭的信,除了矽谷那些大大小小的軟體和網路公司外,華爾街的hedge fund都是直接開出矽谷兩到三倍的價碼在搶人。如果對這些沒興趣的人,也很容易到大學或是大公司的研究機構中繼續做研究,或是直接加入學校附近上百家的startup中當個CTO或tech lead。

這些機會如果我當初待在台灣,就一輩子也見不到甚至聽不到。(我在台灣時甚至沒聽過hedge fund這個詞,也沒聽過有哪個念資訊的會去這種公司。但實際上美國最厲害的幾個hedge fund全都是用數學、物理、資訊的博士用非常科學的方法在賺錢的。有興趣的人可以看看前MIT教授James Simons開的文藝復興科技(Renaissance Technologies)。)

世界很廣大,相較之下台灣真的是一個小小島。如同Sega的《我為什麼離開 Google》說的一樣,台灣沒有軟體產業,甚至在其他產業中也很少有軟體專業能發揮所長的舞台。我希望台灣能夠更好,但同時我也覺得每個人的眼光應該放遠放大,看向世界和未來十年二十年,而不是聚焦在台灣、中國和未來的兩三年而已。

Disclaimer: 這篇文章不是要鼓勵每個人都念博士,我知道很多人對於學術研究沒有興趣和熱情(其實我也不太有,我只是喜歡打造新東西而已)。但是,眼界、研究和實作能力的培養則是每個人都能自己做的,這些才是真正影響一輩子的事情。


十月 29, 2011
» 影響力

這個月資訊界有很多了不起的人去世,很多人爭相討論到底誰才真正改變了世界,誰的影響力才大。Steve Jobs的死訊讓千萬人悼念,但發明C語言和UNIX的Dennis Ritchie和AI之父John McCarthy的消息就沒有受到如此廣大的注目。剛好最近很常和人聊到相關的話題,所以想寫篇文章讓自己反芻一些想法,也順便交換一些意見。

四年前,當我在申請博士班時,我還不確定我想做什麼以及我能做什麼。我知道自己個熱愛技術、喜歡親手打造工具來解決問題的工程師。我喜歡憑一己之力解決問題的成就感,喜歡挑戰新鮮的事物,討厭做重複無趣的事情。當時我有兩條路可以選,出國念博士班,或是留在臺灣做軟體工程師。我幾乎沒什麼猶豫就選了出國,畢竟可以做自己真正想做的事,雖然收入會比去工作少,但只要夠生活其實也不是那麼重要。

到了美國後,做了幾年研究,朝了夢想靠近了一點,但對於很多事的想法都有些轉變。

先來說說一些關於影響力(impact)的想法。在學術界做研究,最直接的產物是論文(paper)。研究人員都希望自己的論文可以在自己的領域裡掀起一些漣漪,把自己的想法擴散出去,甚至流芳百世。但有個問題是,一個研究的影響力不是短時間內看得出來的,一個好的想法可能會埋在數十年前的論文中,直到某個人不小心看到了才衍生出諾貝爾獎等級的產物。所以做研究的人通常不太會計較論文寫出來後到底有沒有用,因為根本就沒辦法知道。一兩年內沒被人引用不代表十年後就不會有,同樣的,即使一時引起了廣泛的討論,可能過兩年就又沉寂下來被人遺忘。

這就是在學術界的難處,很多發明和想法的價值不是馬上看得到的,甚至最後演變成產品後大家也不會知道最原始想法的來源是誰。簡單的說,學術界缺乏一個有效率的機制來快速強化有價值的想法和研究,而只能讓這些論文自然的發展和淘汰。如果剛好有人發現某個論文的價值,就會把它實作成產品再推到市面上給一般消費者使用。但如果沒有的話,這些論文就等於是白寫了,也不會對學術界以外的人造成什麼影響。

我喜歡做自己喜歡的研究,但我也想要自己做的東西是有實用價值的,而不是紙上談兵的理論。所以在研究工作之餘,我也花了很多時間把我的研究成果(像是sikuli)打造成真正能用的軟體並公布出來,讓大家馬上就能享受到成果,而不是等若干年後有個很閒的人碰巧發現這想法才把它實作出來。之前有個朋友問我要怎麼在做研究和instant impact(立即的影響力)中做選擇,我的答案很簡單:「這兩件事並不是互相衝突的,是可以同時完成的」。

話雖如此,如果談到影響力的大小,那我的答案可能又會有點不一樣。讓我從另一個體悟說起。

這幾年來還有個很大的體悟是:「個人的力量是很渺小的,社會中每一種角色都很重要」。雖然看起來是小學生都知道的廢話,但工程師個性的人就是喜歡凡事自己動手做。馬桶壞了自己修,燈泡不亮自己換,就連公寓附的微波爐壞了我都想先幫他們debug一下確定問題根源後再找人來換。凡事自己做是很有成就感,但如果真的想擴大影響力時,就會有點力不從心。

舉例來說,Steve Jobs和Steve Wozniak當初打造蘋果一號和蘋果二號時,如果缺少了任何一個人,這件事都不會成功。很多技術本位的人覺得工程師才是真正做事情的人,如果不是工程師(Woz)打造產品,那商人(Jobs)要賣什麼?但反過來想,如果不是Jobs幫Woz把他的蘋果一號推銷出去,Woz也不能拿這個收入來繼續研發蘋果二號,而蘋果一號也就只會是他閒暇時候的個人玩具而已。這兩個人的角色不同,但卻是完全的互補對方的短處,而蘋果這家公司也就是建立在這樣的基礎上才能持續不斷把產品轉化成價值(也就是金錢),再拿回來繼續研發更好的產品。這個稱為「商業行為」的正向循環是人類社會中非常強而有力的發明,可以不斷自我成長,同時又讓更多人受惠。

看完Apple的例子後,讓我們來看不採用這個稱為(邪惡)商業行為的正向循環時會發生什麼事。以我自己的sikuli為例,我在去年初釋出第一個版本後,這一年多來有九個版本更新,其中三次是重大的更新,總共被下載了二十多萬次(在官方網站上,至於其他各地的mirror我就不知道有多少了)。看起來是不錯的數字吧?我當初釋出並open source的目的就是希望讓更多人使用,也希望有些開發者能進來幫助我開發、翻譯、寫文件之類的,好讓這個東西獲得一定的動能自我發展下去。

但過了一年多後,我發現事情沒有想像中的那麼簡單。一個不營利的open source專案是非常難自我成長的,因為缺乏直接的誘因($$$),我沒辦法雇別人來加入開發,只能祈求剛好有人對這東西「有興趣」,並且有足夠的「能力」、「時間」、「毅力」看懂我原本的code,並加入「符合專案方向」的修改。以上的條件要全部都能滿足,才會有人發個email給我說「嘿 我想送一個patch….」。此外,因為這專案開始只有兩個開發者,沒有其他專長的人,所以我們有很多事都沒辦法做。例如說,我們沒辦法一一回答用戶的問題,因為實在太多五花八門的問題了(客戶關係管理失敗);沒有人去推銷或廣告sikuli的存在(一切都靠口耳相傳);沒有足夠人力填寫和維護文件;沒有人幫我們在各種環境做測試(只好直接拿用戶當白老鼠);沒有專業設計師設計使用介面、網站、logo(一切都是我自己東拼西湊的);沒有人做市場調查,研究什麼功能才是最重要的(所有先做的功能都是我自以為重要的)….有太多事都是我們想做但無能為力的。雖然後來有個熱心的粉絲常駐在我們的論壇上回答絕大多數的問題,甚至還幫我們寫了大多數的文件,但開發力量還是一直很薄弱,有很多我們想做的東西一直都沒時間沒人力去做。看看這個commit log就可以了解了(前兩個是核心開發者,後面都是用戶):

1065 Tsung-Hsiang Chang (其中有19個是用戶送來的patch)
94 Tom Yeh
61 RaiMan
34 Karl-Michael Schneider
9 anatoly techtonik
1 Arnaud Gelas

殘酷的事實:雖然用戶不少,但所有的commit裡面只有11%是由核心開發者以外的人貢獻的(包括了code和documentation)。(更殘酷的是我一個人就佔了超過八成的commit,要是我停下來的話整個專案就等於是死了)

一個人的力量真的很渺小,我知道有很多事能做來讓這個軟體變得簡單、更完美、讓更多人能使用,但一個像這樣的open source專案缺乏誘因吸引更多不同專長的人加入,靠一兩個人閒暇的時間和力量是沒辦法長久經營下去的。這時候我就覺得非常需要一個像Steve Jobs一樣的人來幫忙,因為商業化可以很有效率的讓這個軟體持續成長,並直接讓更多人受惠。工程師雖然是做出產品的人,但如果沒有商人來把產品賣出去,換成資金進來繼續研發,現代社會就不會有這麼多種精緻、可靠、高品質的產品可以用,很多高科技原型就永遠都只會是工程師的玩具而已。

體會到這點後,突然也可以了解世界上很多職業存在的理由和價值。例如佔領華爾街的人說,華爾街只是把錢從一手拿進來,再從另一隻手轉出去,憑什麼可以從中獲得巨大的利益?回答這種問題的時候,其實只要想想:如果沒有這些人存在,世界會變什麼樣?一個簡短的答案可能是:沒有華爾街,大家的錢就會放在家裡,放再久也不會有利息(甚至還有可能發霉或被蟲吃掉),因為沒人把大家的錢拿去再投資;需要錢的人(例如想創業的人),也不容易借到錢或找到人投資,因為大家只能跟認識的親朋好友湊錢;假設有一兩個人願意借錢,運氣好可能不用利息,但同樣的運氣不好可能會被收高額利息而不自知(因為沒有流通的市場,所以也不會有一個大家公認的合理利率)。從這個角度一想,促進經濟有效率的流通(也就是把錢從一手拿進來,再從另一手轉出去)的確是非常重要,即使他們沒有實際生產出什麼東西,但也對社會帶來很大的價值貢獻。同樣的道理,工程師老瞧不起銷售人員憑一張嘴就可以拿高額獎金,但仔細想想,要是沒有人銷售產品,公司就沒有收入讓工程師製造更好的產品了。如果用經濟學來解釋,每個角色的價值都是市場決定的,如果銷售很簡單又好賺,那工程師就會自產自銷而不是交給別人來做了。

以前我總覺得商人是邪惡的化身,但當自己想開始把影響力擴大時,就會發現每一種角色都是不可或缺的。經營公司也不見得是要以賺錢為目的,而可以是為了研發更好的產品而建立的一個生態系統。而社會中每一種角色都有其重要性,每一種人的貢獻和影響力也很難比較,與其爭論這些事,倒不如做好自己認為最重要的事來改變這個世界。


八月 15, 2011
» Sikuli Plays Angry Birds on Google Games

Franck Dernoncourt wrote a Sikuli Script for playing Angry Birds on Google Games.
The script is simple but efficient: it achieves high-scores that are very hard to beat. It tries different launching angles and beats Sergey Brin’s high-score on map 1-4 (36710 vs 29920).

The demo of this script can be seen on youtube.

The full script can be downloaded at here.
frameborder=”0″>

五月 31, 2011
» 駭客們,起來創業吧

前一陣子「雲端」服務正紅的時候,很多熟悉技術的朋友(包括我在內)都有同一種反應:「這有什麼了不起?我十年前就有自己的Linux主機,在任何地方都可以連上去收信、抓檔、聽音樂…。」對於熟悉各種電腦網路技術的駭客來說,有自己的UNIX伺服器是很普通的事。我在十年前就已經習慣用ssh連到我的伺服器上收email,或是用NFS把伺服器上的硬碟掛載到我的laptop上使用,所以在gmail和dropbox剛出現時,我並沒有感到很興奮,也不是最早開始使用的嘗鮮者。

對於熟悉技術的駭客來說,如果發現自己有什麼需求,就會動手利用手邊的資源拼湊出屬於自己的解決方案。這種「私有服務」會讓人很有成就感,因為除了是自己做出來的外,還可以不受服務提供者的無理限制。(我在自己的伺服器上收信,信箱容量上限就是我的硬碟上限;在自己的伺服器上架網站,不會限制只能用多少CPU time或多少RAM,更不會被強迫放廣告。)但相對來說,駭客也因此容易自滿,看不起這些「了無新意」的服務,甚至因此忽略了利用這些技術創業來改變世界的機會。

善於寫程式的駭客也有類似的盲點。每當一個新網站或新軟體出現時,一定會有一些人跑出來說:「我以前也做過類似的東西,用X語言和Y框架一天就能做出來了,沒什麼了不起。」或是「這不是跟3年前的X軟體一樣嗎?」,殊不知這個新東西可能就是Facebook或Angry Birds.

當一個人對科技了解太多時,也同時容易低估讓新科技普及的難度和所產生的影響力。對於這種人來說,沒什麼東西是「新的」,因為他們可能在20年前就做過今日Facebook或是Google的雛型了。我在做研究寫論文時,最大的感受也是這個:資訊界最重要的發明和想法早在30年前就已經存在了,現在很多「新科技」也只是把舊的方法套上新的環境而已。可是,很容易忽略的一點是,駭客和研究人員做的雛型是用來滿足自己一個人的需求而以,即使你能在一個晚上做出這個雛型,接下來你能讓它成長為滿足一百人、一萬人,甚至一百萬人需求的產品嗎?

解決一個人的問題後,不代表複製一百萬次就能解決一百萬人的問題。

滿足一個人和滿足一百個人是完全不同難度的事,同樣的,滿足一萬人和一百萬人又是不同難度的問題。這種規模化的過程,難的不是平行化或分散式的後端技術,更重要的是創造出讓每個人都願意嘗試並且感到滿意的使用經驗(user experience)。

Dropbox和古老的NFS本質上都是遠端的檔案系統,但Dropbox之所以能有上百萬的使用者就是因為它夠簡單,安裝完就能忘記它的存在。使用者不需要知道伺服器在哪,不用設定分享哪個資料夾,不用寫可怕的文字設定檔或是面對有一百個選項的設定介面。反觀駭客間流行的各種技術,如果經過「妥善的設定」也是很好用,但問題是有多少人願意去學怎麼安裝、設定、排除各種疑難雜症,甚至還得被迫先學個TCP/IP基礎概論?

我觀察到有很多駭客自己做了很多小工具來解決自己的問題,但在滿足自己後也很少進一步分享這些工具或是想法。我覺得這實在很可惜,也錯失了很多機會,因為很多問題往往都不只是一個人的問題而已。最近身旁有越來越多朋友投入網路/軟體創業這條路,加上許多的創投、創業討論blog的出現,可以感覺到台灣的軟體產業慢慢開始出現微妙的變化。眾多的技術狂熱者們,如果在hack完能進一步考慮更多人的需求,提供更好的使用體驗,說不定下一個Facebook或Google就是從你手中創造出來的。

(更新)
附註:我指的創業是廣義的「創立屬於自己的事業」,不見得是設立公司或營利企業才是創業。把自己的工具轉變成一個open source專案號招他人一起參與也是一種創業(而且還是慈善事業),把自己的技術心得開設成專業的blog分享給廣大讀者為目標也是一種創業(會有adsense收入喔,但可能非常微薄就是)。本文目的在於鼓勵有能自己動手做解決自身問題的人們,應該要讓這些小東西或小點子發揚光大,而不是埋沒在自家的硬碟或倉庫裡。創業不見得要犧牲原本的工作或脫離舒適圈,即使只在週末或閒暇時間和三五好友一同朝同個目標邁進也是創業,重點是考慮到其他使用者,把目標從自身拓展到其他人身上,影響力自然就會增大。


三月 19, 2011
» 分享我的vim設定檔

最近開始從純文字的vim轉移到有GUI的MacVim,才發現我已經用了15年的vim設定檔不知不覺變得又亂又肥。有一大堆plugin都是放進去就忘記了,或是當初為了解決vim 5.x或6.x的問題,到了vim7後都變成多餘的垃圾。vim這種歷久彌新的編輯器,特點就是客製化功能特別強,每個人都有不同的快速鍵設定或偏好的plugin,但用了十幾年後,我發現真正重要和常用的功能還是那些基本的編輯功能:輸入、移動、複製、剪下、貼上、搜尋、視窗/檔案/分頁切換。(也就是我在給程式設計師的Vim入門圖解說明中畫的那些)其他很多看似很酷的plugin,常常一開始看到覺得很有趣,但裝進去因為很少會用到,時間久了也就忘記它的存在。

因此,我決定趁這個機會重新整理我的vim設定檔,從一個完全空白的設定一行一行把我原本有用的設定加進去並寫註解,並只留下我真正常用,不需要記特殊快速鍵的plugin。本來以為現在還用vim的人不多,但在我的FacebookPlurk上做了個簡單的調查後,沒想到用vim的人還真不少。(當然也有很多是受我影響才開始用vim的XD)於是我也想趁這個機會把我的設定檔分享出來,有興趣的人可以自由拿去參考或改寫成適合自己習慣的設定。

我把我的vimrc放在github上,安裝方法也寫在README裡了。

經過了重新整理,現在我的vim plugin都是透過pathogen.vim來統一管理。每個plugin都可以獨立安裝在~/.vim/bundle下,而不用散佈像以前一樣散佈在~/.vim/{plugin,doc,ftplugin}等等的眾多目錄下。在這種新架構下,要升級或刪除plugin都變得很容易,因為所有跟該plugin相關的檔案都只在同一個目錄下。利用這個特點,我也把plugin都裝成git submodule來管理,這樣日後plugin有新版本推出時,只要一個git pull就能升級完畢。具體利用pathogen和git來管理vim plugin的方式可以參考這篇文章:Synchronizing plugins with git submodules and pathogen

這個vimrc會隨著我的使用持續更新,歡迎大家自由使用或是fork出自己的版本,也歡迎建議好用的plugin。

以下列出一些重要的自訂快速鍵:

分割視窗(splits)
Ctrl-j
跳到下面的分割窗並放到最大
Ctrl-k
跳到上面的分割窗並放到最大
Ctrl-h
跳到左邊的分割窗並放到最大
Ctrl-l
跳到右邊的分割窗並放到最大
分頁(tabs)
Ctrl-t Ctrl-t
開新分頁
Ctrl-t Ctrl-w
關閉分頁
H
前一個分頁*
L
下一個分頁*
一般設定
,/
關閉高亮搜尋標記
,p
切換貼上模式 (paste mode)
:cd.
切換目錄至目前檔案所在處
搜尋/取代
Cmd-t或,t
搜尋/跳到任意檔案
,r
在所有開啟檔案中取代目前的word

*註:和vim原本的按鍵H(螢幕頂端), L(螢幕底部)衝突,有需要用這兩個鍵的請自行修改。


三月 10, 2011
» Trading Bot for Magic Online

Raymond Cheung has created an open-source Magic Online Trading Bot with Sikuli to buy and sell digital products. Magic Online deals in thousands of digital cards that are bought and sold for with real money. Therefore the bot must be as accurate as possible.

The logic takes information from the Sikuli scripts that read the screen for product information and then, after processing that information, uses Sikuli scripting to interact with the Magic Online interface to finish the transaction.

Read the README on his GITHUB for further details. There is a full demonstration of the bot in the youtube video below.

三月 2, 2011
» 做研究與寫論文

最近有幾篇頗有爭議的文章「陳鍾誠給李家同的一封公開信」 「陳鍾誠給李家同的第二封公開信」,針對李家同批判他是現在學術界獨尊論文的始作俑者,並指出應該要有其他的研究產物或評鑑方法(像是寫一個作業系統、做一個CPU之類的)。雖然李家同常常講出令人啼笑皆非的話,但就這兩篇文章而言我還真覺得李家同挺無辜的,連學術界獨尊論文的事也怪到他頭上實在有點牛頭不對馬嘴。

雖然我博士班還沒畢業,但我也寫過幾篇論文,也做過有上萬人使用的系統,我非常了解擅長實作不擅長寫論文在學術界的苦悶和無奈。但隨著我在MIT的時間越來越長,也對這個現象慢慢有了不同的看法。

話說我很愛寫程式,遠勝於寫論文。我可以不眠不休的寫程式,但沒辦法這樣寫論文。如果我當初碩士畢業後直接去工作,就可以在任何我想去的公司愉快的全職寫程式,但到頭來我還是來念博士班了,為什麼?很簡單,我需要有個環境能讓我不計後果的做各種嘗試和試驗。我喜歡寫程式,尤其是沒人做過的程式(一直重複寫留言板和twitter client可不好玩)。做沒人做過的事雖然好玩,結果可能會出乎意料的好,但也有可能會大大的失敗 – 而這就是研究。在公司裡做工程師寫程式就不太能做這樣子的事情,因為公司要考量風險,可能會大成功的東西也意味著可能會大失敗,而大部分的公司沒辦法禁得起這種失敗,所以只好跟著別人的屁股走。

MIT是個很酷的地方,歷史上有很多有名的系統都是在這裡誕生的,像是Ethernet、Emacs、GCC、LISP(語言和第一個compiler)…。如果說要在學術界動手做真正的系統,那MIT一定是世界上數一數二的地方。那麼在這個地方,博士班學生要如何畢業,教授要如何升等呢?

很不幸的,答案是:寫論文。

在資訊科學這領域,美國學校不像台灣獨尊SCI論文,事實上美國人大多不知道SCI是什麼東西,但不是這樣就代表美國不寫論文。在這邊搞電腦、資訊研究的,一樣要寫論文,而且只投到各子領域的一兩個頂尖會議去。(一個大家都知道的潛規則是,三篇頂尖會議的長論文=博士畢業)

台灣有台灣的遊戲規則,美國也有自己的遊戲規則,但即使是MIT的系統hacker們,也擺脫不了寫論文的命運。(例如說,Richard Stallman其實有寫Emacs的論文,做PostgreSQL的Stonebraker也有一大票的POSTGRES論文

我以前覺得寫論文很痛苦,也懷疑有多少人會去看這些紙張(論文英文就叫paper,所以名符其實就是一堆紙),對我來說直接把程式寫出來讓人用似乎更能直接造福人們。我到現在其實還是這麼覺得,所以我花了很多時間把SIKULI open source,建立起一個community,並持續更新千百個跟研究完全無關的功能,目的就是讓所有人能更直接的享用到這個研究的成果。(而很不幸的是,做這些事情跟我能不能畢業沒什麼關係,但還好我老闆還是支持我的。)

但同時,我也覺得論文的存在有其必要性。我認為做研究可以產出多樣化的「產品」,這產品可以是程式碼,可以是影片,或其他任何形式的媒介。而追朔到其核心,研究的產出最重要的是「想法」,也就是 “idea”,而論文只是最簡單又最容易被其他人接受的傳播媒介而已。

為什麼說論文有其必要性,就是因為論文是傳播想法最有效的媒介。論文的架構設計得讓人可以很容易抓到重點,也可以很容易的深入核心想法。如果寫過論文的都知道,論文的架構是死的,一定都有abstract、introduction、related work、conclusion等等,這種架構讓人能各取所需,要深讀或略讀都很容易。但如果說研究的產出是一個軟體系統,我們該從何了解這個系統的「想法」在哪呢?為了要讓一個系統達到「可用」的程度,整個系統裡面至少90%以上的程式碼都是純粹的工程產物,跟核心概念一點關係都沒有。而程式碼又是很難讀的東西,如果別人要了解這個研究的創新在哪,讀程式碼一定是不得已的最後手段。

我絕對贊成做研究的人也得懂如何實作。很多好的idea其實老早在數十年前的論文就出現過了,但一直到現在都看不到,常常只是因為沒人去把它實作出來而已。做研究最難的事就是找到新的idea,如果只是學人家實作一個作業系統或是CPU,那也不過是照本宣科,沒什麼「研究」的價值和貢獻。像MIT這種強調”Mind & Hand”(手腦並用)的地方,很多教授都有很強的實作能力,但他們一手寫程式,另一隻手還是寫論文,因為他們知道這樣才能得到務實的經驗,而同時也能把這些貢獻和想法用最有效的方法傳播出去。

如果你問我,「我在學術界,但我擅長寫程式,不擅長寫論文,該怎麼辦?」

我覺得答案很簡單:如果你有很多創新的點子,那就開始練習寫作和英文,因為不管在什麼領域,如果你沒辦法好好的把想法傳達給別人,那也是孤掌難鳴;如果你沒有什麼點子,只是喜歡寫程式,那更簡單了,趕快quit去做工程師專心享受寫程式的時光吧。

延伸閱讀:
我看李家同的是與非。此文的觀點跟我很接近,所以他講過的很多東西我就不再重複了。

附帶一提,最近在facebook上成立了粉絲頁,歡迎大家加入多多交流!


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

我的學習過程

還記得小時候我和我弟上過一個奇特的數學補習班,叫做「功文數學」。他們的「教學」方法非常特別,不像一般的教室會有一個老師在講台上教課,而是每個人會拿到一疊數學題目,每一面都有數個計算問題,像是「10 x 2 = ?」這樣的問題。每次去功文的任務就是把那一疊題目寫完,寫得越快的人就可以越早回家。那些題目說來沒什麼意思,從頭到尾全都是計算問題,難度從最基本的加減乘除,一直到微積分都有。每次寫完題目後,會有個類似老師的角色,拿出解答本幫你對答案,打上成績。如果在那老師能應付的範圍內,他可能還會跟你說說哪裡犯錯了,下次多加油之類的,但如果到了國高中程度的問題時,老師的作用就只剩對答案而已了。

我之所以說這個補習班很奇妙,原因就在於這個教學過程中,講求的是大量的計算和自我學習的能力。我從加減乘除開始,一路這樣寫到了微積分,寫到後來那邊的老師也沒辦法批改了,乾脆把解答本拿給我們看,讓我們自己看解答學。起初我還覺得這個補習班挺不錯的,只要我做得越快就能越早回家,對小孩子來說是個很好的誘因。而且因為大量的訓練,讓我的計算能力變得非常好,國小國中時的數學考試我都不用準備也能很快寫完交卷。但後來我開始覺得不太對勁,很多題目我雖然知道怎麼算,但我其實不懂為什麼要這麼算,或是這麼算的意義是什麼。可是台灣的考試也不管這個,反正你只要能得到答案,根本沒人在意過程是怎樣。

功文數學的這套方法對訓練計算能力而言很有幫助,因為計算就是需要大量的練習才能變快變好。但問題是,計算能力再好,也是只能算已經定義清楚的問題(也就是考卷上的問題),而無法發現新問題並定義問題,更糟的是還會讓人習慣在沒有完全理解背後的概念時只學得方法快速得到答案。

在我高中開始參加程式比賽後,我用了我熟悉的這套方法訓練自己的程式能力,自己一個人大量的找題目練習。每天從早練到晚,即使沒有人教我也覺得很正常,因為我從小就是這樣自學起來的。這樣練了一年後,我能飛快的寫程式和解題,看到熟悉的題型就能馬上開始敲鍵盤,但同時我也開始覺得寫程式變成一種機械化的過程:看題,解題,寫程式,看題,解題,寫程式…。跟我從小做數學似乎沒兩樣。

我開始覺得無趣。即使我程式寫得再快再好,也只是解出一個別人設計好的問題而已。

心中的聲音不斷的說:「為什麼我要做別人早就知道答案的問題?

我想要做沒有人做過的事,看到沒有人看到的問題,再親手解決這些問題。

當我開始這麼想的時候,我正在一邊學著做科展。科展全名是科學展覽,意味著要做點跟科學有關的事來展覽。以前的文章提過,我高三時夢想著要讓電腦自己寫程式,我覺得這是一件沒人做過的事,非常酷,所以我就一直專注在這件事上(其實當時就有很多人在做這種研究了,只是我不知道而已)。但從一開始到我被選上去美國參加國際科展時,我都一直不覺得這件事科學在哪,頂多說是一個工程(或工藝)作品。但選上代表後是有些好處的,台大的歐陽明教授給了我一些指引,讓我知道「科學方法」得測量和量化這個作品的結果,才有客觀的數據可以知道它的作用,進而跟其他相似作品比較好壞,也因此我才開始對「做研究」這件事有點概念。(到這時我才想起來,小時候雖然有做一些物理化學實驗,但從沒人跟我說過這些實驗是有一套標準的方法和流程的,當然也沒人跟我說這件事的價值所在。)

雖然做科展挺有趣的,但同時我也對科學感到失望 – 因為我意識到科學方法沒辦法幫助我們發明新東西,只能用來評估和檢驗已知事物的好壞。至於所謂的創新科學研究,也是得先提出一個假設(hypothesis),然後再用這套標準方法去驗證它是否成立。但到底要假設什麼事情呢?科學可沒辦法告訴你。

上大學後,我看到當時處在黃金時代的MIT Media Lab所產出的許多創新研究成果,也開始接觸到設計(design)這個領域。我發現Media Lab的人大多有跨領域的背景,像是設計師+電機工程師、或是音樂家+軟體工程師,他們常看到別人看不到的問題,並提出簡單又優雅的解決方法。我以前一直以為做設計的人講求的是美術天份,但後來深入了解後才發現這是個大誤會。設計的目的是解決問題,跟程式設計師其實沒兩樣,只是用的工具是紙筆或模型罷了。(但一個好的設計通常也都很「美」就是了)

雖然如此,設計師和工程師也有很大的不同。設計師對四周環境和日常生活很敏感,常常得在生活中注意各種細節的不完美之處。但工程師成天泡在電腦中,而且很善於使用其實很難用的介面和程式(像Linux、vi、command line、還有各種程式語言),甚至引以為傲,日子久了也就不覺得這些東西有什麼問題。泡在程式碼中的工程師也一樣,如果習慣了和前人或其他人的大便碼相處,久了也就不覺得臭了。

發現這些現象後,我開始學著跳脫出原本習慣的一切,開始注意生活周遭的各種細節,思考為什麼這個東西當初要這樣設計、這樣做有什麼好處和壞處、有沒有更好的方式之類的問題。之後,當我習慣觀察細節後,慢慢察覺到我習慣用的軟體、工具、環境、程式語言,處處都是設計後的結果,而且充滿可以改進和創新的空間。這些東西都不是沒來由的產物,而是經過某些人思考過後的結果,甚至是經過好幾輪的演化結果。可惜平常在學習或教學的時候,很少人會提到這些歷史淵源和演化過程,以至於這些設計都變成理所當然的存在。但如果我們能仔細觀察平常的事物,進一步思考就會發現很多設計都是為了因應當初時空環境的限制,而這些限制現在不一定存在了,所以我們就會有發揮的空間。

眼光拉遠後,能看到的問題更多了。到了這個階段,能力強的人會覺得能解決的問題也很多。但上天給每個人的時間是一樣多的,這時重要的事情反而又變成:「找出最重要、最根本的問題來解決,而不要被眾多的小問題和小機會所分心,才能產生最大的影響力」。

回顧我的學習過程,我會覺得每一個階段都是一塊基石,一塊塊往上疊以後才會具備該有的能力和經驗做下一階段的事情。舉例來說,要是我一開始沒投入程式比賽的練習累積足夠的實作能力,之後我就沒辦法隨心所欲的寫出我想寫的程式,也沒辦法參加科展體會做沒人做過的事有多麼有趣。之後我可能就會一昧沉浸在鑽研各種流行技術中,或是眼高手低說得一嘴好主意但卻做不出什麼來。

雖然學習是一步一步往上走的,但過程中每件事都有反面的效應,讓我不知道是不是做別的選擇會更好。像是我覺得功文數學浪費了我太多時間在數學計算上,而限制了我在其他方面的發展,但同時它也讓我養成靠自己學習的習慣;參加程式競賽也有類似的效應,雖然增強了我的程式能力,但也讓我錯過正常的高中生活和課程(雖然說到目前為止沒有覺得有什麼負面影響)。

無論如何,我相信在成長的過程中適當的大量練習是必要的。異數(Outliers: The Story of Success)一書的作者Gladwell說要精通一件事情至少需要一萬小時的練習,我相信這是真的。我在高中為了比賽所做的練習起碼就超過五千小時,上大學後輕易就超過一萬小時,但其實我也不覺得我真的精通了什麼。經過大量的練習,本來很難的技巧或技術都會變成一種本能,可以很自然的使用它來從事更高階的應用或是建構更複雜的技術。沒有這些基礎,也就很難站在更高的地方看得更遠想得更多,我也不會走在現在的道路上。


一月 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, e, …命名也是行得通,反正對編譯器來說變數或函數的名字不過就是一個沒有意義的符號,不管你取什麼名字最終都只是對應到一個像是0×08048374這個樣子的記憶體位置而已。

簡單來說,一個變數是叫「小狗」或是「小貓」,對電腦來說都沒有區別,但對人來說,差別可大了。

很多初學者以為程式是寫給電腦看的,只要看起來好像能跑出正確結果就好,所以變數位置隨便亂放、名字也隨便亂取、每個變數都是public、甚至一個函數有幾百行,為了在一個畫面中塞下更多程式碼還把IDE的字型縮小到要瞇著眼才看得見。也有很多人覺得高手寫的程式看不懂是正常的,等到自己等級提昇後應該就會看得懂了,但其實事實完全不是這樣。我認識的每個高手和大師寫的程式碼都是乾淨、簡單、易懂,即使是極端複雜的演算法,都能直接從程式碼中看懂作者的想法。

Martin Fowler的 “Refactoring – Improving The Design of Existing Code” 一書中有一句話我很喜歡。

Any fool can write code that a computer can understand. Good programmers write code that humans can understand. (任何一個傻瓜都能寫出計算機可以理解的程式碼。唯有寫出人類容易理解的程式碼, 才是優秀的程式員。)

一段好的程式碼是不需要任何額外註解或說明的。如果名字都取得好,每個變數就能適當的解釋了自己的角色,每個函式都說明了自己的功能,整個程式讀起來就會像在讀說明文件一樣自然。在這種境界下,只要有了基本背景知識的程式員應該都要能輕易地看懂。英文中有個詞叫做explain itself很適合用在這,也就是自己應該要能完美的解釋自己的一切,不需要其他的人或文件來幫忙。

但是,命名是很難的一件事,可以說是寫程式中最接近「藝術」的一部分了。我說的命名,不是要用大小寫混雜的「CamelCase」或是底線分隔的「underscore_separated_style」這種風格問題,而是一個方形到底要叫rectangle或是x的差別。名字取得好,不但自己或其他人未來再回來看這份程式碼時容易進入狀況,對於正在開發中的程式也可以減少很多不必要的bug。

我之前當一門課的助教時,有個作業是要學生實作一個西洋棋遊戲,畫面上要有個棋盤,還有該有的棋子。既然是個棋盤,底層很自然的就會用個二維陣列來表示棋盤的狀態,例如說我們會有

Chess board[N][N]

這樣子的一個陣列。接下來,真正的問題來了,程式中勢必會有一些兩層的for迴圈去對這個陣列做操作,如果是你會把這兩個迴圈的index變數取做什麼名字?

最常見也最不用腦的index命名就是i和j,在一般沒有特殊意義的迴圈中用i是沒什麼太大問題的,因為大家都知道這只是一個單純的index。但如果用到j,通常就代表程式可能有些臭味了,至於會用到k、l、m… 那這個程式一定是徹底腐敗了。

我看了很多學生的程式,我發現很多有bug的程式都是用i、j,或是x、y來命名,而那些寫得很漂亮的程式,幾乎都是用row和column來命名(或是他們的縮寫r和c,或是row和col)。

用i、j的問題在哪?

問題在這兩個名字沒有和棋盤的位置有直接關連,看程式的人沒辦法一眼看出你的i到底是指row還是指column,或是指到宇宙裡的一顆星星。即使是正在寫程式的作者本人,也得一直在心中做i是row、j是column的轉換,但只要精神稍不集中,或是吃個飯休息回來,很輕易就會忘記這些隱晦(implicit)的對應關係。而這種隱晦的對應,就是傷害程式碼可讀性和造成bug的通緝要犯之一。有的人為了避免自己忘記這些細節,就會把這種隱晦的關係或假設寫在程式的註解裡。但話說回來,既然要寫,直接寫在程式碼裡不是更好嗎?

除了用i、j的這群人外,還有另外一群用x、y的程式也是讓人非常頭痛,如果要我比較的話,我會說用xy比用ij還糟糕。為什麼?因為這個程式最終要把棋盤畫在螢幕上,而所有2D繪圖的函式庫都是用x、y來表示螢幕上的位置,如果棋盤用xy,螢幕繪圖也用xy,這樣如何分辨這個xy是棋盤的位置還是螢幕的位置?用xy這群人的解決方法都大同小異,比較懶惰的就是用x1、x2,甚至是x和xx;好一點的會用boardx和screenx,但以index變數來說還是太長太囉嗦了。

與其費這麼大力氣區分兩種xy,如果一開始就用完全不同的名字來存取棋盤和螢幕,不就沒事了?以二維陣列來說,用row和column符合natural mapping,不用再心中自己多做一次轉換。此外,現代程式語言的多維陣列大多是row-major排列,也就是說A[r]就能取到第r個row,A[r][c]就能取到第r個row的第c個元素;但如果用xy來存取二維陣列,就要把xy反過來,寫成A[y][x]才能取到第y個row的第x個column。
(在這個程式中很多用xy的人都把row和column順序搞反,導致初始化的盤面整個轉了90度。)

我以前參加程式比賽時,看過很多經過長期訓練的選手因為比賽的時間壓力而養成不好的習慣,像是把所有程式碼寫在main裡面,變數不是aa就是bb這種沒意義的名字。在程式比賽這種特殊的環境裡,每個程式的目的就是解一個有明確輸出入規定的問題,加上有時間限制,所以選手們都是盡量用最短的code來實作自己的想法。這種情況下寫的程式可以說是用完就丟,只要比賽一結束這個程式的生命也就到了盡頭,所以很多人就不會去思考命名的問題。

到大學的時候,我也常幫同學在作業deadline前夕看他們的程式幫忙debug。很奇妙的是,大學課程的期末專題或是作業應該都有充裕的時間可以慢慢「設計」一個程式,但很多人都是在最後一兩天才開始動手,於是在作業死線的壓力下也沒心情去好好設計一個程式的架構,更別提要好好想每一個變數的命名和位置,也就浪費了許多可以好好練習這個命名藝術的機會。

命名和抽象化是一體兩面的事情。當你能把一個概念用一個適當的名稱來稱呼它時,你才有辦法把這個概念當成一個基石往上建構更複雜的事物。在此同時,人們也才能用這些簡單的名稱來討論複雜的概念或想法。如果你在寫程式時常常沒辦法用很簡單的話跟別人解釋你的程式,通常也代表你的程式是一團漿糊,沒有條理和層次。在這種情況下,你怎麼知道漿糊裡是不是黏了一堆臭蟲呢?反過來說,當你能用簡單清晰的白話跟人解釋你的程式時,你也一定能把程式寫得一樣乾淨漂亮有條理。

如果你現在還在用a, b, c這種變數寫程式,不妨先暫停一下,好好想想每個變數的意義是什麼,你的程式就會自然的變得越來越簡潔和漂亮。

(待續)

2/1 更新:
有朋友提到一篇有趣的相關文章:軟體業的重要職缺 命理大師!。這文章說軟體公司應該有個專門掌管命名的人,才能保持整個project的一致性,並順便算個命看看這些名字吉不吉利。

這讓我想到,其實現有open source程式這麼多,我們可以很容易的寫一個「命理大師」程式出來。只要到幾個project host site,像github、google code之類的地方,把所有project裡的程式碼token抓出來做一些簡單的分析和統計,就可以得到一些有趣的資訊和命名時的參考。例如說,我們可以知道有多少程式裡面用Box表示方形,多少程式用Rectangle,多少程式用deleteXXX,多少用removeXXX,他們之間的區別又在哪。甚至在設計library或API時,連function參數的多寡和排列順序,都可以從此得到參考資訊。更進一步,可以用word net把這些token做clustering,之後我們就可以打一些關鍵字,甚至打中文,讓這個程式建議最多人用的習慣命名法…。


八月 31, 2010
» 42年的鴻溝 – Dyna Book與iPad

昨天睡前心血來潮翻了一下《世紀末軟體革命復刻版》,這本我一直非常喜愛的經典書籍。(註)意外翻到書中提到Alan Kay在1970年代的Xerox PARC(Palo Alto Research Center)提出Dynabook概念的那段歷史:

曾經有好長一段時間,電腦給人的印象是處理複雜運算的龐然巨物,CPU龐大不說,磁帶機、終端機…硬體設備本身便以大著稱。這些「巨物」處理的事務也是龐大的:大量的數據、大量的資料…。電腦是不折不扣的資料處理機,和人們的生活其實是八竿子打不著邊的。

1969年,一位Ohio大學的研究生Alan Kay提出了一個構想:他希望創造一「本」可以帶著跑的電腦,並且利用電腦的資料儲存和運算能力,模擬甚至取代現有的紙跟筆。這台電腦的理想體積要和紙張的筆記本相近,能夠用它來從事寫作、繪畫、個人行程編排或是財務管理、通訊,或者是用它來取代傳統的教科書等「死板」的文字。

如果書本不再只是單向地灌輸知識,而是能對讀者的迴響做出反應(從最簡單的回答問題的正確到複雜的全文檢索等),甚至讓讀者也參與創作的過程(例如透過網路,作者可以和讀者交流,而在「筆記本」上的內容可以隨時更動),那麼我們所得到的,將是一個和當時截然不同的文化 – 對「電腦」的概念不同了,以往對「書本」、「資訊」的概念也將翻新。Kay把他理想電腦稱作Dyna Book,是「動態」的「書」,而不是xx computer,等於不再把電腦當做「電腦」了。

這段歷史我很久以前就知道了,但我一直以為Dyna Book的概念是更接近於筆記型電腦的東西。但昨天看到這段文字時,我卻有了完全不同的感覺,心裡異常的激動,因為這段文字描寫的Dyna Book,似乎更像另一個東西,一個直到今年才出現的東西。上網查了一下Alan Kay當初的論文,看到這圖我才明瞭,原來Dyna Book的設計根本就不是電腦!!



1968年Alan Kay的Dyna Book,其實就是2010年Apple iPad的原型啊。

看到這讓我不禁感嘆,1970年的Xerox PARC真是個傳奇性的研究單位,從以太網路(Ethernet)、最早的個人電腦Alto、圖型使用者介面(GUI)、物件導向程式設計(OOP)和第一個物件導向語言Smalltalk都是在這被發明出來的。(附帶一提,GUI、OOP、Smalltalk的發明人其實都是Alan Kay。)可是Xerox畢竟是個做影印機的公司,PARC做出了這麼多驚世發明,雖然跟影印機都沒關係,但不論哪一樣東西持續發展下去都大有可為,結果Xerox就這樣讓這些概念被Apple和Microsoft免費拿去創造了現今的電腦王國…。

但話說回來,即使在70年代Xerox就投下資源去做Dyna Book,結果也一定不會成功。對當時的環境來說,Dyna Book的概念實在太過先進,能實現這個產品的軟硬體技術都還不存在。除此之外,當時的電腦是只有大型企業或是尖端研究機構才會有的東西,大眾還沒辦法接受每個人都需要一台有「運算能力的機器」(computing device)這件事。即使到了1993年,那個個人電腦才剛開始普及的時代,Apple推出的Newton(最早被稱為PDA的機器,話說回來也還是想實現Dyna Book所描繪的遠景),最後也是慘淡收場。



商業界有本很有名的書叫「跨越鴻溝」(Crossing the Chasm)。這本書的核心概念是說一個新科技被接受的時間可以分為五個時期,過了最早的創新期後,要先讓一群對新科技比較敏感及狂熱的「早期接受者」(early adopters)接受後,再來才能大量擴張到「早期的主流大眾」(early majority)。但很要命的是在early adopters這個區域有一個巨大的鴻溝,如果一個創新的科技不能得到夠多early adopters的支持,就會直接跌落谷底而死亡。

Dyna Book在1968年前提出的概念,一直到2010年才真正實現並跨過鴻溝讓主流大眾接受。不知道該說是Alan Kay的思想超前時代太多,還是相關科技與大眾進步得太慢…。

但話說回來,從The iPad was invented 38 years ago一文所做的比較看來,iPad已經距離Dyna Book的願景非常接近了,但還是有兩點不是那麼容易解決的問題:第一,「Kay把Dyna Book視為一個創造並閱讀資訊的裝置,但iPad主要是設計為一個閱讀裝置。」第二,「使用者要能在這個裝置上創造他們自己的程式。」

很有趣的是,這兩點都是人機互動上的難題。40年來,硬體技術的成長把iPad變得又輕又薄又帶有非常強大的運算能力,但在軟體的使用介面上一直還是沒有很大突破。尤其是讓每個使用者都有能力寫他們自己的程式(end-user programming),更像一個終極的聖杯,能徹底解放人類使用機器的自由,但到底該怎麼做卻沒人有頭緒。(註二)

寫到這裡,不禁擔心起來,如果Alan Kay在40年前提出的概念到今天才開始要進入early majority的普及程度,那麼到現在都還沒有出現的end-user programming聖杯,究竟要多少年後才能真正普及到全人類手上呢?

註:《世紀末軟體革命》由劉燈、賀元、賴明宗所著,這三人都是台灣資訊界早期的傳奇人物。這本書有三個版本,1994年的第一版,1996的第二版,2006又出了復刻版。這本書是中文電腦書中難得一見能把物件導向和GUI相關架構與理論概念完全融會貫通再加以清晰闡述的書。如果有心想融會貫通物件導向與GUI系統核心概念的人,這本書真的值得一看再看。

註二:Alan Kay所描繪的Dyna Book主要使用者是小孩,所以說如果是以讓小孩子能創造自己的程式為目標的話,MIT Media Lab的Scratch可以說是一個很成功的里程碑。(Scratch用「積木」來寫程式的概念在今年被Google做成了App Inventor for Android,可以用同樣的方式寫Android程式。)(雖說是打Google的招牌,但其實App Inventor是MIT CSAIL教授Hal Abelson去年輪休時去Google做的。)

後記:
很多人說iPad是抄襲Dyna Book的概念,這點其實很難說得清楚到底是抄襲或是「實現共同的願景」,畢竟Dyna Book是40年前的提出的概念了。但Apple在iPad出來後不久就拒絕了Scratch的iPad app,原因是Apple不想要使用者能藉由第三方的平台來執行程式,否則使用者就可以繞過App Store取得其他軟體了(Flash主要也是因為同樣的原因被封殺)。這個決定可以看出Apple並不是想做Dyna Book,而是一個一定要先繳錢成為會員後才能開發程式的…….i板子。


七月 23, 2010
» iPad電子書及電子漫畫閱讀軟體試用心得

最近買了iPad,老實說主要的目的是拿來看漫畫。在美國待久了最惆悵的就是很難找到中文漫畫看,現在在加州還算好,10 mile內就有一家中文漫畫租書店,但在Boston則是想都別想…。所以iPad出來後我就一直很關心拿來看漫畫的效果如何,結果之前看到了Apple IPad 漫畫迷的褔音 (含開箱及漫畫測試多圖)這篇文章,就讓我決定要來試試iPad到底能不能滿足我長久缺少漫畫灌溉的心靈。

我總共試了GoodReader、CloudReaders、Bookman、iBunko HD、iBooks這五個app。上面那文章還有提到一個Comic Reader Mobi,但據說作者之前對Apple耍了點小花招,結果被懲罰下架一年,所以現在根本就買不到了。(花15塊買的人不知道做何感想……)

這五個軟體我本來是最看好iBunko HD(他也最貴,$5.99讓我猶豫了挺久才買的),但全部試一輪下來還是覺得免費的CloudReaders拿來看漫畫最好用。
無奈CloudReaders的介面實在不太好看,讓我很想去問這個作者能不能幫他免費改寫一下,還是我乾脆自己來寫一個算了。
(本來想說花點錢買iBunko HD應該就能滿足我,但結果他很致命的不能直著讀一次掃兩頁的漫畫… 唉,為什麼ipad軟體不能要求退錢呢)

anyway,下面是試用心得的簡單記錄,就分享給有興趣的人參考了。

GoodReader

GoodReader(itunes連結)是超級強大的檔案管理和閱讀程式,除了PDF外也能看Office或是iWork的檔案,但偏偏就是不支援jpg.zip,就變得不太適合拿來看漫畫。但如果要看其他格式的文件或是看Google Docs上的文件,GoodReader是非常好的選擇。

優點:

  1. 超強大的檔案管理功能,一般電腦上能做的他幾乎都能做
  2. 可直接從Web下載檔案(內建瀏覽器)
  3. 支援超多格式txt, pdf, doc, ppt, xls, iwork 08/09, HTML, Safari webarchives
  4. 可從Mail server, MobileMe, Google Docs, Dropbox, WebDAV server, FTP server下載檔案
  5. 內建web server,可用wifi或bonjour直接上傳檔案進去
  6. PDF閱讀器的功能非常強大,支援超連結,單頁或雙頁顯示,裁切邊緣、書籤、跳頁、搜尋
  7. 可把檔案送到其他支援的app中開啟,所以也可以把GoodReader當做一個通用的檔案管理器

缺點:

  1. 以看漫畫來說最大的缺點是不支援jpg.zip
  2. 要價0.99,但以這麼強大的功能來說實在是很便宜
  3. PDF翻頁後的繪製速度有點慢,有時候要會閃一下背景後才會出現

CloudReaders

CloudReaders簡直是完美的漫畫閱讀器,也是我目前最喜歡的一個!
唯一缺點是沒有呈列封面的書架,主頁面只是簡單的用條列出檔名,還蠻醜的。

優點:

  1. 支援jpg.zip、jpg.rar、pdf
  2. 可直看兩頁的一半或是一頁,也可橫看兩個一頁,會聰明的把頁面塞進螢幕中。
  3. 很輕鬆就可以翻頁,可以用點的也可以輕輕滑動,單指就能看完整本漫畫
  4. 可設定翻頁方向
  5. 內建web server,可用wifi上傳檔案
  6. 免費!

缺點:

  1. 主頁面很醜。只有簡單條列出檔名和每本書的「進度條」(很妙的設計)
  2. 不支援資料夾分類。雖然支援tag分類,但使用方法不太直覺

Bookman

Bookman(itunes連結)蠻適合看漫畫的,不管PDF或jpg.zip都支援,不管單雙頁掃描都能直讀也能橫讀,而且免費。最大缺點是只能用iTunes傳檔案進去,對我來說要一直插線總是不太方便。除此之外我也不習慣他的操作方式,一般手指滑動都是翻一頁,但他會根據滑動速度決定要翻的頁數,可是無論滑多慢都沒辦法翻一頁。一定要點左下或右下才能翻一頁,操作上不太方便。

優點:

  1. 支援jpg.zip和PDF
  2. 主畫面可陳列每本書的封面
  3. 支援直式橫式和單頁雙頁閱讀的各種組合
  4. 可設定閱讀方向
  5. 用slider快速瀏覽時可同時預覽前後兩頁
  6. 免費

缺點:

  1. 一定要點畫面左下角或右下角才能翻一頁。如果用滑動的會一次翻十幾頁。
  2. 移動檔案到資料夾的方式的visibility太差。我本來一直以為沒辦法移動檔案到資料夾,用了很久才突然知道怎麼用
  3. 資料夾不能設定封面圖示
  4. 只能用iTunes sync檔案進去

iBunko HD

iBunko HD(itunes連結)是這幾個app中最貴的一個,功能上可以說是值5.99,但他的UI設計上缺點不少,導致實際上用起來不怎麼好用。

優點:

  1. 跟iBooks相同的封面呈列書架,非常漂亮
  2. 可看TXT、PDF、JPG.zip
  3. 有手動、自動書籤
  4. 可設定翻頁方向
  5. 可有多個書架
  6. 可用FTP上傳檔案
  7. 可做複雜的UI設定(點選區域大小、手指滑動速度、翻頁特效)

缺點:

  1. 不會記住放大的倍率, 想看一次掃兩頁的漫畫就只能橫著看了
  2. FTP上傳的檔案系統跟書架是完全分離的,無法整批加入書架(但可以直接在FTP目錄中一個個閱讀,閱讀後自動加入書架)
  3. 雖然可以有多個書架,但最多只會出顯示六個
  4. PDF中的超連結無法點選(看漫畫不重要,但看電子書就很糟)
  5. 預設的UI不好用,要滑動很大距離才會翻頁。而且設定介面也太複雜
  6. 要價5.99,不算便宜

iBooks

iBooks是不錯的PDF和epub電子書閱讀器,但不適合看漫畫。

優點:

  1. 免費,而且iPad一開始就內建了
  2. 介面最漂亮
  3. 有快速瀏覽介面
  4. 可以搜尋內文
  5. 可連接Apple的書店直接買電子書

缺點:

  1. 只支援epub和PDF
  2. 不能橫著同時閱讀雙頁
  3. 不會記憶縮放大小,不適合直式閱讀雙頁掃描的漫畫


五月 25, 2010
» 為什麼我用Mac

這篇文章其實已經醞釀很久了。起因是前幾個月看了tinyfool的为什么我认为每个程序员都应该用Mac OS X?youxu的开发人员为何应该使用 Mac OS X 兼 OS X 小史,我當時就很想順便分享一下我的經驗,但那時忙著Sikuli實在沒法靜下心來寫文章,直到最近稍微閒下來了才又想起這件事。

我從2005升上研究所前買了第一台Mac mini到現在已經五年了,說起來其實沒有很長,但自從2005年起,我就成了非Mac不用一族。但用Mac是一回事,我要先澄清我不算是狂熱的Apple粉絲,我除了Apple的電腦外,只有跟朋友以超低友情價買過一台開學優惠送的ipod touch來玩,除此之外,我沒有iphone、沒有ipad、也沒有Apple鍵盤滑鼠以外的周邊產品。在2005年以前,我高中和大學約6年都是用Linux作為主要工作環境。我一路從Slackware、RedHat、Mandrake(後來改名Mandriva)、玩到Debian、Ubuntu,那段時期我有數台24hr online的Linux server,還換過3台laptop,但都是裝Linux。在更之前呢,從國小的386 PC算到高一將近10年就是用DOS和Windows了。

這篇文章主要想分享的是作為一個programmer使用各種作業系統開發的經驗,不是想要說服大家全改用Mac。雖然從時間上看起來我用DOS和Windows最久,但我真正開始大量寫程式是國中開始用Visual Basic的事,所以我在DOS和Windows平台的開發經驗其實算是最少的。而大學階段是我最密集寫程式的時候,所以我的經驗和使用的工具也都是以UNIX派的為主,不見得適用所有人。

我在DOS+Windows、Linux、Mac這三大主流平台上都混過一段時間,這個遷徙的歷史其實也代表了我個人心態上的轉換。

在剛開始學電腦的時候,我是純粹的使用者。我用電腦玩遊戲,國中幫老師用excel做全班的成績單,閒來無事就隨手玩玩photoshop、3D studio等軟體自娛娛人。我記得在386的DOS時代要玩個遊戲還挺不簡單,雖然很多遊戲都說只要打play.bat就可以玩了,但事實上總要修改config.sys和autoexec.bat裡的一些記憶體或音效卡的設定才能玩。所以那個時代的使用者其實大都是玩家級的人物,多少都對Adlib、EMS、XMS、可恨的640K限制有些了解才有辦法「玩」電腦。

國中開始寫程式之後,我的心態就不太一樣了。像一般玩家般玩電腦已經不能滿足我,我開始熱切的想了解電腦內部運作的一切原理,想了解每個程式是怎麼寫出來的,每個零件是怎麼運作的,每一個細節我都想知道。而我剛好就在這段時間接觸到Slackware Linux。

Slackware Linux其實是一個不太好用的Linux distribution,可能很多人也沒聽過它。現在的Ubuntu和Windows沒兩樣,一直按「next」就能裝完整個系統並開始使用。但那時的Linux裝完後可是「什 麼 都 沒 有」。沒有X11,更別提其上的GNOME或KDE;文字編輯器只有vi(不是vim)和joe;沒有make、沒有gcc、…,總之,真的什麼都沒有。那個時候裝Linux其實是為了自己架MUD server,但當時Linux的安裝教學都說裝完的一件事就是自己重新compile kernel。(因為預設的kernel很陽春,幾乎什麼driver都沒有,不自己compile的話很多硬體都動不了。)其實當時我覺得這還蠻酷的,make config打完出現數百個選項可以慢慢勾選,讓我這種想要一窺作業系統裡面在搞什麼鬼的人非常過癮。(一開始我還不知道有make menuconfig可以用,所以其中一個選項不小心選錯就會非常痛苦要整個重來……)但過了一段時間我就發現,MUD server沒架起來,但倒是很會重編Linux kernel和設定xf86config。

國中我還在用Visual Basic寫程式時,其實沒有注意到「平台」不同的影響,因為當時我只用Windows和VB寫程式,也不會其他語言,更不用提在不同平台寫程式。一直到上高中學了C,開始寫比賽的程式時,才讓我注意到Turbo C和gcc雖然都可以compile C的程式,但有某些header檔(像是conio.h)是只有Turbo C中才能用的。發現這件事後,我才突然搞懂library是什麼,還有Linux下有一堆libxxxx及libxxxx-dev的套件是在做什麼的。

Windows和Linux的關鍵差異 – 資訊透明度 – 也就在這裡顯現出來。在我學VB的時候,我把當時一本VB5的經典書籍從頭到尾全讀過了,但我竟然對library一點概念都沒有。我以為我能用的東西就是VB提供的那些元件,後來我多學了一點後發現我還能呼叫Windows API做一些VB辦不到的低階功能,我從來沒想過要去利用別人已經寫好的程式和函式來節省自己的開發時間。簡單說,我以為要造一輛車子,就是要從輪子甚至是螺絲釘自己做起。

某方面來說這是個好事,因為我的第一個VB遊戲「黑白棋」,就是這樣一個個pixel從無到有自己畫出的。但如果要寫更大的程式,每次都從輪子做起就不是個好主意了。接觸到Linux後,我也學了很多open source界的「哲學」,其中最重要的就是重用別人的輪子。

記得很久以前在Redhat和Mandrake上裝軟體非常痛苦,雖然每個程式都被包裝成一個RPM檔,但RPM之間的相依性常會讓人發瘋。每裝一個軟體都有可能會跳出數個相依的library或套件需要安裝,然後使用者必須自己去找這些相依的RPM,更糟的是這些相依套件可能會沒完沒了的依賴更多其他的套件…。(還好後來改用Debian就不用再被這個RPM地獄折磨了。)

這個過程讓我深刻的體會到,軟體應該是像金字塔一樣一層疊著一層往上蓋的,Linux套件的包裝方式清楚的讓使用者能夠看出來一個軟體是利用了哪些library建構起來的,如果自己想寫有類似功能的程式,很容易就可以找到相關的library來用。但在Windows下就不是這麼一回事了。Windows的軟體是為end-user設計的,目標使用者很可能什麼都不懂,所以發佈軟體時應該要把所需要的library或套件全部包進去變成一個龐大的自動安裝程式,使用者只要一直按下一步就可以裝完了。這讓使用者變得比較輕鬆,但同時也一些對開發者有益的細節也隱藏起來了。

Windows的軟體大多是完全不透明的,安裝時你不知道它裝了什麼,也不知道它寫了什麼到registry,更別提要知道他的某某功能是怎麼做的。但Linux是在另一個極端,每個程式的一切都是透明易懂的,RPM或DEB套件裡有什麼東西一個指令就一清二處,每個套件需要用到哪些相依套件也是明明白白。此外,Linux下的設定檔都是純文字,只要文字編輯器就可以修改,不但方便編輯,也方便寫自動化的script或是備份系統。當然,更不用提Linux下幾乎所有程式都是open source的,只要有興趣,隨時可以打開每天在用的軟體的source研究它是怎麼做的。這些事情在Windows底下則是天方夜譚,所有的細節都被自然的包裝和隱藏起來了。這種透明度的差異對於充滿好奇心的程式設計師會產生南轅北轍的影響,當你接觸的東西越開放,就能自然而然接觸和學習電腦從裡而外的各種知識;但當你接觸的東西越封閉,就只能受限於黑盒子的限制而當個單純無知的使用者。

高中時轉到Linux作為工作環境還有另一個很大的原因:「效率」。Linux的世界是架構在文字設定檔和command line工具上的,整個OS的操作都可以用command line解決。更方便的是搭配shell script或是Perl、Python這種script language,可以輕易把系統裡各種小工具結合起來完成複雜的工作。command line有個很大的好處,你每天用的操作介面,和寫自動化script的介面是完全一樣的。也就是說,你只要把每天打的指令串起來放進一個檔案,就自然變成了shell script,而日後只要執行這個script就能自動完成需要一連串指令的工作。這種工作方式滿足了我身為一個「懶人」的慾望,因為我懶得每天用手親自重複做同樣的事情,所以我寫script將這些事自動化。當script寫的越多,就會面臨越複雜的工作,這時就會想要學更多”UNIX power tools”的用法(這是O’REILLY的一本好書)或是更強大的「黏合」語言(像是Perl)來組合不同工具。透過這種正向循環,可以不斷刺激自己提昇工作效率:事情做得越快,就可以想得更多,解決更複雜的問題,進而就能學得更多,做得更快。

大學那幾年我成了虔誠的Linux command line信徒,不管是什麼樣的事情我都可以用各種小工具加上Perl或shell script來解決,而Windows在這方面就完全比不上Linux。Windows的哲學是一套軟體可以做N種事情,但如果你想做的事情不在它原本設計的功能裡,只能兩手一攤什麼事也做不了。

資訊的透明度和command line帶來的高效率讓我非常享受在Linux上工作的樂趣,然而Linux也不是沒有缺點。當我學得越多,對系統底層的好奇心漸漸被滿足後,Linux的缺點就漸漸暴露出來,其中最讓我受不了的是殘破不全的driver支援。讓我印象最深刻的是在802.11b無線網路剛開始流行時,我花了很多時間在找driver和當白老鼠compile最新的driver,重編kernel幾乎是每日例行公事。除了無線網卡外,就算是有線網卡Linux都不見得支援,最惡名昭彰的莫過於Dlink系列的卡,他們的530TX甚至還被暱稱為惡魔卡。(這張便宜的卡在當時非常流行,但偏偏在Linux上就是不能用…)

雖然我是個programmer,但我同時也是一般user。在我想要快樂用電腦看電影或上網時,還要不時的處理系統內部的問題其實有點惱人,更別提當我只想寫一般的桌面程式或是Web app時,為什麼我還得跟Linux kernel奮戰呢?

除了硬體相容性外,Linux這種過於開放的平台還有個大問題是缺乏統一且一致的user experience design,導致usability常常奇差無比,而這也是很多open source軟體普遍共有的問題。程式設計師在乎的是功能面的設計,每個人做自己想要或喜歡的功能,雖然看起來和樂融融,但很少project有專門的團隊負責思考user是誰,他們想要什麼,以及他們會怎麼用這個軟體。同樣的功能但由不同的介面呈現,帶給使用者的感覺也會有天南地北的差異,而由千百個open source軟體拼湊起來的Linux系統帶給使用者的就是千百種不同的設計和使用方式。(後來Ubuntu的出現大大的改善了這個問題,但那時我早已跳到Mac上了…。)

就在Linux的缺點慢慢浮現後,我同時也注意到身邊很多FreeBSD/Linux hacker們開始改用Mac OS X。深入了解後,我很快發現Mac是一個完美解合Linux的效率和開放,同時又兼顧了精心設計過的user experience design的平台。Mac作業系統核心是BSD的近親Darwin,上層有跟Linux相同的command line shell,所以我以往在Linux慣用的設定檔和程式(bash、screen、vim…)全都可以直接帶到Mac上使用。(更棒的是還能像在Debian下一樣用apt-get install或是port install一個指令就自動裝完所有相依套件)

而在command line的上面則是Apple設計的GUI系統,美觀、一致、充分為使用者「設計」過的介面,輕易的就打敗我在Linux上較調半天的FVWM設定。(我換過和較調過無數的window manager,從enlightenment、GNOME、KDE、Window Maker、FVWM…)除此之外,我也不用再自己重編kernel和找driver,每一台Mac都是買來後一打開就能用了。

後來Mac用久了,漸漸發現更多Mac的好處,尤其是對於programmer而言。

每一台Mac都有附Mac OS X的安裝光碟,裡面同時附帶Xcode。而只要把Xcode裝上去後,我整台Mac就已經準備好可以讓我工作了。Xcode是Apple開發的IDE,可以開發各種常見的程式語言,但其實我不用這個。我都用Xcode底層的command line工具,像是gcc、make、svn,加上OS X內建的screen、vim、perl、python、apache(只用這些的話其實連Xcode都不用裝,每一個OS X都內建),我就有了完整的程式開發環境,而且我甚至還不需要連上網路就可以有這些。除此之外,Xcode裡還附帶很多好用的開發、除錯工具,像是我最愛的Shark(非常好用的profiling和memory debug工具)、或是Malloc Debug(找memory leak的好東西)、BigTop(監看每一個process耗用的資源記錄)。

自從我轉到Mac後,後來因為需要寫跨平台程式而切到Windows時,都覺得極端痛苦。因為Windows是給一般使用者的系統,而且所有程式都是獨立分開的,每次光要把開發環境準備好就要先耗上一整天在下載和安裝。後來我學乖了直接裝cygwin弄一個假的UNIX環境出來,但cygwin畢竟還是跑在Windows上,系統設計的哲學不同讓cygwin還是格格不入。(像是Windows就是沒有用文字檔存放系統設定,所以也沒辦法用一般的文字工具自動操作;Windows也沒有提供夠多的command line工具可以控制系統;Windows也沒有符號連結(symbolic link),我之前想用Bazaar check out一個有符號連結的repository就爆炸了…)

從Linux轉到Mac,讓我可以花更多時間專注在我想寫的程式上,而不是拿去研究driver的相容問題,或是Linux kernel新增的設定選項。對於一個應用程式或網頁程式的開發人員來說,這些底層的細節都是不重要的。雖然說Windows也把系統底層的細節藏起來了,但它實在藏的太徹底了。萬一偶爾需要看系統底層的訊息來debug,在Mac上還是跟Linux一樣直接到/var/log下grep一下就有了,但在Windows上除了「回報給微軟」外,也沒太多辦法可以自力救濟。

Mac上很多設計也改變了我使用電腦的方式。例如說QuickSilver讓我可以用鍵盤快速啟動任何程式,甚至是做更複雜的操作。Spotlight讓我不再需要思考怎麼把檔案文件分類整理到不同folder裡,需要什麼就像用google一樣只要直接用spotlight找就好了。Mac上的繪圖、設計軟體都有很貼心的設計,例如OmniGraffle的自動對齊線,可以幫忙使用者輕易設計出平衡、一致、美觀的圖像、網頁、或是圖形介面。Mac上幾乎什麼都可以自然地用drag and drop操作(例如Safari很早以前就可以把檔案拖到網頁裡上傳),但很奇怪Windows上就是有些地方可以有些不行。

整體來說,Mac是一個融合Windows和Linux雙方優點的平衡點,我可以像一般使用者一樣不費心力的操作電腦,也可以用高效率的command line處理複雜的任務,甚至是在需要的時候扮演hacker挖掘底層的錯誤訊息,或是利用Darwin Ports安裝和修改我需要的open source軟體。但除了Mac外,其實我還是有在用Linux,只是都跑在遠端的server上而已。主要原因是在沒有圖形介面時,Mac就沒有什麼優勢了。所以到現在即使我的laptop都改用Mac,我也還是會有一個terminal連到我的Linux server上。(雖然說主要是拿來掛IRC和BBS的…)


五月 7, 2010
» Do the right thing and do the thing right

這學期糊里糊塗的就忙過去了,回頭看看blog,學期中竟然連po篇文章的時間都沒有。(順便跟有留言的讀者道歉,之前太忙也沒時間回,留言似乎就這樣積到喜瑪拉雅山上了….)

因為畢業前一定要做一次助教,剛好老闆這學期開課人少不夠,就被拉去做助教了。在MIT做助教還真不是普通花時間,難怪拿的薪水比之前做RA還多。在這當助教一學期後,有個簡單的心得:全天下的學生其實都沒兩樣,MIT的學生也沒有比台大的學生厲害。以前在台灣當鄉民,聽過很多外國月亮比較圓的謠言,最經典的像是「美國大學生都不蹺課,因為學費很貴」(才怪XD MIT學費一年三萬多美金,蹺課的也多的是),「美國名校學生都強如鬼神,人人考試都100」(才怪XD 考試出來成績也還是常態分佈;期末project也一堆做得亂七八糟,能讓人眼睛一亮的一隻手都數不滿。)

以前我也在台大當過助教,相較之下,兩個地方能讓人眼睛一亮的學生比例其實差不多。這實在蠻令人納悶的,這兩個學校的學生原本也都是各地頂尖的「強者」,但被聚集在一起後,整體程度也還是回歸到常態分佈。(這就是所謂的人外有人,天外有天,一山還有一山高?)

觀察這些強者中的強者其實是蠻有趣的事,到頭來我覺得這些人其實也是普通人,一樣要吃飯睡覺,一樣有男/女朋友,一樣有各種千奇百怪的興趣。但唯一不同的是,這些強者似乎比較知道怎麼做「對的事」。

昨天我跟其他兩個助教加教授四個人馬拉松5個小時看了四十幾組的project demo,因為題目是各組自訂的,大家應該都是選了自己最有把握最有興趣的東西做。每一組都或多或少有做出點東西,有的組雖然做的功能很單純,但他們把這些簡單的事做得非常好;有的組雖然做了很多東西,但其實大多跟我們在意的重點沒什麼關係。

馬拉松一天後,晚上有個助教就收到其中一組的抱怨信。他們說10分鐘的demo時間根本不夠,他們花了很多心思把程式修到沒有bug,還花了很多時間做了功能A、B、C、D、E,但成績竟然不到全班平均。

收到這樣的信其實還蠻囧的。他們其實不是做得不好,只是根本沒搞清楚重要的事是什麼,所以雖然花了很多力氣,但方向完全就搞錯了,不重要的事做到200%也不會變重要。此外,更糟的是他們一直都沒有意識到哪裡不對了,所以才理直氣壯的來討分數。反觀能讓人眼睛一亮的組,他們一開始就花了比較多力氣確定要做什麼才是對的,一旦確定後,雖然做的事情可能比較小,但因為做了「對的事」並且也把事情「做對了」(do the right thing and do the thing right),成果就能讓非常人印象深刻。

一個最好的現代例子莫過於twitter。twitter的功能實在簡單到不行,在web 1.0甚至bbs時代就有一大票功能遠強過twitter的留言板或論壇網站,但twitter卻異軍突起了。原因很單純,twitter選擇了幾個對的事(WEB+限制長度的短訊+公開API),然後把他們做到最好。

Do the right thing and do the thing right雖然是很簡單的概念,但令人意外的,即使在世界上可能是天才密度最高的地方,卻還是只有非常、非常少人能同時做到。


五月 6, 2010
» Use Clipboard to Extract Text with Sikuli

Sikuli 0.10 has added tons of cool new features. Now it is easier to write smarter scripts to do more interesting and useful tasks than you can ever imagine. Here is one of my favorites. The original idea of this script was contributed by RaiMan, one of the most active Sikuli users. I simplified it a little bit and made a video to show how it runs in a real environment.

The source code of the Sikuli script that downloads a bunch of files.

The script to download a bunch of files.

The goal of this script is to download all ZIP files whose file name starts with “Sikuli-IDE-osx” in a web page. To find all ZIP files is easy, because they have an identifiable icon. However, we can’t simply click on the icon. We need to click on the hyperlink next to the icon, instead. The really tricky thing is, how to know a hyperlink that starts with “Sikuli-IDE-osx”?

The simplest solution is capturing a screenshot of the text “Sikuli-IDE-osx”, and putting the screenshot as the parameter of click(). Unfortunately, this way is not really robust since the images of text only have tiny differences. Sikuli’s fuzzy image matching engine may treat “S1kul1-1DE-esx” as the same as what we want. So, a right way to do this is – extracting the text from the web page.

You may recall that there was an ancient technology named OCR (Optical Character Recognition), which recognizes text from scanned books. However, current OCR engines do not really work well. They are slow and inaccurate.

In fact, even without OCR, we still can extract text from the screen using Sikuli.

How?

Use the clipboard!

The following script tells you how to do that. At first, we use Sikuli to find all locations of the ZIP icon (line 7). On line 8, we sort the list of the matched locations by their y coordinate, it’s not necessary though. The key steps are line 10 and 11. We click on the space between the icon and the hyperlink next to it using the new target offset attribute of a pattern. (denoted by a small red cross in the ZIP icon on line 7. See the figure below for its setting window.)

And then we hold the mouse button and drag to the location 600-pixel right to the center of the icon. This step (line 2) actually simulates using a mouse to select a line of text with a dragDrop(). After the selection, we simply press Command+C (Ctrl-C on Windows) to copy the selected text into the system clipboard.

Copy (extract) text from a browser.

Aha! We got the precise text in the clipboard. :)

The rest of the script are trivial. Sikuli 0.10 provides a new API Env.getClipboard() to get the content of the system clipboard. We can use this function to get the text of the hyperlinks and then use Python’s string function (startswith) to filter out the files we need.

I also made a tiny video that shows how this script looks like when it is running.

五月 3, 2010
» Sikuli 0.10 is coming!

We are very excited to announce that Sikuli 0.10 is coming!

Since the success of of Sikuli 0.9, we have heard lots of suggestions and feature requests from the world. Sikuli 0.9 was a research prototype for showing the possibilities of applying computer vision techniques to the desktop environment. It was cool, but not very solid and well designed. So, we decided to redesign and rewrite (almost) everything to make a faster, more robust,  more flexible Sikuli.

Sikuli 0.10 will be a more comprehensive visual automation library for both Java and Jython. Novices can still simply use the basic functions, such as click, type, and dragDrop, with screen shots without learning anything new. Advanced users can restrict the searching region on any screen more easily. You also can click on a position that is next to the found visual target. It is especially useful for scripting games that have an arrow to indicate what to do (Fig. 1).

Fig. 1. Clicks on the "hammer" that is below the found target "arrow".

Sikuli 0.10  provides a new programming model – visual event driven programming (Fig.2). You can run a Sikuli Script in background to monitor certain visual events (something appears, disappears, or changes), and the specified event handling function will be called once the monitoring events happen.

Fig. 2. The function "darker" is called when the "Charged" icon disappears.

Sikuli IDE 0.10 also becomes better. A command toolbar that lists the core Sikuli commands and their usage inserts a line of command with just one click. Now it is possible to write a Sikuli script without typing a single line of code!

Sikuli IDE 0.10

We also support internationalization(i18n) since Sikuli 0.10. We already have Traditional Chinese and German interfaces now. The whole interface can be easily translated to your languages. Come to the Translation page on our Launchpad page to help translation!

Sikuli IDE with a Traditional Chinese interface.

Low-level keyboard and mouse actions, such as keyDown(), keyUp(), mouseDown() and mouseUp() are also supported for advanced operations. In addition, multiple screen environments are also supported. It means you can run Sikuli on the second monitor without messing up the working desktop on the primary monitor.

Sikuli 0.10 also becomes more universal. It will support 64bit platforms, including 64bit Linux, 64bit Mac OS X, and 64bit Windows.

Finally, we know the importance of good documentation, so we will release a reference book: The Complete Guide to Sikuli Script, which contains the usage and examples of all classes and functions in Sikuli. We hope the guide can give you a better understanding of Sikuli and assist you in learning Sikuli without trial-and-error.

Can’t wait anymore?

In fact, you don’t need to wait too long. You can get it tomorrow!!

三月 2, 2010
» Sikuli plays a piano

Sikuli is not only visual but musical. ram B has uncovered Sikuli’s musical potential with a creative script that plays a virtual piano. The script opens a browser and opens up an online virtual piano. Then it asks for an input to choose from a collection of two songs: Terminator’s theme and Godfather’s theme.

The whole script is shown below. You can also download the script to try it out on your computer. Enjoy!!

三月 1, 2010
» Sikuli signs in Twitter and tweets

A while ago we posted several examples of automatic tweets on Twitter sent by Sikuli. Andrew Burton (a.k.a. jarod), from whom one of these tweets were originated, sent us a Twitter script he created that does much more than the simple example we showed last time. This script not only sends a tweet but also signs in one’s Twitter account. When the script is run, it prompts the user for signin id, password, and message. Then the script goes about looking for various buttons to click and text fields to type. In the process, it starts a web browser, types the address of Twitter, waits for the Twitter logo to appear, clicks on the sign-in button, types the login and password, clicks the message box, types the message, and finally clicks the update button to submit the tweet.

The whole script is shown below.

二月 28, 2010
» Sikuli searches Picasa photos and starts a slideshow

Many thanks to ram B for contributing another interesting script. The purpose of the script is to search for pictures on Picasa. The script first opens Picasa in Firefox browser. Then in this example it enters a keyword “cars” and clicks on the “search” button to submit the keyword. Unlike Flickr search, in Picasa, one has to click the “play” button even after clicking the slide show button. So this script will start the slide show increase the speed by 1 sec, hit the play button and will close the window after displaying around 10 pictures.

The full script can be seen below.

二月 27, 2010
» Sikuli automates FFXI login

FFXI (i.e., Final Fantasy 11) is one of the most popular online RPG games, but notorious for its ridiculously long and tedious login process. firewing at the Bluegarttr created a Sikuli script to automate this process. By exporting the script to an executble (.skl) file and placing a shortcut on the desktop, all one needs to do to start playing FFXI is to double-click the shortcut. How easy!!

The full script annotated by the author is shown below.

二月 26, 2010
» Sikuli plays Beatles radio

Today’s showcase script is contributed by Ram B for tuning in to an online radio station on last.fm to listen to Beatles music. This script launches Firefox, types “www.last.fm” in the address bar, types “beatles” in the search box, clicks the “GO” button to confirm the search, and finally clicks on “Play The Beatles Radio” button to play. The entire script can be viewed below.

A Feedjack powered Planet
A Django site.