2013年11月24日 星期日

如何寫出有用的程式?

有網友在這篇 別讓危險成為預設的行為,讓危險的行為比安全的行為更麻煩 回應裡提到
WiyD-Luck
請問大大寫程式寫多久了
小弟今年大三要升大四了
在無意間近來大大的blog
收穫良多(請受小的一拜
會寫程式.跟會寫一個能用的程式.差別好大…
想問大大那些程式會造成的漏洞.是經過自己研讀還是有人指點才有如今的實力阿
PS.小弟就讀的大學老只有教我怎麼寫程式.並沒有教我寫出一個可以用的程式..
我覺得這是很多人心裡共同的疑問,所以就特地寫了一篇來說說我的看法…

個人的經驗

以我個人的經驗而言,開始有程式的概念大概是在小學六年級,那時喜歡自己做出些亂七八糟的網頁,就是那種整頁都是GIF閃個不停沒什麼內容的網頁, 傳到一些免費空間裡,不知怎麼的突然有點懷念那種亂七八糟的風格,總覺得有種復古的感覺,想說如果現在網頁刻復做成那樣應該蠻有趣的,接著開始用 Flash做一些小遊戲,在當時Flash不像現在有先進的ActionScript,我記得似乎是填某些表單,自動產生類似script之類的,在當時 開始有變數、流程控制等等很淺的概念
接著時間來到國一,在偶然的機會下接觸到了VB6.0,起初完全不懂怎麼寫程式,靠著剪貼、修改,最後終於知道怎麼寫一個簡單的VB6的程式,我還 留有第一個程式,只能做比大小,兩個文字欄輸入,按下按鍵它會告訴你誰大、誰小、或是相等,如此簡單的程式在當時做出來就有很大的成就感,在現在看來只不 過是幾行的程式,連縮排都沒有,但是卻是一個很重要的開始,在什麼都沒有的金門,靠的只是一條網路線,和一些電腦書,對於從小就喜歡拆東西、科學、機械之 類事物的我,這是一片可以自由創作的天地,透過寫程式,只要想得到的功能,就能透過程式寫出來,程式語言就像魔咒一般,只要唸出正確的咒語,事物就會依照 你的語意、你的意唸動起來,就像魔法一般,從此就開始了寫程式的興趣,每天放學回家就是寫程式,寫到一兩點第二天去學校睡覺,日復一日
在這個過程中,我寫過無數的程式,爛程式,這對於寫有用的程式來說,寫爛程式是一個很重要的經驗,正因為我寫過爛程式,所以才知道好的程式和爛的程 式到底差別在哪裡,我重寫過最多次的程式,是一款叫Dream On Line的線上遊戲,當時我很喜歡天堂這款線上遊戲,他好玩之處就是能當小白,還記得小六暑假就推出了,一開始在太陽神伺服器線上人數才700~800 人,一開始都沒有人會玩,大家看見村裡的雞鴨豬狗牛就猛追著砍,砍了一陣子發現自己名字似乎有點紅,這不是錯覺,的確變紅了,過一陣子,開始學著當小白, 故意剩一滴血負重跑去打別人讓別人還手一擊就把自己打死等等腦殘的白目行為,可以說是小白的始祖,這遊戲好玩的地方就是夠白目,我也想做出一個這樣的遊戲 自己來玩玩,於是就開始研究如何寫遊戲,研究Direct Draw等等,寫出了非常陽春的版本
夢想線上登入畫面
夢想線上登入畫面
夢想線上遊戲畫面
夢想線上遊戲畫面
雖然說這樣的遊戲看起來似乎有這麼回事,但其實其中的bug不少,像伺服器就極度的不穩定,動不動就會當機,隨著時間不停的前進,很多時候不是有那 麼多時間寫程式,而且在當時寫的程式都是硬寫出來的,常常沒有設計可言,隨著程式的膨賬,程式雜亂不堪常常覺得有心無力,每次回頭想寫時,就發現,為什麼 自己會寫出這樣的爛程式,連自己都看不下去,所以每次回頭過來的改寫,最後都是受不了自己的爛程式變成重寫,這個程式重寫了5~6次之多,我自己都快記不 清了
各個重寫的版本
某個重寫版本的地圖編輯器
某個重寫版本的地圖編輯器
某個重寫版本的Client
某個重寫版本的Client
更晚的重寫版本的Client
更晚的重寫版本的Client
更晚的重寫版本的地圖編輯器
更晚的重寫版本的地圖編輯器
更晚的重寫版本的Client 2
更晚的重寫版本的Client 2
最後的重寫版本的地圖編輯器
最後的重寫版本的地圖編輯器
最後的重寫版本的地圖編輯器
最後的重寫版本的地圖編輯器
即使每次都覺得自己以前寫的程式是垃圾,但從好的角度看來,這或許就是代表了進步,當然這遊戲只是我寫過的程式中的一部份,其它還有很多五四三的程 式,像是鍵盤記錄器之類的,而這個遊戲我還沒放棄它,我一直想找個時間想玩成它,比起當年,我永遠都覺得比當時更有把握寫出來,只是時間上的問題,但是是 不是這樣我就不知道了

來到了大學

來到了大學,在這之前我靠的都是自己、書、還有網路,當然也得感謝很多指導過我的人,起初我一直認為,我靠自己都能學成這樣,如果有人教一定可以學 得更快,有點像是中華小廚師裡雷恩想跑去暗黑暗料理界的那種感覺,希望能有更多、更快的進步,但是我卻發現,事實上倒頭來還是得靠自己讀,不過不可否認 地,在大學這三年裡我學到了很多我之前都一直不懂的理論,在之前我可能不懂多緒、多工背後context-switch怎麼運作,寫迴圈為什麼存取相鄰的 記憶體會比較快,原來是cache的原因,一直聽到什麼分支預測錯誤,不瞭解是什麼東西,修了計算機結構學,才瞭解原來CPU裡還有pipeline這種 機制在加速,才會有分支預測的問題,很多理論都是在這時建立起來,在這之前我會寫程式,但很多概念上可能不正確,在這之後我能從基本的原理出發,寫出更好 的程式來
所以,為什麼大學沒辦法教會你寫有用的程式?
在經過這些歷程,我想我很清楚為什麼大學資工四年沒辦法培養出一個可以寫出有用的程式的工程師,出在下列原因

程式作業生命週期太短

在資工系的大學生寫的程式,通常都是寫完交完就算了的程式,在這種情況下寫出來的程式,都是寫完丟就算了,程式的生命週期在交上作業的那一瞬間就結 束了,相較於我自己寫的遊戲,我不停地重新檢視自己的程式,差別就在於,一個程式如果一直改,它設計不良的地方就可以被看得出來,好的程式設計應該是要經 得起修改,但是大學因為作業交完就算了,可能再也沒有人會再看它第二眼,所以寫出來的程式常常都是硬寫出來的,規劃、維護什麼的都不需要,但是在現實世界 中,程式其實是寫完那一刻它的生命週期才正要開始,寫完了程式,交到客戶手裡,客戶發現bug、或是有新的需求,這時再改程式,初而復始,直到程式不再被 使用,程式的生命週期才正式結束,學校和現實的落差就在這裡,程式作業的超短生命週期讓它寫作的風格、設計都不受到重視,反正能交能跑就好,所以學生往往 在遇到真實的程式會用寫作業的方法寫,下場當然是很慘

程式的規模太小

除了生命周期短,規模小也是另一個原因,通常作業都是幾百行甚至幾十行可以打發的程式,然而在真實世界中,程式往往是用萬行在算的,像我寫的遊戲就 有上萬行的程式、甚至上十萬,而且還是好幾個程式,Server、Client、地圖編輯器等等,程式小,不經規劃和設計,硬寫也一樣可以寫出來,但是當 程式一大,不經過適當的規劃、分析、與設計,下場就會很慘,那重寫無數次的遊戲只是例子之一,我曾經接過一個Case,錯估了程式的複雜程度,打算隨便寫 就可以寫出來,後來發現複雜程度預估錯誤,所以加上了之前沒想到的部份,結果就非常慘,程式改這裡,那裡會跑出bug,而且你無法確定,這個bug到底是 誰的,是什麼東西引起的,因為設計不良,疊床架屋,一堆模組之間有亂七八糟纏在一起的關係,造成一點點修改就牽一髮動全身,整個程式陷入無限的debug 迴圈中,我發現這樣子下去不行,程式肯定寫不出來,所以就整個砍掉重寫,讓他們之間的關係,也就是藕合度降到最低,這才順利將程式寫出來,因為每個模組和 其它程式的關聯都很少,所以可以很輕易地確定這個模組是正確的,而且關係少了,出了bug誰和這模組有關,也很容易找出來,這些經驗都是要程式大到一定規 模才能會遇到的,在大學的作業通常規模都太小,學生自然不懂得設計,小程式硬寫也寫出來,何來的設計,而就算是畢業專題,通常也是寫完就算了,就算稍大一 點硬寫也一樣寫出來,所以沒有實務經驗是理所當然的
但是我有遇過有門課教授出程式作業的方式我相當認同,而且可以改善以上兩點問題,他的作業一開始是簡單的功能,然後後面出的作業都是要求原本的功能 加上另外的功能,如此一來,越到後來的作業規模會越大,程式也經過一再的檢驗,學生在這過程中可以學到程式如何重復利用,如果學生用硬寫的方式,很快就會 吃到我上面所說的苦頭,越到後來程式越來越大,硬寫的程式以前的程式難以擴充,除錯也困難,生命週期長了,學生也能從中學到寫出較容易維護的方式,就算不 知道,在以後看見了設計相關的概念,就會突然發現原來設計就是這麼一回事,在此我個人建議資工大學的課程,可以考慮用這樣的方式,設計每次增加一個小要求 的大程式,如此一來可以解決上面提到的問題

寫的程式太少

不止是生命週期和規模的問題,以資工四年的程式作業來看,如果學生寫的程式就只有作業真的是太少了,個人其實也不是很喜歡寫作業,因為不是很有趣, 並不是因為太簡單,難度不是問題,而是因為你覺得有沒有興趣,如果你對會計有興趣,或許可以自己寫一個財務報表的計算程式,如果你對物理有興趣,或許可以 寫個簡單的物理模擬程式,如果你對數學有興趣,或許你可以寫一個尋找超大質數或計算圓周率的程式,如果你對遊戲有興趣,就寫遊戲,其實有太多程式都不難, 而且都很有趣,像是鍵盤記錄器,聽起來很神奇,其實就只是一個掛在windows下的hook攔劫keyboard event而已,而木馬其實也只是利用socket等連線,一個指令一個動作,你傳什麼給我,我就做什麼的程式而已,有太多有趣的程式都比作業好玩,而實 際上又會用到,如果學生只單純的寫作業,可能什麼是Win32API永遠都不會用,而Open source的library又要怎麼樣用,學校通常也不會教你,debugger怎麼用? 也很少有人會教你,資料怎麼找? 也沒人會教你,文件怎麼看? 沒人教你,所以除了程式的作業以外,學會如何寫有用程式的不二法門就是多寫,沒有人規定你要寫什麼好,對什麼有興趣就寫什麼,在這個過程中你找資料、問問 題、解決的每個問題,都是你學到的經驗,而且課堂上通常都不會教你

不會找資料

我們從小到大的教育似乎範圍都只在教課書上,但事實上在實際的應用上很常需要自己找資料,現在有了網路、有了Google,即使找資料已經是這麼簡 單的事情,但是很學生還是不會找,舉個例子,當你手上有一個函數的名字,fopen,它是拿來做什麼? 你要如何使用它? 很多學生可能想都沒想過要找資料,甚至有些人用Yahoo!奇摩 搜尋引擎來找資料,不好意思,找資料請用Google,最簡單的方式就是fopen直接貼到google裡搜尋,通常你要的答案就會在那裡,但是有時候不 是這麼簡單可以找到資料,例如可能跑出來的是PHP的fopen而不是C語言的fopen,那你可能得這樣下關鍵字”C語言 fopen”,而這還算是好找的例子,有時候你想找你以前某個看過的東西,但是想不起來是什麼名字,關鍵字也不知道要下什麼,這時你可能要透過聯想的方 式,想一下應該找什麼會出現包含那個名字的網頁,再透過那個頁面再找你要的資料,有時甚至要這樣轉兩三次,很多人或許以為寫程式的能力就只有寫,但其實在 背後有很多其它的能力支撐,而資工系的學生可能很多都只會翻教課書,遇到問題或是想知道的東西不懂得找資料的技巧,當然所知範圍只限於課本的話,不用談寫 出有用的程式

不會閱讀

其實寫程式聽起來好像就只有寫而已,其實在背後需要大量的閱讀,當你拿到一份library的文件,要如何閱讀,當然這部份還扯到英文的能力,中文 的資料是有,但是通常都已經慢最新的東西許多,如果最新的東西都要等人翻譯你才能使用,早就已經落後好久,更新的東西又出來了,因此英文我認為是讀資工系 必備的能力之一,當然我一開始看英文資料也很痛苦,不懂的單字一堆,可能一開始大部份時間都在查單字,但是同樣一個單字,查一次、查兩次、查三次,查久了 就自然記起來了,而且很多同學可能有錯誤的讀法,喜歡一字一句讀,事實上很多資料只有某部份的東西是你要的,一字一句讀很快地會讓你失去耐心,大部份時間 都花在查字點上,進度可能只有一頁,這樣的方式理所當然會看不懂,正確的讀法,應該是要快速的描過一次,大概知道哪裡有什麼,像是工具書,或是說明文件等 用來查的東西更是需要這樣,不懂的單字其實可以不用急著查,先猜猜看,猜不到就算了,大概看懂就好,有時你發現你不懂的單字一次兩次多次地出現,這時表示 這個字很重要或是很常用的術語,此時再查這個字也不遲

不會問問題

比起查資料,問問題最好當作最後一個手段,因為你會問的問題通常別人都已經問過了,先問問Google吧,當你找了該找的地方發現沒有你要的問題, 這時才考慮問問題,雖然說問問題聽起來好像沒什麼,但是不會問問題一樣是很多同學的通病之一,有時同學問我問題,我聽了半天都聽不懂他到底想問什麼,原因 出在於可能自己都沒有把問題先整理過,這是很重要的步驟,多例如像程式出現bug,想要貼上網問,有些人就全部的程式一口氣貼上去,事實上程式可能只有一 小部份有問題,這樣做讓回答問題的人很煩腦,必須看完整個無關的程式,降低回答的意願,最好的方法是先把想問的問題整理出來,以程式片段來看,就是把無關 的部份刪去,然後只剩下可以重現出那問題的程式片段,如此一來回答問題的人可以很快找到問題所在,而且這樣做有個好處,就是常常在整理問題的過程中,就發 現問題在哪裡,其實其中就包含了推導的過程,很多同學常常不懂怎麼問問題,當然也不知道怎麼解決問題
用英文問問題一樣是一個很重要的技能之一,這一樣扯到了英文的能力,當學會問問題之後還不夠,很多東西出了問題,你必須用英文到那東西的出處去問問 題,例如像是open source的library,英文絕對是電腦領域的官方語言,其實用英文問問題不難,就算文法有些錯誤,其實也不要緊,只要大家能懂你的意思,基本的禮 貌做到,該找的資料先找了,通常他們都很樂意回答你的問題,懂的單字都很簡單也沒關係,我個人就傾向以最簡單的單字來表達我想說的,我知道可能有些單字在 字義上能更精確地表達那意思,但是那樣的單字我通常都不知道或記不住,我們不是在寫什麼作文比賽,什麼華麗的詞藻就丟進馬桶裡沖掉吧

沒有興趣不要來念資工

能做到上面說的這些,通常是有一定的興趣才辦得到,沒有興趣,難以支撐這背後所需要花的心力,最好不要來讀資工,很多幼稚的父母總喜歡要自己的小孩 去擠所謂的熱門科系,也從不過問到底他們的興趣是什麼,一心只想說熱門等於有錢賺,其實這是很大的錯誤,以資工來說,如果讀了四年什麼都不會,這樣的人根 本不會有什麼人想雇用,即使有的話,也頂多是少得可憐的薪水,並不會因為有資工系畢業的文憑而有任何保障或前途,與其花四年在所謂的熱門科系上不如在自己 有興趣的事物上,如果畢業時才發現,父母逼你讀的熱門科系已經成為了夕陽產業,父母又要如何替你負責? 所以沒有興趣的話,不要來讀資工,往你最有興趣的方向發展,遠比在資工系裡一無所獲來得好,所以如果以有人逼你讀你不想讀的資工時,請告訴他們「我的人生 是我自己要過的,你沒辦法替錯誤的選擇負責,而我可以」

最後

如果我說的這些你都做到了,恭喜你,不敢保證,但是至少隨著時間會越來越強,懂得越來越多,到今天我也跟原po一樣,大三要升大四了,背後花了9年 的時間,大學畢業剛好十年,有人說,培養一項專業要十年,但其實我覺得學越多越會覺得懂越少,十年過後,其實才正要開始,只要有興趣、有心做,當然,有人 教是更好更快,程式設計不難,每個人都能設計出有用的程式

http://blog.ez2learn.com/2009/06/27/how-to-write-useful-program/#more-598

沒有留言:

張貼留言

標籤