Saturday, August 29, 2009

自己的罩門是什麼?

自己的罩門是什麼?

人非聖賢無法百分之百的完美,所以,每個人身上一定有自己最弱的之處,這個死穴我們可以將它稱之為「罩門」,而人在職場上如果自己的「罩門」過於容易暴露,或者是與自己工作職能相衝突,相信絕對會影響自己未來的發展。

前陣子與一位人資界的好朋友,在聊我們彼此都認識的另一位多年老友,這位老友不管在學習的精神與努力的態度與聰明智慧等,都在我們兩人之上,不過,很可惜的卻是這位老友格局不夠大,而且很難聽的下別人的建議,更糟糕的是他做事情的方法常常讓團隊成員,對他非常的排斥,我的好朋友跟我聊到最後用了「這是他的最大罩門」這一句話來做為對這位老友的評論,因為這位老友一直無法突破自己的「罩門」,因此,也就侷限了他職涯整個的發展與限制。

什麼是「罩門」呢?我們用練功夫來做比喻,凡是練金鐘罩或鐵布衫這一類功夫的人,身上總會有一兩處功夫練不到的地方,這就是「罩門」,一個武功大師如果練成了金鐘罩,全身可以刀槍不入;但只有罩門例外,罩門如果被人發現,用重手法一戳,武功即廢,這也說明了「罩門」是一個人的最大死穴,只要無法破除或遮掩這個部位,比武時有可能就會因此遭致了失敗的命運。

在職場上我們常常會看到很多感覺非常優秀的人,卻因為自己存在的一些跟自己工作、職務有關職能相衝突,結果沒有如大家所預期般發展的很好,令人感到十分的惋惜,我相信人非聖賢絕對不可能百分之百的完美,所以,每個人絕對有自己的「罩門」,只是如果這些「罩門」不能做有效的遮掩或改善,或者是自己的「罩門」與自己現在的工作與職務上無法相容,可能就會成為自己「致命」的要害了,而有時更令人覺得難過的是,很多人並不知道或並不認為自己的這些問題,最後會成為嚴重影響與阻礙自己在職場發展的「罩門」,這才更讓旁人覺得唏噓不已。

人要懂得去學習如何避免讓自己的缺點變成「罩門」,我想了解自己的問題並不困難,最難的就在於如何去認知、面對與改善自己的問題,其實並非所有的缺點都會成為自己的「罩門」,有時候我們可以藉由學習與改善來讓自己的「罩門」降低對自己在職場或在工作上的傷害與影響,這時候如果週遭有很好的「良師益友」更可以讓自己即時的發覺這些缺點與問題,趁早改善以避免最後嚴重到形成無法遮掩的「罩門」,那可能就真的很難去補救了,所以,年紀越輕的人,只要能早點知道與面對自己的缺點與問題,就比較容易去改善這些缺點,相對的等到年紀越大時,要去面對與改變自己的缺點與問題,相對的就困難多了。

人在職場要隨停下來思考,是不是自己有些不知道的狀況,已經成為自己的「罩門」,或是自己已經有哪些小「罩門」,可以趕快去遮掩與修改的,否則一旦有天等到自己上了擂台對決時,這些「罩門」將會成為自己未來被打下擂台的關鍵要素了。

Friday, August 28, 2009

安身立命的起點-----「絕對自信」Absolute Self-confident

安身立命的起點-----「絕對自信」Absolute Self-confident




今天電視上有報一個新聞很妙,就是說最新一期樂透彩9.2億的得主,被朋友控訴其侵
吞大家集資買彩券所得到的頭獎獎金。朋友為錢而反目對簿公堂,實令人不覺莞爾
而諷刺。

美國曾經對各屆樂透彩得主作過長年的追蹤研究,結果發現,樂透彩得主的下場幾乎都
不太好

●有因為在電視上公開露面而遭歹徒搶劫而死於非命者
●因為突然成為暴發戶,於是紙醉金迷,身體狀況急遽惡化而魂歸離恨天者
●財產分配不均而遭親人仇視或殺害者
●因遺產龐大而遭法定繼承人謀殺者

上面是死掉的,而沒死的則有以下後遺症

●生活習慣與價值觀改變,喪失了原本生活與工作的目標
●對物質需求的胃口被養大了,能夠使他們更滿足的東西變少,人生反而變得無趣
●家人失和、反目,因為只要家人有誰遇到金錢問題,一定先找這個樂透彩得主要錢
●因為錢來的容易,所以不會珍惜,而因為不會珍惜,所以亂花錢,又因為亂花錢,惡化了人際關係與健康
●結果竟然發現錢買不到快樂,還耽心錢會被偷走,患得患失、抓了怕死,不抓怕飛,成為被錢制約的人
●不再能感受單純而小成本的快樂了--例如:撿到錢不會快樂、被請客不會快樂、摸彩摸到大獎不會快樂、被
贈送禮物不會快樂、辛苦工作賺到小錢不會快樂、什麼都有了,於是「心」不見了。

這樣說起來,有錢的困擾還真的也不小。


這告訴我們的答案己經很清楚了

「幸福的核心關鍵在於心靈感受的時空結構主體,而不在會隨時空而變化的物質客體」


美國有位知名的諮商心理學家曾言

「西方近年來所有關於心理學的討論,基本上不會超過二位心理學大師所曾思考過的範疇
一位是談原欲與成長歷程是如何影響人們潛意識與選擇的佛洛伊德,一位則是研究人們自信心如何
建立與如何崩潰的阿德勒」

當然,其他學派可能不一定同意這位心理諮商師的說法,切入的角度也可能有所差異,不過
他的這個宣稱,雖不中亦不遠矣。

看過富爸爸與窮爸爸的人會告訴你----「有錢人想的與你不一樣」

了解吸引力法則的人會告訴你--「你的頻率會吸引相同屬性的人事物到身邊」

了解佛法的人會告訴你---「佈施是福德資糧的基礎,是人們可以得到金錢等福報的原因」

了解心理學的人會告訴你--心胸寬大,願意主動服務奉獻的人,人們比傾向於信任他們,願意與他們合作

了解賽局理論與遊戲理論的人會告訴你-----發自內心為對方考慮且坦承合作的人,才有機會好處全拿,打造雙贏

了解演化機制的人會告訴你----「族群間演化所構成的集團力量,遠勝於族群內演化所打造的自私強者」


不過,各位啊,以上的例子其實都只是「現像」的應用,都很好,但並不是真正最核心的關鍵。

真正的關鍵是本體,是隨緣不變、不變隨緣的「本體」


把妹達人說:「如果男生對自己沒有自信,女生自然不會喜歡這個人」

銷售達人說: 「如果業務員對自己的產品沒有信心,任何顧客都會從業務員的表情、動作等小地方觀察出來」

開悟的師父說:「如果老師對自己學到的東西也感到沒有價值,學生自然也不會有想要學習的動機」

心理醫生說:「如果一個人從小是在被否定的教育中長大,末來一生中的大部份能量,都會消耗在與這份自卑抵抗上面」


於是我們要問


「我們到底要怎麼找到「絕對自信」?」


我們或許反過來問比較快

一定要成為有錢人以後,人才可以有自信嗎?

女生一定要變得漂亮以後,才會覺得有自信嗎?

男生一定要有才華、有型,才會覺得有自信嗎?

學生一定要考第一名,才會有自信嗎?

醜女一定要整型後,才會覺得有自信嗎?

受苦的人或貧窮的人,一定要接受了人家的施捨,才會不那麼痛苦嗎?


其實聰明的人會知道,上面的問題,答案是「也對也不對」

說對的原因是------人確實在某個時間點,會覺得我們需要這些外在的條件來支持我們,或是彌補我們內心的坑洞,或是
解銷我們的欲望、或是完成我們一開始不知為何要設定成如此的「內在故事」。

但說不對的原因是---人的注意力很偏窄,因此不可能有人全拿,而全拿的人反而又會像樂透彩得主一樣------「全失」
這是哲學上必然的「二律背反」


很多天才都會想自殺,因為他們太早得到自己以為得到就會一直快樂的東西了

梅蘭芳會成為梅蘭芳,正因為他的孤寂,他如果很早就得到了他想要的,他就得不到後來他想要的


公司經營的好,因為太忙了,人會病倒
公司經營不好,因為沒錢賺,公司會倒

有鴻福就不會有清福,想要靠外表來享受福利的人,就要接受被人說靠那張臉的批評,想要得到眾人尊敬的地位,得到時
就會想,得不到自己的肯定好像反而更空虛?

帥哥與美女聽說都不太能在心靈世界有太大的長進,因為他們「認知」到了自己是比別人「好看」的,所以有意或無意下
在「機會成本」的考量上,把大部份的時間拿來「應用」在可以靠「外表」來得到的「福利」上面而「浪費」太多「時間」。

而如果「帥哥與美女」不想浪費時間去得到別人的肯定與仰幕,那「漂不漂亮」就不是重點了。


所以答案不就很清楚了嗎?

不管你現在是貧是富、是聰明是笨、是好看或長的難看,某方面有優勢某方面就構成劣勢,得到的同時,失去的可能是
一份學習的心,可能是一種謙虛、可能是一種本來良善的價值觀、可能是寶貴面對自己的時間、可能是讓身體健康的悠
閒、可能是道德良知。

認識到自己在這個無常的世界裡,大家看起來有前有後,但實際上卻都是在同一個「原點」上的人。就會知道「自信」
了不可得。

完全了不可得之後,會發現一種否極泰來的「絕對自信」(absolute self-confident)

本體是「不動的自動者」所以它「能善能惡者,為善惡所不能。」

能善能惡者是「本體」
善惡所不能是指「現像」


而認識到本體,就能認識到何謂「絕對自信」。


8推薦此文章 推 收
Add a Bookmark: Yahoo!奇摩 BookMark Furl BookMark Technorati BookMark HEMiDEMi BookMark MyShare BookMark udn BookMark funP BookMark del.icio.us BookMark
Today's Visitors: 73 Total Visitors: 1032
You can leave comment to this collection

Collection Category: Add Collection Category
Collection Comment:

Personal Category: Uncategorized Articles Topic: creation / image / comics
歷史上的今天:
:失之毫釐、差之千里
:藍圖正確的話,方能從一而終----談工作的真相
:生活品質的閥值--有錢人不是喜歡有錢,而只是無法忍受貧窮
gradlive at 無名小站 at 03:32 PM post | Reply(21) | Trackback(0) | Collection(1) | prosecute
[Trackback URL]

Reply

*

1樓

1樓搶頭香

說得真好!!
自信才能散發光采!!推~
* shyan6811 at August 27, 2009 03:39 PM comment | prosecute

*

相信自己之後,別人也才會相信我們哪
* Blog Owner at August 28, 2009 04:15 PM Reply

*

2樓

2樓頸推

金錢和精神是硬幣的兩面 缺一不可
* Tzar at August 27, 2009 03:40 PM comment

*

色不亦空、空不亦色嗎?
* Blog Owner at August 28, 2009 04:15 PM Reply

*

3樓

3樓坐沙發

大大的意思我懂,
我還是覺的這年頭還是有錢比較好~~~
但還是要有健康的身體才有用~~

如果有人嫌錢多的,可以給我!!
感恩!!

吉米
* 吉米 at August 27, 2009 05:25 PM comment | email

*

我可以給你十塊錢
* Blog Owner at August 28, 2009 04:16 PM Reply

*

4樓

福樓

我也有想過要寫一篇「絕對自信」的文章
你這文章寫的不錯
如果我要寫的話,我認為絕對自信來自於對自我的認知,自信的來源是你未來的自己
如何?不錯吧?
* 于文強 at August 27, 2009 06:43 PM comment | email Homepage

*

絕對自信來自於對自我的認知,自信的來源是你未來的自己

很讚的想像

自信的來源是未來的自己,這還算好理解
對自我的認知是指什麼呢 ?

願聞其詳,我們把絕對自信的哲學理論基礎完整的建立起來
* Blog Owner at August 28, 2009 04:18 PM Reply

*

5樓

專業的5樓

看完後有種,原來"真愛原來就在身邊"的感覺...

站在原地,也是種進步,看不到的進步(這樣的解釋有點怪)
* wliomsky at August 27, 2009 08:42 PM comment | Homepage | prosecute

*

沒錯啊,你抓到我要表現的精華之十有七八了
* Blog Owner at August 28, 2009 04:18 PM Reply

*

6樓

6樓

善知識!正知見哪!~~~~(瘋狂吶喊中!!!!)

陽明心學有同樣的說明
只是用語不同~
* tearknows at August 27, 2009 10:12 PM comment | prosecute

*

陽明心學是怎麼說的呢

願聞其詳
* Blog Owner at August 28, 2009 04:18 PM Reply

*

7樓

7樓

看似很有道理!!但假設今天有1億放在你面前,你要拿嗎!!??
或許這就是這社會的生存道理
* lv2410 at August 28, 2009 01:40 AM comment

*

可拿可不拿

如果拿了一億,會對別人造成傷害我就不拿

如果有人沒事要給我一億,當然就拿啦,不會客氣的,而且要承諾自己,拿了後要好好利用

說起來「錢」也只是一種「概念」,不把錢當錢,才會自己流進來
* Blog Owner at August 28, 2009 04:20 PM Reply

*

8樓

8樓

最近研究量子力學的哲學啟示,

的確宇宙的根本是與我們的大腦有絕對的關係,

版主的這幅漫畫我覺得很能表達量子力學中的ㄧ個重要現象,

"漸進自由",

真是踏破鐵鞋無覓處,得來全不費工夫。
* Klein Bottle at August 28, 2009 05:12 AM comment

*

是的,宇宙實相與我們某種意識成份的觀察有關。

說來實是一言難盡
* Blog Owner at August 28, 2009 04:21 PM Reply

*

9樓

9樓

絕對自信,意味著能夠隨心所欲做自己,這很困難阿

我們所做的只能在眾多機會中,做出最好的選擇,而幸福與痛苦是靈魂的體驗

相信我,有競爭力的人絕對會自信許多

但是遇到的是自我感覺良好的人;,就很OOXX
* at August 28, 2009 07:15 AM comment

*

絕對自信,換個角度來說,就是活在當下
* Blog Owner at August 28, 2009 04:22 PM Reply

*

10樓

10樓

說的真好 內裏的本質才是最重要的
* TingGang Syu at August 28, 2009 08:07 AM comment

*

沒錯,這是對內在莊嚴華美的肯定
* Blog Owner at August 28, 2009 04:22 PM Reply

*

11樓

11樓

精神與金錢 內在與外在我都覺得很重要耶!
也希望自己都能得到
是因不是因為這樣太貪心 所以我永遠不滿足?
也常看見自己與別人 其實都不夠好

事實上 凡事講求平衡
當我們有足夠的智慧去平衡能影響我們內外在的一切因素
對於任何處竟都能有智慧去看穿這一切的本質與現象
進而去接受
我想 有錢 沒錢 能不能快樂?
那就要看那個人的智慧如何解釋囉

一切的痛苦 都來自於 我還沒有足夠的智慧去化解與解釋目前這一切
於是乎 我擁有著凡人的七情六慾 痛快也痛苦著

還是早點學佛 修身養性去好了 ㄏㄏㄏ
* brain453969 at August 28, 2009 08:14 AM comment | prosecute

*

佛法中說「依正不二」

因此也只有在一個「無苦、無業」的境界裡談「無惑」,才是正解

從這個角度來看,我們還是要有物質,只是不被物質所控制

仁者役物,而不役於物,這樣就還蠻好理解了。

話說回來

妳的二極性也很明顯

不是追逐,就是完全捨棄,好像沒有中間項哩…

(我發現我也有這種傾向,如果不是有朋友這樣提醒我,我也不會發現這點,人心的細微毛病,還
真是不容易察覺哪)
* Blog Owner at August 28, 2009 04:25 PM Reply

*

12樓

12樓

基於以上
中樂透後 得到不幸的事件
那證明那些得主 還沒有足夠的智慧去處理 中樂透獎後的一切內外在改變的生活

不過說真的
我寧可中了樂透後 再去學這個智慧
請上天 用實質的案例來敎我 謝謝 哈哈ㄏ
* brain453969 at August 28, 2009 08:17 AM comment | prosecute

*

「富者有富者的困擾、貧者有貧者的困擾,相較之下,我還是當富者比較好」

「窮的只剩下錢」---不過還好還有錢

某個角度來說,有些真理當然是在我們還沒成功時才可受用的
因為這個境地只能這樣想
如果不這樣想

不就自討苦吃了嗎?

話說回來,近年來樂透得主想法比較開明,也更能善用這筆錢
以往的慘痛歷史,應該也比較不會發生了

這或許又是性格召喚命運的一大佐証。
* Blog Owner at August 28, 2009 04:29 PM Reply

*

13樓

13樓

我想有一些是度眾的方便,金錢,外表,等等外在的事項本身並沒有過失,端視如何運用.
為何需要方便呢?.....因為眾生"需要"啊.
* Joe at August 28, 2009 08:54 AM comment

*

沒錯,現像的應用是為了隨緣,但本體依然不動
* Blog Owner at August 28, 2009 04:30 PM Reply

*

14樓

14樓

說的好,但也並非全對
很多事情都有其一體兩面
也不能以偏概全的一桿子打翻一船人
前陣子不就有一對夫妻在中了獎後
將獎金中很大的一部分拿出來捐做善款嗎?
所以同一件事情在不同的人身上
會看到不同的結果
俗語說的好:一樣米養百樣人
端看當事人是否有足夠的智慧啦!
* ydnlhojwp at August 28, 2009 09:11 AM comment | prosecute

*

嘿呀,現在的人想法比較靈活了,對金錢的觀念不像以前那麼死
這是好現像

代表人能役物,而於役於物了
* Blog Owner at August 28, 2009 04:31 PM Reply

*

15樓

15樓

多謝團長開示~~
我確實有這方面問題,所以人生規劃上以成果作導向
有時因此快要氣炸=.="
* 居隱 at August 28, 2009 10:32 AM comment | Homepage

*

您想要完成的成果是什麼呢?
我感覺你的夢想也是很遠大捏
* Blog Owner at August 28, 2009 04:31 PM Reply

*

16樓

16樓

警察:「鳳飛飛沒戴安全帽...」(拖走)
* layles at August 28, 2009 03:15 PM comment

*

有啦,她只是沒戴好,下巴的地方沒綁啦
* Blog Owner at August 28, 2009 04:32 PM Reply

*

17樓

17樓

我會提到陽明心學
主要是因為團長最後的敘述有關於本體與現象之說
其實西方哲學也有探討
而且比中國哲學明確很多

就陽明心學而言
最主要就是談心性論
談心的本體與作用
所以勞思光認為陽明心學是先秦以後儒學發展史中
最接近孔孟儒學心性論者
當然這裡不能詳談

就心的本體與作用而言
本體大致上與團長所述說的本體內含是融貫的
而作用大抵就是心所指導表現出來的外在作為
也就是形成現象

先談到這裡

明天有空我繼續敘說

團長我要下班了

晚安!
* tearknows at August 28, 2009 08:54 PM comment | prosecute

*

18樓

18樓

有種駭客任務的FU
* plcwalker at August 28, 2009 10:18 PM comment | prosecute

*

19樓

19樓

當大家似乎都得道...
我還看的懵懂時,有些挫敗!=_=
但我喜歡大大的圖,
很簡單卻很有感覺,
我果然對文字很不在行:P
* ohmygod248 at August 28, 2009 11:13 PM comment | prosecute

*

20樓

20樓

隨緣不變 不變隨緣 隨緣而不隨俗

Thursday, August 27, 2009

發現好工具:CommitMonitor

發現好工具:CommitMonitor

我們在使用 Subversion 做原始碼版本管理的時候,常常要主動去使用 Show Log 檢查到底專案有沒有別人改過什麼,但因為很多人會忘記看 log 就開始拼命寫,導致下班前才在解決衝突的問題!

今天發現一個很棒的工具,叫做 CommitMonitor,網址在 http://tools.tortoisesvn.net/CommitMonitor

這個小工具可以縮在系統匣(System Tray)中,程式本身執行的時候佔的記憶體很小不太會吃系統的資源,且可以定時去 SVN 儲存庫檢查你參與的專案是否有其他人 commit 了新東西進來,如果有就先看一下 Log 再說。

如何用 TortoiseSVN 復原錯誤的簽入動作

如何用 TortoiseSVN 復原錯誤的簽入動作

在一個開發團隊裡,當有人將錯誤的程式碼簽入(Commit)到 Subversion 儲存庫(Repository)去,的確會造成許多人的麻煩,這時程式開發經理應該就要立即出面,將這類的問題排除。

如果目前最新的版本(Revision)是 9 的話,你可能想要將版本復原到 Revision 8,這時候有兩種方法可以做:

1. 透過 Update to revision.. 將目前的程式碼更新至第 8 版



但這種作法是錯的!

因為這方法只是將你的工作目錄更新到舊的版本(第 8 版),這時重新所做的修改其實都會失敗,因為當你要 commit 的時候,Subversion 就會告訴你必須先更新(SVN Update)過才能 commit,到時就會發生衝突!

2. 透過 Merge (合併) 將目前的程式碼合併到第 8 版



這才是正確的作法!

因為這等於是將目前的版本 ( 第 9 版 ) 直接合併到第 8 版去,現有的工作目錄還是處於第 9 版的狀態,只是所有程式碼因為執行合併的關係而變成第 8 版的內容而已,當你 Merge 成功以後,還必須 commit 一次,讓第9版修改後的程式簽入到儲存庫 ( 成為第 10 版 ),這時的第 10 版就會跟原本的第 8 版一模一樣了!此時,再請專案成員做一次 SVN Update 就可以讓大家回復到正確程式碼的狀態了!

而將目前的 Revision 合併回上一個 Revision 的方式如下,以下將以 TortoiseSVN 工具做說明:

先在工作目錄的根目錄顯選取 SVN Merge 功能






在 From: 的地方選取 "HEAD Revision" ,在 To: 的地方選取 Revision 並設定到你想要還原到的版本編號 ( 此範例是 8 ),最後按下 Merge 按鈕



此時你將會看到在工作目錄下的檔案已經被異動了,最後再執行 SVN Commit 就可以復原成功了!

介紹好用工具:WinMerge

WinMerge 幾乎是我每天必用的軟體之一,他可以幫我比對我在 Subversion 受控管的檔案差異,也可以幫我比對兩個目錄的檔案差異。最主要來說是用來替換掉 TortoiseSVN 內建的 Diff 工具,因為 TortoiseSVN 內建的 Diff 工具對中文字的顯示有些問題,改用 WinMerge 就會好很多。使用 WinMerge 幾乎不用看手冊就會操作了,而且跟檔案總管也整合的十分的好,比對目錄時只要選取兩個資料夾按右鍵選 WinMerge 就會進行比對了。

檔案比對圖例







目錄比對圖例







安裝好 WinMerge 後的預設「選項」我是建議修改一下,讓使用的時候比較順暢一些,以下是我習慣的設定:

一般:勾選「自動捲至最初差異」





比較:比對空白通常沒什麼意義,且檔案多按了個 Enter 也不需要大驚小怪的,斷行符號也不是挺重要的。





編碼頁:我們的程式檔案通常都是 UTF-8 編碼,使用「系統用的編碼頁」在繁體作業系統是 Big5,常會造成無法比對的情況。





相關連結

WinMerge

Is there an easy way to rebuild everything (kernel, base system and installed ports) without IPv6 support?

Is there an easy way to rebuild everything (kernel, base system and installed ports) without IPv6 support?

"NO_IPv6" hook in make.conf or something similar?

Create / update your /etc/src.conf file with the following:
Code:

WITHOUT_INET6=yes
WITHOUT_INET6_SUPPORT=yes

Once done; do make buildworld
Code:

make buildworld && make buildkernel && make installkernel

See handbook build world chapter and http://man.freebsd.org/src.conf

Yes, do check out the proper way of building kernel and world, because the suggested order is incomplete. See /usr/src/Makefile for the 11-point list you should use.

Yes, thank you for pointing this out. I saw "make delete-old-libs" last night. My first rebuild was up to point #10 as it's shown /usr/src/UPDATING.

...Addition: Something is not clear. "delete-old" includes "delete-old-[files,dirs,libs]". Is point #11 redundant?

delete-old does *not* remove library files. delete-old-libs has to be run separately in order to delete library files.


I've just finished rebuilding world without IPv6 and saw that. Even though /usr/src/Makefile states:
"delete-old: deletes obsolete Directories/Files/Libraries"
issuing "make delete-old-libs" after "make delete-old" cleared some additional files.

Wednesday, August 26, 2009

HOWTO - Define an SPF Record

HOWTO - Define an SPF Record

This section defines HOWTO configure a Sender Policy Framework (SPF) record for a domain and its mail servers.

The macro feature of SPF was incorrectly documented using parenthesis, these should have been braces ({}).

SPF was initiated by Meng Weng Wong of pobox.com to enable validation of legitimate sources of email for a domain and is now an IETF standard (RFC 4408).

Briefly, the design intent of the SPF record is to allow a receiving MTA (Message Transfer Agent) to interrogate the Name Server of the domain which appears in the email (the sender) and determine if the originating IP of the mail (the source) is authorized to send mail for the sender's domain.

The SPF information SHOULD be defined in a standard TXT RR and MAY now be defined in an SPF RR type (BIND releases from 9.4.0 support the SPF RR type - see also RFC 4408).

If a SPF (TXT) RR exists and authorizes the source IP address the mail can be accepted by the MTA. If the SPF (TXT) RR does not authorize the IP address the mail can be bounced - it did not originate from an authorized source for the sender's domain.

Many Open Source MTAs have already been modified to use the SPF record and there is no down-side (assuming you get the SPF RR right) and plenty of potential up-side (elimination/reduction of some spam categories) to implement the SPF record now.

We use the following terminology to try and simplify the descriptions below:

sender - the full email address of the originator of the mail item (typically uses return-path in the actual SPF checks)

source-ip - the IP address of the SMTP server trying to send this message

sender-domain the domain name part of the sender's email address e.g. assume the sender is info@example.com the sender-domain is example.com.

The SPF record defines one or more tests to carry out to verify the sender. Each test returns a condition code (pre below). The first test to pass will terminate SPF processing.

TXT RR Format

The standard TXT and SPF record format is defined as:

name ttl class TXT text

name ttl class SPF text

The SPF RR is functionally identical to a TXT record with SPF data. BIND 9.4+ supports the SPF RR type, however previous versions, and most other DNS software (as of July 2007), do not yet support the SPF RR type. Thus the RFC's recommendation is to always provide a TXT based SPF RR and, if your DNS software supports the SPF RR type, duplicate the information from the TXT version of the SPF RR in a native SPF RR. The reason for this procedure is simply because while the master/slave may support the SPF RR, querying name servers - such as name servers used by receiving MTAs - may not. Some, but not all examples, below have been updated to reflect the use of both record types to illustrate usage. In all cases the TXT and SPF RRs are shown with a comment line between containing the word AND as a reminder of the current policy recommendation. It is safe to assume for the foreseeable future that only using a TXT version of the SPF will always work.

The SPF data is entirely contained in the text field (a quoted string). SPF defines the contents of the quoted string as follows:

v=spf1 [[pre] type ] ... [mod]

Where:

v=spf1

Mandatory. Defines the version being used. Currently the only version supported is spf1.

pre

Optional (defaults to +). pre defines the code to return when a match occurs. If a test is conclusive either add + or omit (defaults to +). If a test might not be conclusive use "?" or "~" (tilde). "-"(minus) is typically only used with -all to indicate that if we have had no previous matches - fail.

Value

Description

+

Default. Pass.

-

Fail.

~

Softfail.

?

Neutral.

type

Defines the mechanism type to use for verification of the sender. May take one of the following values:

Basic Mechanisms

These types do NOT define a verification mechanism but affect the verification sequence.

include - Recurse (restart) testing using supplied domain. The sender-domain is replaced with the included domain name. Example:

; spf record for example.com

example.com. IN TXT "v=spf1 include:example.net -all"

; AND

example.com. IN SPF "v=spf1 include:example.net -all"

; use the SPF details for example.net

; in the above case to replace example.com's SPF

; or

example.com. IN TXT "v=spf1 mx include:example.net -all"

; additive - use MX RR for example.com

; AND if that fails use example.nets's SPF

all - The all type terminates processing (but may be optionally followed by a mod value). It is defined to be optional but it is a Good Thing™ to include it. It is normally present in the form -all to signify that if processing reaches this point without a prior match the result will be fail. But if you are not sure that the tests are conclusive you could use ?all which would allow mail to be accepted even if all previous checks failed.

Sender Mechanisms

These types define a verification mechanism.

ip4 - use IP Version 4 addresses, for example, 192.168.3.0 for verification

ip6 - use IP Version 6 addresses for verification

a - use DNS A RRs for verification

mx - use DNS MX RRs for verification

ptr - use DNS PTR RRs for verification

exists - test for existence of domain

Value

Description

a

a:domain

a:domain/cidr

a/cidr

In its base form this uses the sender-domain to find an A RR(s) to verify the source. This form relies on an A RR for the domain as shown:

; fragment for example.com

$ORIGIN example.com.

example.com. IN TXT "v=spf1 a -all"

; AND

example.com. IN SPF "v=spf1 a -all"

; needs domain A record

@ IN A 192.168.0.3

; functionally the same as

example.com. IN A 192.168.0.3

The form a/cidr applies the test to the cidr (or IP refix or slash) range of the sender-domain's A RR. For more info on CIDR.

The form a:domain replaces sender-domain with domain's A RR for verification. This does NOT use domain's SPF record(s) (use include for that). The domain form may use macro-expansion features. Example:

; fragment for example.net

$ORIGIN example.net.

@ IN TXT "v=spf1 a:example.com -all"

; AND

@ IN SPF "v=spf1 a:example.com -all"

; will use a single A query to example.com

; which may not yield the result expected unless

; example.com has an A record as below

@ IN A 192.168.0.3

; functionally the same as

example.com. IN A 192.168.0.3

can take a host name format as shown below:

; fragment for example.net

$ORIGIN example.net.

@ IN TXT "v=spf1 a:mail.example.com -all"

; will use a single A query for mail.example.com

The form a:domain/cidr applies the cidr range to the IP address obtained from the A query e.g.

; fragment for example.net

$ORIGIN example.net.

@ IN TXT "v=spf1 a:mail.example.com/27 -all"

; AND

@ IN SPF "v=spf1 a:mail.example.com/27 -all"

; will use a single A query for mail.example.com

Any of the 32 IP addresses that contain mail.example.com will pass. e.g. if the source-ip is 192.168.0.25 and the A RR for mail.example.net is 192.168.0.2 then the test will pass.

mx

mx:domain

mx:domain/cidr

mx/cidr

This basic form without any extensions uses the MX RR of the sender-domain to verify the mail source-ip. The MX record(s) return a host name from which the A record(s) can be obtained and compared with the source-ip. The form mx/cidr applies the IP Prefix or slash range to the A RR address. For more info on CIDR. With any of the domain extensions the MX record of the designated (substituted) domain is used for verification. The domain form may use macro-expansion features.

Warning Remember the MX RR defines the receiving MTA for the domain. If this is not the same host(s) as the sending (SMTP) MTA then tests based on an mx type will fail. We have also received a report that mx on its own is rejected by certain SPF libraries. We regard this as an error and are trying to contact the library developer to clarify issues.

Examples:

; fragment for example.com

$ORIGIN example.com.

IN TXT "v=spf1 mx:example.net -all"

; AND

IN SPF "v=spf1 mx:example.net -all"

; verify sender using example.net MX and A RRs

; fragment for example.com

$ORIGIN example.com.

IN TXT "v=spf1 mx/26 -all"

; AND

IN SPF "v=spf1 mx/26 -all"

; verify sender using example.com MX and A RRs

; and use 16 IP address range

ptr

ptr/domain

Use the source-ip's PTR RR and a reverse map query. The AA RR for the host is then obtained. If this IP matches the sender-ip AND the sender-domain is the same as the domain name of the host obtained from the PTR RR then the test passes. The form ptr:domain replaces the sender-domain with domain in the final check for a valid domain name. The domain form may use macro-expansion features. The PTR record is the least preferred solution since it places a load on the IN-ADDR.ARPA (IPv4) or IPV6.ARPA reverse-map domains which generally have less capacity than the gTLD and ccTLD domains. Examples:

; fragment for example.com

$ORIGIN example.com.

@ IN TXT "v=spf1 ptr -all"

; the effect is to allow any host which is

; reverse mapped in the domain to send mail

ip4:ipv4 ip4:ipv4/cidr

In its basic form defines an explicit ipv4 address to verify the mail source-ip. If the source-ip is the same as ipv4 the test passes. May optionally take the form ipv4/cidr to define a valid IP address range. For more info on CIDR. Since this type incurs the least additional load on the DNS the current draft of the proposed RFC recommends this format. Examples:

; fragment for example.com

$ORIGIN example.com.

@ IN TXT "v=spf1 ip4:192.168.0.2 -all"

; AND

@ IN SPF "v=spf1 ip4:192.168.0.2 -all"

; if source-ip is 192.168.0.2 test passes

; cidr format

@ IN TXT "v=spf1 ip4:192.168.0.2/27 -all"

; AND

@ IN SPF "v=spf1 ip4:192.168.0.2/27 -all"

; if source-ip is in range 192.168.0.1

; to 192.168.0.31 test passes

ip6:ipv6

ip6:ipv6/cidr

In its basic form defines an explicit ipv6 address to verify the mail source-ip. If the source-ip is the same as ipv6 the test passes. May optionally take the form ipv6/cidr to define a valid IP address range. For more info on CIDR. Since this type incurs the least additional load on the DNS the RFC recommends this format. Examples:

; fragment for example.com

$ORIGIN example.com.

@ IN TXT "v=spf1 ip6:2001:db8::10 -all"

; AND

@ IN SPF "v=spf1 ip6:2001:db8::10 -all"

; if source-ip is 2001:db8:0:0:0:0:0:10 test passes

; cidr format

@ IN TXT "v=spf1 ip6:2001:db8::10/120 -all"

; if source-ip is in range 2001:db8:0:0:0:0:0:0

; to 2001:db8:0:0:0:0:0:FF test passes

exists:domain

The existence (any valid A RR) of the specified domain allows the test to pass. Domain may use macro-expansion features.

mod

Two optional record modifiers are defined. If present they should follow the last type directive i.e. after the all. The current values defined are as follows:

Modifier

Description

redirect=domain

Redirects verification to use the SPF records of the defined domain. Functionally equivalent to include but can appear on its own (without a terminating all) or can placed after the all which means "if all the previous test fail try this redirect". Examples:

; fragment for example.com

$ORIGIN example.com.

@ IN TXT "v=spf1 ip4:192.168.0.2 -all redirect=example.net"

; if source-ip is 192.168.0.2 test passes

; if it fails redirect to example.net

; OR single redirect

@ IN TXT "v=spf1 redirect=example.net"

; AND

@ IN SPF "v=spf1 redirect=example.net"

; only use example.net SPF record

exp=txt-rr

The exp record if present should come last in a SPF record (after the all if present). It defines a DNS name whose TXT record's text may be returned with any failure message. Example:

; domain SPF record

IN TXT "v=spf1 mx -all exp=bad.example.com"

; AND

IN SPF "v=spf1 mx -all exp=bad.example.com"

; the getlost TXT record

bad IN TXT "Not allowed to send mail for domain"

The syntax allowed by this record is significantly more complex (see macro-expansion below.

Macro-Expansion

SPF defines a number of macro-expansion features as defined below:

Note: all macro-expansion delimiters use braces {}.

Modifier

Description

%{c}

Only allowed in TXT records referenced by the exp field. The IP of the receiving MTA.

%{d}

The current domain, normally the sender-domain %{o} but replaced by the value of any domain argument in the type above.

%{h}

The domain name supplied on HELO or EHLO, normally the hostname of the sending SMTP server.

%{i}

sender-ip The IP of SMTP server sending mail for user info@example.com.

%{l}

replace with local part of sender e.g. if sender is info@example.com, the local part is info.

%{o}

The sender-domain e.g. if email address is info@example.com the sender-domain is example.com.

%{p}

The validated domain name. The name obtained using the PTR RR of the sender-ip. Use of this macro will require an additional query unless a ptr type is used.

%{r}

Only allowed in TXT records referenced by the exp field. The name of the host performing the SPF check. Normally the same as the receiving MTA.

%{t}

Only allowed in TXT records referenced by the exp field. Current timestamp.

%{s}

Replace with sender email address, for instance, info@example.com

%{v}

Replaced with "in-addr" if sender-ip is an IPv4 address and "ip6" if an IPv6 address. Used to construct reverse map strings.

The above macros may take one or more additional arguments as follows:

r - Indicates reverse the order of the field, for instance, %{or} would display example.com as com.example and %{ir} would display 192.168.0.2 as 2.0.168.192. The normal split uses "." (dot) as the separator but any other character may be used to define the split but a "." (dot) is always used when rejoining so, for instance, %{sr@} would display info@example.com as example.com.info.

digit - the presence of a digit (range 1 to 128) limits the number of right most elements displayed, for instance, %{d1} displays only com only from example.com but %{d5} would display five right hand elements up to the maximum available, in this case it will display example.com since that is all that is available.

Examples

Example 1

Example 1: Assumes a single mail server which both sends and receives mail for the domain.

; zone file fragment for example.com

$ORIGIN example.com.

IN MX 10 mail.example.com.

....

mail IN A 192.168.0.4

; SPF stuff

; domain SPF

example.com. IN TXT "v=spf1 mx -all"

; AND

example.com. IN SPF "v=spf1 mx -all"

; mail host SPF

mail IN TXT "v=spf1 a -all"

; AND

mail IN SPF "v=spf1 a -all"

Notes:

the domain SPF is returned from a sender-domain query using the sender's email address e.g. sender = info@example.com sender-domain = example.com. The SPF record only allows the MX host to send for the domain.

the mail host SPF is present in case the receiving MTA uses a reverse query to obtain the source-ip host name and then does a query for the SPF record of that host. The SPF record states that the A record of mail.example.com alone is permitted to send mail for the domain.

If the domain contains multiple MX servers the domain SPF would stay the same but each mail host should have a SPF record.

Example 2

Example 2: Assumes the domain will send mail through an offsite mail server e.g. an ISP:

; zone file fragment for example.com

$ORIGIN example.com.

IN MX 10 mail.offsite.com.

....

; SPF stuff

; domain SPF

example.com. IN TXT "v=spf1 include:offsite.com -all"

; AND

example.com. IN SPF "v=spf1 include:offsite.com -all"

; WARNING: offsite.com MUST have a valid SPF definition

Notes:

This format should be used IF AND ONLY IF you know that offsite.com has a valid SPF configuration.

include recurses (restarts) verification using the SPF records for offsite.com. Mail configuration changes are localised at offsite.com which may simplify administration.

include could have been replaced with redirect.

Example 3

Example 3: Assumes we are the host for a number of virtual mail domains and that we can send mail from any host in our subnet.

Zone file fragment for one of the virtual mail domains:

; zone file fragment for vhost1.com

$ORIGIN example.com.

IN MX 10 mail.example.com.

....

; SPF stuff

; domain SPF

vhost1.com. IN TXT "v=spf1 include:example.com -all"

; AND

vhost1.com. IN SPF "v=spf1 include:example.com -all"

Notes:

the domain SPF is returned from a sender-domain query using the sender's email e.g. sender = info@vhost1.com, sender-domain = vhost1.com. The SPF record recurses to the DOMAIN example.com for verification.

Zone file for example.com

; zone file fragment for example.com

IN MX 10 mail.example.com.

....

; SPF stuff

; domain SPF - any host from

; 192.168.0.1 to 192.168.0.30 (32 - bcast and mcast = 30)

; can send mail

example.com. IN TXT "v=spf1 ip4:192.168.0.3/27 -all"

; AND

example.com. IN SPF "v=spf1 ip4:192.168.0.3/27 -all"

; mail SPF

mail IN TXT "v=spf1 ip4:192.168.0.3/27 -all"

; AND

mail IN SPF "v=spf1 ip4:192.168.0.3/27 -all"

Notes:

the domain SPF is returned from a sender-domain query using the sender's email e.g. sender = info@example.com sender-domain = example.com. The SPF record allows any host in the 32 address subnet which contains 192.168.0.3 to send mail for this and any host virtual domain e.g virtual1.com in the above example. NOTE: while /27 allows 32 IP addresses subnet rules remove 192.168.0.0 and 192.168.0.31 as the multicast and broadcast addresses respectively. [read more about IPv4 Classes]

In the above scenario we could have used a slightly shorter version such as:

example.com. IN TXT "v=spf1 mx/27 -all"

; AND

example.com. IN SPF "v=spf1 mx/27 -all"

This record has the same effect as a:192.168.0.3/27 above but will cost a further DNS look up operation whereas the IP is already available.

The above scenario relies on the fact that customers will only send mail via the domain example.com i.e. they will NOT send via another ISP at home or when travelling. If you are not sure if this is the case you can terminate the sequence with ?all which says kinda pass (soft fail) and let the mail go through - perhaps logging the incident to capture statistics.

If the domain contains multiple MX servers the domain SPF would stay the same but each mail host should have a SPF record.

Example 4

Example 4: Assumes that the domain never sends mail from ANY location - ever. Typically you would do this to prevent bogus mail for everyone else - it is a supreme act of self-sacrifice!

; zone file fragment for example.com

; zone does NOT contain MX record(s)

...

; SPF stuff

; domain SPF

example.com. IN TXT "v=spf1 -all"

; AND

example.com. IN SPF "v=spf1 -all"

Notes:

This SPF test will always fail since the only condition it tests is the all which results in a fail.

Example 5

Example 5: Illustrates various macro expansion features:

; zone file fragment for example.com

$ORIGIN example.org.

IN MX 10 mail.example.com.

....

; SPF records

; domain SPF

@ IN TXT "v=spf1 exists:%{ir}.%{v}.arpa -all exp=badguy.example.com"

; AND

@ IN SPF "v=spf1 exists:%{ir}.%{v}.arpa -all exp=badguy.example.com"

badguy IN TXT "The email from %{s} using SMTP server at %{i}

was rejected by %{c} (%{r}) at %{t} because it failed

the SPF records check for the domain %{p}.

Please visit http://abuse.example.com/badguys.html

for more information"

Notes:

The badguy TXT above is split across multiple lines for presentation reasons only and should appear on a single line in the zone file.

The exists:%{ir}.%{v}.arpa test is a great example BUT IT WILL NOT WORK because the exists type checks for an A RR whereas a reverse lookup is defined using a PTR RR. But it does show the power of macro-expansion and we could not think of a better one. However Stuart Gatham could and suggested using the reversed IP address in a DNS Black List (DNSBL) as shown here:

@ IN TXT "v=spf1 exists:%{ir}.blacklist.example.com -all exp=badguy.example.com"

; AND

@ IN SPF "v=spf1 exists:%{ir}.blacklist.example.com -all exp=badguy.example.com"

You may aslo want to chnage the text in the badguy.example.com record to reflect the new failure. Many thanks for the suggestion.

PHP send sendmail slow delay hang problem

有關 php send mail 的最新資訊,,, 問題應該是出在 ipv6 (FreeBSD 7 by default 是 enable 的),,,,,,,, 然後 有可能是因為我這的 switch 太舊 (不 support ipv6?)

所以要把 ipv6 disable 掉,而我測過,光在 /etc/rc.conf 加 ipv6_enable="NO" 是不夠的,還要重新 compile kernel,把 inet 6 這個 option 拿掉,這樣在
#tcpdump -i em0 port 53

時,才不會出現 request AAAA DNS delay

# cat /etc/hosts
::1 localhost localhost.dev01.mydomain.com
127.0.0.1 localhost localhost.dev01.mydomain.com
219.16.152.262 dev01.mydomain.com
192.168.700.152 dev011

# cat /etc/resolv.conf
domain mydomain.com
nameserver 219.16.152.262 # my DNS IP
nameserver 139.142.2.3 # My ISP's DNS IP
nameserver 209.135.99.3 # My ISP's DNS IP

Tuesday, August 25, 2009

PHP to test for empty input, but not zero

PHP to test for empty input, but not zero
Wed, 19/04/2006
stuart

While writing my flash node I came across a problem with one field on the form. If it was empty I wanted to reset the value to the default, but zero was an allowed value.

In PHP empty($var) evalutes as true if $var is empty, but also if $var has a value of zero. So 0 was seen as empty and the default arrived.

Two solutions to test for empty, but not zero:

* Use if ( empty($var) && !is_numeric($var) )
* Use if ( $var == '' )

Both return true if empty and not zero. The latter looks easier to read. Not sure if one is any faster than the other! There's some discussion of this issue on php.net.

Friday, August 21, 2009

ls command


Shells
Most Linux distributions use the bash shell while the BSDs use tcsh, the bourne shell is only used for scripts. Filters are very useful and can be piped:

* grep Pattern matching
* sed Search and Replace strings or characters
* cut Print specific columns from a marker
* sort Sort alphabetically or numerically
* uniq Remove duplicate lines from a file

For example used all at once:

# ifconfig | sed 's/ / /g' | cut -d" " -f1 | uniq | grep -E "[a-z0-9]+" | sort -r
# ifconfig | sed '/.*inet addr:/!d;s///;s/ .*//'|sort -t. -k1,1n -k2,2n -k3,3n -k4,4n

The first character in the sed pattern is a tab. To write a tab on the console, use ctrl-v ctrl-tab.
bash
Redirects and pipes for bash and sh:

# cmd 1> file # Redirect stdout to file.
# cmd 2> file # Redirect stderr to file.
# cmd 1>> file # Redirect and append stdout to file.
# cmd &> file # Redirect both stdout and stderr to file.
# cmd >file 2>&1 # Redirects stderr to stdout and then to file.
# cmd1 | cmd2 # pipe stdout to cmd2
# cmd1 2>&1 | cmd2 # pipe stdout and stderr to cmd2

Modify your configuration in ~/.bashrc (it can also be ~/.bash_profile). The following entries are useful, reload with ". .bashrc".

# in .bashrc
bind '"\e[A"':history-search-backward # Use up and down arrow to search
bind '"\e[B"':history-search-forward # the history. Invaluable!
set -o emacs # Set emacs mode in bash (see below)
set bell-style visible # Do not beep, inverse colors
# Set a nice prompt like [user@host]/path/todir>
PS1="\[\033[1;30m\][\[\033[1;34m\]\u\[\033[1;30m\]"
PS1="$PS1@\[\033[0;33m\]\h\[\033[1;30m\]]\[\033[0;37m\]"
PS1="$PS1\w\[\033[1;30m\]>\[\033[0m\]"

# To check the currently active aliases, simply type alias
alias ls='ls -aF' # Append indicator (one of */=>@|)
alias ll='ls -aFls' # Listing
alias la='ls -all'
alias ..='cd ..'
alias ...='cd ../..'
export HISTFILESIZE=5000 # Larger history
export CLICOLOR=1 # Use colors (if possible)
export LSCOLORS=ExGxFxdxCxDxDxBxBxExEx

tcsh
Redirects and pipes for tcsh and csh (simple > and >> are the same as sh):

# cmd >& file # Redirect both stdout and stderr to file.
# cmd >>& file # Append both stdout and stderr to file.
# cmd1 | cmd2 # pipe stdout to cmd2
# cmd1 |& cmd2 # pipe stdout and stderr to cmd2

The settings for csh/tcsh are set in ~/.cshrc, reload with "source .cshrc". Examples:

# in .cshrc
alias ls 'ls -aF'
alias ll 'ls -aFls'
alias la 'ls -all'
alias .. 'cd ..'
alias ... 'cd ../..'
set prompt = "%B%n%b@%B%m%b%/> " # like user@host/path/todir>
set history = 5000
set savehist = ( 6000 merge )
set autolist # Report possible completions with tab
set visiblebell # Do not beep, inverse colors

# Bindkey and colors
bindkey -e Select Emacs bindings # Use emacs keys to edit the command prompt
bindkey -k up history-search-backward # Use up and down arrow to search
bindkey -k down history-search-forward
setenv CLICOLOR 1 # Use colors (if possible)
setenv LSCOLORS ExGxFxdxCxDxDxBxBxExEx

The emacs mode enables to use the emacs keys shortcuts to modify the command prompt line. This is extremely useful (not only for emacs users). The most used commands are:

* C-a Move cursor to beginning of line
* C-e Move cursor to end of line
* M-b Move cursor back one word
* M-f Move cursor forward one word
* M-d Cut the next word
* C-w Cut the last word
* C-u Cut everything before the cursor
* C-k Cut everything after the cursor (rest of the line)
* C-y Paste the last thing to be cut (simply paste)
* C-_ Undo

Note: C- = hold control, M- = hold meta (which is usually the alt or escape key).

LSCOLORS The value of this variable describes what color to use
for which attribute when colors are enabled with
CLICOLOR. This string is a concatenation of pairs of the
format fb, where f is the foreground color and b is the
background color.

The color designators are as follows:

a black
b red
c green
d brown
e blue
f magenta
g cyan
h light grey
A bold black, usually shows up as dark grey
B bold red
C bold green
D bold brown, usually shows up as yellow
E bold blue
F bold magenta
G bold cyan
H bold light grey; looks like bright white
x default foreground or background

Note that the above are standard ANSI colors. The actual
display may differ depending on the color capabilities of
the terminal in use.

The order of the attributes are as follows:

1. directory
2. symbolic link
3. socket
4. pipe
5. executable
6. block special
7. character special
8. executable with setuid bit set
9. executable with setgid bit set
10. directory writable to others, with sticky bit
11. directory writable to others, without sticky
bit

The default is "exfxcxdxbxegedabagacad", i.e. blue fore-
ground and default background for regular directories,
black foreground and red background for setuid executa-
bles, etc.

Wednesday, August 19, 2009

Httpd Exited on Signal 11 - Caused by Buggy Script

Httpd Exited on Signal 11 - Caused by Buggy Script

July 31, 2005 Posted by KP

My security run output of today contains lots of error messages like:

pid 90742 (httpd), uid 80: exited on signal 11

pid 90896 (httpd), uid 80: exited on signal 11

It looks like a serious problem, then I searched the Internet immediately, here is a helpful discussion. Although there are no definite answers, the possible reasons can be summarized as:

1. Hardware problems, the most common one.

2. Vulnerable version of Apache, PHP or other Apache modules.

3. Buggy scripts.

Regarding my server

1. Hardware problems

This server has been running well for several months, unlikely to be the case.

2. Vulnerable version of Apache or its modules

Normally I can ignore this since I monitor the packages closely with portaudit. But recently Apache did have a known vulnerability. I ignored the upgrade because it shouldn’t affect my installation.

This only affects installations where Apache is used as HTTP proxy in combination with the following web servers.

3. Buggy scripts

I did install mambo yesterday and it has a very weird problem, admin login doesn’t work. There are many similar bug reports without solutions on their support forum, which is very unusual for a popular CMS, IMO. I debugged the script as I wrote in a previous post, it turned out that the login script ended at a PHP function “session_start()”, it didn’t give any error message, just like calling “die()”. Then I made a test, signal 11 error happened every time I made a login.

Now the problem is clear, I removed mambo.

=====================
Danny: 我曾經有經驗是 database 裡面的 資料有問題 導致這個現像,只要把 backup 的 database restore 就解決了,例外還有底下三個方向:

- 確認 script file 沒有 UTF-8 的 BOM or Space at the beginning and end of script files.

- 看 drupal table 裡面的 watchdog table

- 在 command line interface cli 底下 執行 php drupal/index.php

Work like you don't need the money,

Work like you don't need the money,
love like you'll never get hurt,
and dance like nobody's watching.

Tuesday, August 18, 2009

How to Setup Drupal for Multiple Sites

How to Setup Drupal for Multiple Sites

Drupal is a very powerful open source content management system
. And one of the most attractive features from Drupal is that it will allow you to install one single Drupal code base which can serve for multiple web sites, each with its own individual configuration.

But unfortunately, the guide from Drupal office site on how to configure this feature is not clear enough, and the beginner might be lost during it. In below, we will provide you with the step by step guide to set it up:

Before we start, you should have successfully install one Drupal instance, if you still haven't, please follow the installation guide
from Drupal official site to get it setup. Here, we will focus on how to add another domain to one Drupal installation.

* Create a new database and database users for the second domain (lets call it as "domain2.com")
* Grant full privileges to the database to the user created in the step 1)
* Create a sub-directory in the "/sites" directory call "domain2.com", it will look like /sites/domain2.com/. Please don't include 'www' in the sub-directory.
* Copy the /sites/default/default.settings.php to the new directory /sites/domain2.com/settings.php (don't forget to remove the 'default.' from the file name)
* Setup the add-on domain for "domain2.com" in your web hosting account. For a shared web hosting environment, domain2.com will point to a directory like "/home/username/public_html/domain2".
* Delete directory "/home/username/public_html/domain2"
* Create a symlink to the main site as "/home/username/public_html/domain2", the same as what in above.
* Launch the domain2 in browser, Drupal Installer will be launched, go through the installation process
according to on-screen instructions. You will get new web site setup on the same Drupal code base.

Monday, August 17, 2009

Clock in a VMWare FreeBSD Guest Runs More Slowly or Quickly Than Real Time

Method 1.
Add the following to /boot/loader.conf and reboot: kern.hz="100"

According to the author of this solution it has something to do with the amount of interrupts/second that various kernels generate. Reducing the load creates a work around for the problem.

Method 2.
Add the following to /boot/loader.conf and reboot: hint.apic.0.disabled=1

By disabling APIC device, FreeBSD is forced to fall back on the IRQ timers to avoid the rate of the clock and timer on emulated FreeBSD machine on VMware slows down. The down side to this resolution is that FreeBSD cannot runs in as SMP kernel mode as a virtual SMP machine on the emulated machine.

Another alternative is to comment out the “device apic” line in the kernel config file and rebuild the kernel, but only if you are technically know what you’re doing.

==============================================
Anonymous said...

kern.hz="100" does not help me and I guess disabling APIC is no acceptable, because VM has 2vCPU on real Athlon64 X2 CPU Linux host.
==============================================

Reference:
http://msmvps.com/blogs/rexiology/archive/2007/01/07/clock-in-a-vmware-freebsd-guest-runs-more-slowly-or-quickly-than-real-time.aspx
http://www.mydigitallife.info/2006/04/12/freebsd-60-on-vmware-server-time-and-clock-slow-down/

Saturday, August 15, 2009

成熟男人的十大標準

成熟男人的十大標準
分類:knowledge
2009/07/15 12:59

男人必看!! 成熟男人的十大標準
一、重視諾言。
成熟男人絕對不會出爾反爾,他對自己的每個承諾都相當重視,在許願之前周密考慮,自己的話是否真能兌現,如能兌現的話他決不說,言出必踐。他的每一句話都讓你覺得放心、可信任。滿嘴跑火車、亂放空炮、遲遲拿不出行動的男人,與成熟不沾邊。

二、不誇誇其談。
成熟男人從不隨隨便便高談闊論,他會把握適當的沉默,說話聲音清晰但不亂嚷。隨便喝點酒就把自己的點小經歷小故事拿來滿桌子大講,不用喇叭半屋人都能聽見的,這種男人,最多博聽眾一笑,誰也不會把你那五花八門的所謂'奮鬥之路'放在心裡。

三、有學識而含蓄內斂。
他們讀書,接受新事物新信息,不斷豐富自己的內涵。但他們不張揚,他們的才華只在必需的時候才展現出來,決不會為了滿足虛榮去刻意賣弄。他們如醇厚的酒,越品越有味道。

四、心胸寬廣。
成熟男人不斤斤計較,不貪圖小便宜,不在乎吃點小虧,不喋喋不休地抱怨這抱怨那。他們的眼光從不被瑣碎事務絆住,對於家庭中的小爭吵,他們經常是'首先回頭的天使'。

五、不以自我為中心。
成熟男人尊重自己,更懂得尊重他人。他們善於換位思考,會站在別人的立場上來考慮問題,不強求別人遷就自己,善於同別人合作。凡是'我怎樣怎樣'的男人,典型的小皇帝脾氣,還沒長大。

六、勇於承認錯誤。
成熟男人不頑固,能接受不同意見,善於採納好的建議。對於自己的不當決策,他們勇於承擔後果,從不找藉口搪塞推諉。

七、意志堅定。
成熟男人有處變不亂的心理素質,他們一旦確定自己奮鬥的目標,就朝著它努力,遇到挫折,他們分析原因,吸取教訓,及時修正方向,但決不輕易言退。他們會疲倦,但在休整後,又信心十足地出發了。

八、乾淨整潔。
成熟男人尊重自己的外表。他們留最適合自己的髮型,下巴乾淨沒有鬍子茬,面部不油膩,不留長指甲。衣服不一定要名牌,但整潔大方,不會穿得皺巴巴像個送快遞的。他們決不會穿黑皮鞋配白襪子,穿著西服去旅遊。

九、尊老愛幼。
成熟男人有愛心,有社會責任感,有中華民族的傳統美德。他會給老人和孕婦讓座,會給受災地區捐款捐物,會幫助失學兒童,會義務獻血……這些事情他們不一定全做,但他們決不會什麼都不做。

十、有業餘愛好。
他們不是只知道工作的機器人,懂得用業餘愛好來調節自己緊繃的神經,工作休閒兩不誤,這使他們有情趣。怪不得女人們說:有愛好的男人不容易變壞。

Thursday, August 13, 2009

Trac 整合性開發環境

Trac 整合性開發環境現在開發軟體專案,已經不是一個人可以徹底掌握的,隨時都會遇到 "XD Programming" 的經驗,什麼是 "XD Programming" 呢?這是我在 #dot IRC channel 閒聊時發明的稱法,主要是描述建構一個軟體,就算有相當充足的資源,還是不免到處碰壁的挫折經驗,這時候就需要惡搞,然後就不免會補個 "XD" *笑*。例如 PCMan 兄當初打算重寫過去的 [pcman],成為現在我們所見的 [PCManX pure GTK+ 2],這過程有頗多艱辛,不過本週二 PCManX 本尊就會在 [TOSSUG - 台北開放源碼軟體使用社群 (Taipei Open Source Software User Group)] 給場 talk,這裡就不贅述了。但是,使用好的工具,對開發的過程絕對有相當程度的幫助,特別在多人協同開發中。

[布長輩] 提過 [Trac 介紹 & 0.8.4 中文版],可以得知 [Trac] 實在是操作簡單,功能卻強大的整合 SCM 與專案管理的系統,而 [hcchien’s space] 也提到 [科技還是要來自人性] 一文,看來博大精深的 [RT] 也有了 trac theme:



引用 [布長輩] 的介紹敘述:

Trac 提供一套網站作業環境:有撰寫文件用的Wiki子系統、事務追蹤(issue tracking)子系統等等。而且不論是 [操作介面] 跟 [系統整合] 方面,都表現得可圈可點。也難怪 [許多知名軟體專案] 都已經採用目前才0.9版的Trac了。雖然說Trac是專門設計給軟體專案用的,可是我覺得裝在自己筆記型電腦上,管理svk也挺不錯。 十一月初,我這個 server 白痴,也終於在某種特定的需求下,自己動手安裝 [Trac],雖然一般來說文件都寫得很詳細,可是搞這種東西,都會讓我想起以前是如何把 [KDE@Taiwan] 搞爛的往事。[Trac] 全部以 Python 撰寫,不是我懼怕的駱駝文,看來有點信心,而且還有 standalone web daemon 可用,大大的提高我的興趣,然後設定檔改一下,將變數指向 Subversion repository,apache-ctl restart 後,竟然... 就可以動了,讓我這個 server 白痴真是高興了好一段時間。

Trac 0.9 改用 BSD-like License,有更大的彈性,而且我也開始練習寫 Python module,在內部的專案管理開始作實務應用,用起來還不錯,Trac 開發團隊也相當活躍,大概除了 localization 外,沒什麼特別要挑剔的 :)

由 jserv 發表於 December 12, 2005 12:30 AM

Wanted: 10 IT Skills Employers Need Today

Wanted: 10 IT Skills Employers Need Today

Technologies such as wireless and Web 2.0 demand new skills, while network and security know-how never seem to go out of style

By Denise Dubie , Network World , 04/17/2008

Technology pros looking to find new work or secure their current jobs should get schooled on wireless, Web 2.0 and virtualization while also boning up on business basics.

"IT professionals with the right technical skill set plus a foundational understanding of the business they work in will stand a much better chance in today's market," says Neill Hopkins, vice president of skills development at the Computer Technology Industry Association (CompTIA).

Business initiatives such as enterprise mobility, data center consolidation and unified communications are driving demand for expertise in new technology areas and reinforcing the importance of mastering the fundamentals such as networking and security, industry watchers say.

"Web 2.0, .Net, Java, wireless -- skills in technologies that enable end users to engage and communicate with each other -- are hot," says Rich Milgram, CEO of online job portal Beyond.com. "At the same time network and security skills are becoming more and more important, especially as companies expose more and more of their networks and data to the world."

Here we examine (in no particular order) the current most-sought-after skills and those destined to be in demand going forward.
1. Wireless

Because end users expect to be able to work from anywhere anytime, skills in wireless and mobility are being pushed to the top of many hiring managers' must-have lists.

"Now you need to be able to plan and troubleshoot radio interference and access point placement. Everyone wants to work from anywhere," says Bruce Meyer, director of network services at ProMedica Healthcare in Toledo, Ohio. "Standards will continue to evolve rapidly as everyone chases the Holy Grail of a wirelike experience. I'm not just looking for wireless skills; I'm looking for the ability to rapidly learn new things."

According to CompTIA, wireless skills in many areas -- 802.11, WiMAX and broadband -- will only become more appealing to companies in the next five years.

John Estes, vice president of strategic alliances at Robert Half Technology, adds that mobility goes beyond knowing wireless technologies. It also requires knowing about each device end users might start using to tap the network. "End users have mini multimedia computers in their hands now. Someone is going to have to be involved in decisions around which devices best suit the environment and application needs," Estes says.
2. Virtualization

No longer just a tool for systems administrators to tinker with in testing environments, virtualization technology is the main component behind data center consolidation and disaster recovery initiatives.

"Virtualization is a hot technology area, which means managers are looking for people with some savvy there," says Steve Clifford, field recruiting director at staffing agency TAC Worldwide. "Many companies have a lot of redundant servers, and they are trying to maximize resources and utilization on every server on every site."

And while server virtualization is the current hot technology, industry watchers expect storage, network and desktop virtualization to continue to drive demand for expertise in this technology area. EMA Research Director Andi Mann says desktop virtualization will show the strongest growth of any virtualization technology during the next one to two years.
3. Security
Security as a must-have skill is a no-brainer.

A CompTIA skills survey released in February had security listed as the No. 1 skill among three-quarters of the 3,578 IT hiring managers polled. Foote Partners reports that security skills accounted for 17% of base pay in the fourth quarter of 2007, and pay for network security management skills increased by more than 27% in 2007.

But going forward, IT professionals will need to be able to incorporate their security savvy into network, wireless, application, operating system and other IT areas to best compete.

"Firewall, data leak, compliance -- you name it and it's in demand for security," says CompTIA's Hopkins. "In the networking field, you need to also be an expert at security, but going forward skills around how to train staff and employees to be security-aware will have to be developed."
4. Networking

Networking expertise, which fell out of favor after the dot-com bust, is now back in demand and second only to security in terms of needed skills among the IT managers surveyed by CompTIA.

"Networking and infrastructure skills are back. Companies are not getting rid of data and they are doing more transactions online. With the growth and complexity of networks, there is a push for skills to design and manage such large-scale environments," says Beyond.com's Milgram.

Martin Webb, manager of data network operations for the Ministry of Labour and Citizens' Services in the province of British Columbia, says he is looking for people with practical experience in large enterprise IP-based networks, "both in terms of implementing services as well as operational support."

"Experience in wide-area networking is hard to come by, particularly as it applies to traditional carrier networking technologies such as T-1, frame relay, ISDN and multiplexing," Webb explains. "Today's technical staff also need to have basic business analysis skills with an understanding of financial management."

Brian Jones, manager of network engineering at Virginia Polytechnic Institute and State University's Tech's Communications Network Services unit in Blacksburg, says he is always on the lookout for "field personnel who are well-organized. This means people who are experienced in installing networks, including everything from assembling racks to installing fiber panels, cross connect fields, cable management, and various network chassis and equipment." Other networking skills he says are must-haves include proficiency in cable and fiber termination and splicing as well as experience installing and configuring edge switches.

"These skills are hard to find and keep," Jones says.

For John Tuman, director of network services at WakeMed Health & Hospitals in Raleigh, N.C., finding VoIP skills is a challenge. "There is a lot of talent available with the traditional PBX, far less that have practical VoIP experience," he says.

Virginia Tech's Jones agrees. He says expertise in VoIP will only be more in demand as time goes on.

"VoIP, IPv6, and other emerging technologies will be driven by new applications and user requirements. IT staffers as always will have to learn these new things while maintaining the older technologies and services," Jones says.
5. Application delivery

Often as networks become more complex and sophisticated, they also get distributed over various remote locations and branch offices -- which Gartner says is driving the need for expertise in the area of application delivery.

Application delivery networks, according to Gartner, are required if companies want to deploy modern browser-based applications and emerging Web services applications. This network overlay responsible for application delivery will demand skills that cross storage, security, network and application development disciplines. Knowledge of application optimization techniques such as protocol offload, caching, application firewalls and others would be required of application delivery experts on staff.

"IT departments that add these positions will see smoother application development and deployment, increased user satisfaction and lower costs," says Joe Skorupa, research vice president at Gartner.
6. Web 2.0

Companies looking to implement Web 2.0 technologies want to see IT professionals with skills in areas such as AJAX, .Net and XML. These technologies require updated application development skills because they provide a more interactive experience, which could cause bandwidth or performance issues if not executed properly.

"For application development tools, AJAX, .Net, WebSphere and others have replaced and are replacing all the early-generation stuff like CGI, Visual Interdev and HTML/DHTML," says David Foote, CEO and chief research officer at Foote Partners.
7. IT business analysis

Being able to gauge the business relevance of technology decisions is critical for all high-tech hires, industry watchers and IT managers agree.

Arun DeSouza, a director of strategic planning and security at Inergy Automotive Systems in Troy, Mich., says skills around managing IT with finance in mind are in demand at his company.

"Ultimately, all technology investments and operational expenditures are about enabling the business and adding to the bottom line," he says. "IT managers need to be able to help align with the business, manage the financial portfolio and articulate the benefits in a language that the business can understand."

IT managers expect their employees not only to have a comprehensive understanding of the business they support but also to keep that knowledge current.

"The more senior a technical staffer gets, the more business aware they need to be," says John Turner, director of networks and systems at Brandeis University in Waltham, Mass.
8. Database management

Database management skills are growing in importance, according to several industry sources.

Robert Half Technology found database management to be considered an in-demand skill among 66% of 1,400 CIOs it polled. Foote Partners reported that median pay for database skills increased by 10% over the last two years, with Oracle database skills specifically seeing a 24% spike in pay over the previous 12 months.

"Simply speaking, it is cheaper now to store data so more companies are keeping more data on large-scale disk drives, because in the online world content is king," Beyond.com's Milgram says. "The more content you have the bigger you are, and back-end SQL, MySQL and Oracle skills are in demand to ensure companies are successful at such large-scale data management."
9. Business intelligence/data mining

In a similar vein as data management, business intelligence and data mining skills are growing in importance to enterprise companies as analyzing the data stored can directly impact a business' bottom line.

"Customers have spent so much money on gathering their data and putting it in data warehouses that they are now looking for ways to generate revenue from the data or from the knowledge contained within it," says TAC Worldwide's Clifford. "It's important that IT professionals have these skills -- one part business intelligence and one part data mining -- but also that they can apply them in such a way that is suitable to their business.

According to Foote Partners, pay for business intelligence grew by more than 22% in 2007.
10. The X factor

The trend is for IT professionals to emerge from being specialists in one technology area to being team members with broad knowledge of the environment. As networks and systems grow more sophisticated and intertwined with each other and the business, IT staff is expected to be well-versed in many areas and able to apply that know-how to the business at hand.

"I am seeing a need for IT staff to have a more holistic view when designing, integrating and troubleshooting. In the past, skill sets could be quite focused because there were better-defined lines of demarcation between systems; the trend continues to move to more interdependent and intertwined systems," says WakeMed Health & Hospitals' Tuman. "Now we need folks to understand how multiple systems interoperate, and when troubleshooting, have the ability to associate symptoms that surface in other areas back to the source."

Wednesday, August 12, 2009

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

追求神乎其技的程式設計之道(九)Thursday, August 13th, 2009

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

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

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

高中到大學

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

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

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

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

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

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

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

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

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

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

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

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

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

(待續)

Posted in 追求神乎其技的程式設計之道 | 1 Comment »

追求神乎其技的程式設計之道(八)Wednesday, March 11th, 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的能力,那我覺得還有個關鍵是,要在有點子前先做過夠多的努力打好基礎,等到靈光一現時才能把握住機會馬上實現它。如果等到一分的天才出現時,才準備開始做九十九分的努力,那很容易就會被許多基礎能力不足所帶來的挫折感和障礙所壓垮。

(待續)

Posted in 追求神乎其技的程式設計之道 | 20 Comments »

追求神乎其技的程式設計之道(七)Friday, October 10th, 2008

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

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

思考的高度

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

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

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

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

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



a = 1;  // 把a設為1



有些經驗後,會再多看到一層,利用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,但這裡就不要這麼講究了)寫起來大概是這樣:



PhoneData contacts[N] = {…..};

String number[MAX_NUMBERS];

int count = 0;  

for(int i = 0; i ){

  if( !strncmp( contacts i>.name, "張", 1 ) ) // well, 讓我們假設這個strncmp支援unicode

    ret[count++] = contacts i>.number;

}

return ret;



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



contacts = [ { 'name' => '...', 'number' => '...' }, ... ]

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



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

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

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

(待續)

Posted in 追求神乎其技的程式設計之道 | 24 Comments »

追求神乎其技的程式設計之道(六)Tuesday, August 19th, 2008

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

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

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

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

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

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

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

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

(待續)

Posted in 追求神乎其技的程式設計之道 | 12 Comments »

追求神乎其技的程式設計之道(五)Friday, July 25th, 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”,也就是期望每個學生都能手腦並用,除了做夢外也要實做出來才算數啊。

(待續)

Posted in 追求神乎其技的程式設計之道 | 13 Comments »

追求神乎其技的程式設計之道(四)Tuesday, July 15th, 2008

程式設計到底是什麼?

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

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

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

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

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

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

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

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

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

(待續)

Posted in 追求神乎其技的程式設計之道 | 4 Comments »

追求神乎其技的程式設計之道(三)Saturday, July 12th, 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,碰在一起時就讓各自的程式互相決鬥分個高下,玩起來比自己親自下去玩還刺激很多。

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

(待續)

Posted in 追求神乎其技的程式設計之道 | 11 Comments »

追求神乎其技的程式設計之道(二)Monday, July 7th, 2008

(本來沒有想寫這麼長的,哪知道一下手後欲罷不能…。看來這系列文章會變成長連載了。)

資訊奧林匹亞與程式競賽

在升上高中前,我因緣際會透過一個國中的同班同學認識了他的哥哥YJL。YJL比我大三年,我要進中一中時他剛好畢業,很巧的是他很會寫程式,一直都是中一中的資訊能力競賽代表隊成員。剛認識他時,他就demo給我看他用QBASIC自己寫的橫向捲軸射擊遊戲,當時看得我目瞪口呆,我完全沒法想像 QBASIC竟然能寫出這麼順暢且華麗的遊戲。這個demo如果不說,我一定會以為這是市面上在賣的商業遊戲(我那時還以為一定要學C才能寫出這種遊戲)。

透過YJL我也得知原來高中還有資訊能力競賽和奧林匹亞這種比賽,聽他述說跟全國的高手一起比賽寫程式時,讓我不知不覺也熱血沸騰起來。我把他高中時留下的各種參考資料全帶回家,並透過他認識了更多還在中一中的強者學長們,就這樣在踏進高中校門的同時也決定了我這三年的方向。

這裡我先介紹一下對於高中生最重要的資訊比賽。高中的學科能力競賽是教育部主辦的比賽,包括數學、物理、化學、生物、地球科學、資訊,每間高中通常會先辦個校內初賽來選出代表選手,再由這些選手參加各區域的能力競賽,最後各區的前N名(每科的人數不同)才能參加全國競賽。以資訊科來說,我記得是校內取6名,中區再取6名進全國決賽。到了全國決賽能拿到前10名,還能直接保送進資訊奧林匹亞的培訓營,不用再另外參加培訓營的入營考。至於資訊奧林匹亞 (International Olympiad in Informatics, IOI)則是國際性的資訊比賽,參加的人是從每個國家挑選出來的頂尖高中生,每年輪流由一個參賽國舉辦,選手要進行兩天每次連續五個小時的頭腦比賽,其中只有一半的人可以得到獎牌。

這些比賽和一般的程式比賽其實很不一樣。這種比賽比的是解決問題的能力,不是比賽軟體實做的能力。題目比較像數學問題,只是除了紙筆外,還得用某種程式語言實做出能解出正確答案的程式,也就是說參賽者必須想出問題的解法(演算法),再透過自己擅長的程式語言寫進電腦,讓電腦執行後輸出問題的答案。這種解題比賽主要考驗的是運用資料結構和演算法以有效率的方法解決問題,並寫出正確程式的能力。大學有個類似的比賽是ACM ICPC,問題類型和IOI很類似,但比賽的模式和方法則有很大差異,有興趣的人可以自行尋找相關資料。雖然IOI是給高中生參加的比賽,但IOI題目的水準其實非常高,如果你能輕易解出IOI的問題,那… 我跟你打賭去Google面試也有99%的機率會通過。順便一提,Google Code Jam就是一個開放給所有人參加的解題比賽,題目類型就跟IOI和ACM ICPC差不多,前一百名就有獎金,還能免費去Google Mountain View總部玩一玩喔。

參加比賽是一個評估自己實力的好方法,沒在比賽會場上較勁過,真的很難體會解題與寫程式能力的差距可以有多麼巨大。一個頂尖的程式設計師和一個普通的程式設計師,其生產力是很輕易的能有十倍甚至百倍以上的差距,而寫出來的程式碼品質及效率也是同樣會有如此巨大的落差。

透過良性的競爭,高中這段時間也成了我進步最快的一個時期…..

(待續)

Posted in 追求神乎其技的程式設計之道 | 13 Comments »

追求神乎其技的程式設計之道(一)Saturday, July 5th, 2008

最近有讀者問到我學寫程式的方法和經驗,讓我一下掉入時光隧道回想起當初用VB寫出自己第一個遊戲時的成就感,但當初沒料到的是我真的就此迷上了電腦和寫程式的快感,不知不覺也過了10年的光陰…。在這篇文章中,我想寫出我對程式設計的看法和我一路學習上來的歷程和經驗。寫程式是一條無止境的道路,不只是科學和工程,更是一種藝術。而我還在追求「神乎其技」的半路上,雖然還有很多要學的,但我也希望能讓初學者更容易看清楚這條路是什麼樣子,避免陷入盲目追求新技術的死巷中。

一切的開始

如果是從DOS時代開始玩電腦的玩家,應該都知道當初DOS有兩個內建的QBASIC小遊戲:貪食蛇和猩猩丟香蕉。這兩個小遊戲是許多人兒時共同的回憶,我還記得我國小時曾有幾堂電腦課,當時老師在台上嘰哩瓜啦的不知道在教什麼,而台下每台電腦都是貪食蛇或丟香蕉的畫面(老師對不起,其實我就是帶頭做亂的罪魁禍首…)。

微軟把這兩個QBASIC遊戲附在DOS內對我產生了莫大的影響,那是我第一次發現到原來QBASIC和不只是像PE2能打打字而已,QBASIC 竟然能把一堆看起來像咒語的文字變成遊戲!幸運的是我家剛好有本第三波的QBASIC入門書,沒事我就自己拿起來翻著看,雖然當時太小,即使把整本都看完了還是搞不懂貪食蛇是怎麼寫出來的,但也誤打誤撞知道了原來這就是程式設計,原來我能直接把貪食蛇檔案內的一個數字改掉就能有幾百條命可以死,原來學寫程式就能做出電腦遊戲…。對小孩子而言,知道這些事就像告訴他魔術師袖子裡的秘密一樣,我一天到晚興奮地要老爸帶我去書局看電腦書,彷彿真的可以搞懂電腦螢幕背後的一切魔法一樣,我也夢想著有一天能寫出自己的遊戲。但當時我沒想到的是,我還真的花了十幾年的時間在探索電腦的魔法…。

MUD與黑白棋

升上國中後,家裡裝了一台28.8kbps的modem,當時的internet還沒完全成形,在沒有Google的時代internet是沒什麼價值的。當時的modem最常被我拿來上一些撥接式的BBS,那時候的撥接BBS站台還不少,最棒的是還能從站上抓到很多軟體和各式各樣的教學文章,像是如何用組合語言寫電腦病毒,如何破解大富翁2之類的文章。這些文章對當時的我就像武林密籍一樣,雖然沒辦法完全看懂,但我也是從中得到很多零碎的概念,像是16進位的換算、組合語言、中斷向量、常駐程式….。

在國二時,我還不小心迷上當時一個超熱門的MUD – 萬王之王(KK),每天放學回家都急著連上線,讓家裡電話整晚都忙線中,玩到每個月電話費都是上千元,搞得我媽數次警告要把modem收起來再也不讓我上網了。(還好她沒真的這麼做,不然我現在就沒辦法寫這篇文章了。)

MUD是現在MMORPG的純文字版,整個虛擬世界都用文字描述,並且只要用telnet就可以連上去玩了。但內行的玩家都知道,玩MUD應該要用 zMud或是UNIX下的tintin++,因為這兩個軟體可以設定所謂的trigger,偵測到某些事件的發生,就能自動採取事先指定好的動作。因為一切的訊息都是由文字呈現,所以偵測事件非常簡單,只要看看有沒有特定字串出現就可以了;而要做特定的動作也很簡單,就是送出文字指令而已。(眼尖的人一定會發現,這其實就是現在MMORPG外掛的最原始形式。)嚴格說起來,zMud是我首次寫「實用程式」的平台,我學會透過trigger在MUD的世界中寫自動化的機器人,自動在迷宮中遊走,自動換裝備打怪練功..。這時的我突然體會到,會寫程式真是太棒了,我在MUD中簡直跟神一樣。其實當時我也不過只會用最基本的變數、if、迴圈而已,但透過在虛擬世界中寫機器人的練習,讓我的邏輯思考概念有飛快的進步,也給我了非常強烈的動力想好好學一個正統的程式語言。

升上國三後,很幸運的透過推薦甄試提早上了台中一中,升學壓力解除後,老師和父母就完全不管我要幹麻了。這時我終於有了一段完整的時間可以好好的再把BASIC重新學過,無奈的是在我國三時QBASIC已經快滅絕了,取而代之的是Windows上的Visual Basic,我只好硬著頭皮買本新書來從頭學起VB。當時我看的是王國榮的VB 5入門書,整本書有六七百頁吧,比我國三所有課本疊起來都還厚,現在想想小時候真的有點不知天高地厚竟然相信自己能看完這麼厚的磚頭書。那時候我每天上課就帶著這本磚頭去學校,這樣看了幾個禮拜下來,沒想到我這時突然都看得懂了,很多原本不知道有什麼用途的概念突然都相互連結起來了。(多虧了在MUD裡的訓練!)就這樣,某天突然有種打通任督二脈的感覺,我發現我全搞懂了,迴圈、陣列、Windows GUI控制項、去背貼圖…,我突然想通要怎麼用程式語言寫出遊戲了。

從那之後,每天回家就是打開VB寫程式,我想寫個黑白棋來檢驗自己的想法,我把自己知道的所有概念都放進去,有GUI元件、有貼圖、有動畫、有音效..,這是我第一個完整的程式,從頭到尾每一行都是自己寫出來的。(以現在的眼光來說只能說是一個期末project規模的小程式,但對當時的我可是意義非凡)

這個黑白棋讓我印象最深的其實是debug的痛苦經驗。我花了一個禮拜把程式的核心部分完成,但在吃子的時候卻跑出一個不明的bug會打亂整個盤面。為了找這個bug,我又花了一個禮拜,每天從早到晚都在想哪裡寫錯了,後來慢慢trace了好久,才發現竟然只是一個變數忘了歸零!!!

這種bug很常見,不過只是programmer最容易犯的無心之過之一,但這件事對我的影響非常大,它讓我花了很長時間在想以後要怎麼避免犯同樣的錯。我後來才知道一個普通的programmer和厲害的programmer從這裡就會分出高下:普通programmer犯了這種錯會覺得很平常,並提醒自己下次別再這麼笨了,但實際上不久後一定又會再犯同樣的錯;厲害的programmer會反省自己寫程式的方法,並改變原有的方法或習慣來避免以後再度產生同樣的bug。

古老的程式設計教材(尤其是C語言),都說要把變數宣告在函式的一開頭,並且因為變數宣告完還得經過初始化,所以很多人習慣是在函式開頭宣告並初始化所有變數。這不是錯的,可是,這其實就是會導致bug的元兇。

因為變數在開頭就被初始化,這樣在真正要用到它的時候就能直接拿來用,但是如果這個變數需要被歸零(也就是重新初始化)並在迴圈中重複利用,就很容易會忘記要再多做這一步。(在多層迴圈中更容易發生)

我為這個bug苦惱了幾天,後來才意識到這是coding style的問題,只要改變宣告變數的習慣,就能避免犯這種錯誤。如果一開始就在迴圈內宣告並給定變數的初始值,而不是在函式開頭宣告,就不會有這種 bug跑出來了。有了這個經驗後,我歸納出一個原則:「永遠在變數需要被用到的最內層區塊才宣告並初始化該變數。」這種原則很重要,我日後一直放在心裡,它也幫助我避免掉未來再犯同樣錯誤的可能。(事實上,我後來再寫了十年的程式,再也沒有比這更痛苦更長久的debug經驗了…)

(待續)

Posted in 追求神乎其技的程式設計之道 | 17 Comments »