2008年4月28日

程式設計之快速入門法

程式設計對大部分人來說,都會感覺是非常專業的東西。
從我小時候接觸到的電視、電影經常可以發現到,裡面的電腦高手,往往都是對著電腦不斷的打字,然後螢幕不斷顯現各種奇怪的畫面或程式碼,就算程式碼出現的只是9x9乘法表,都還是會讓人感覺非常的專業。
也許因為電腦的發展往往跟『高科技』畫上等號,又也許電腦常常出現在讓人感覺不可思議的場合,也可能是電視、電影長期灌輸的電腦高手印象,不論是任何人,只要看到在寫程式的人,都會從內心升起一股莫名的崇拜。

而我個人來說,從國小就開始玩電腦,還記得小學六年級上電腦課,還簡單的寫過GW Basic,以我的年紀來說,和一些年長些的高手相比,我還嫩了些(看過有blog,有比我大10歲左右的高手,在那個年代就在超頻286、386),但跟其他大部分的人相比,我的電腦經驗算是很早的了。

很多人想要學習程式設計,會去上課、補習,很多人在學校上電腦課上了一個學期,仍然不會寫程式,看著一些所謂的電腦高手,短時間內就可以把程式寫出來、跑出來,往往都會感覺很不可思議,從內心發出一聲『高手阿~』的吶喊。
包括我在內的許多可憐蟲,只有在這種時候,才會莫名的受到歡迎,班上不熟的男女咖,會在這種時間點突然跟你聊天,這種時候就會想,電影上又高又帥的電腦高手,其實從來不曾出現在現實生活中~(抱怨到此結束~)

那到底程式要怎麼寫?怎樣才可以快速的入門,學會程式寫作?

經過這麼多年的經驗後,我可以告訴大家,關鍵只有2個:
1. 語法(包含if, for, while...等使用)
2. 函式

不論是哪種程式語言,不管是硬體的、軟體的,比較硬一點的,比較軟一點的,軟硬適中的,通通脫離不了上述2個關鍵,差別只在稱呼和用法。

以高階的程式語言來說,我們拿Java來說(我Java還是比較熟些,比較不會漏氣... :p),跟C相比,Java的語法比較特別,因為它有物件導向的概念,所以程式碼長的會和C比較不同,而和其他物件導向的語言相比(c#、php...等),因為概念很接近,又都互相摹仿,所以語法會長的很接近。
我在之前曾經提過關於Java物件導向主程式的樣式,這類樣式通常是很固定的語法,建議直接背起來比較快,因為解釋了半天,結論還是把它背起來。
其他比較細節的語法,以Java來說,String a = new String();這種樣式,通過Example的一再練習,可以幫助快速的熟悉語法。

而程式語言的另一個重點在於函式,當我們語法熟悉之後,最重要的就是要找出這個語言提供的函式,了解我們有哪些函式可以使用。
以我個人感覺來說,以100分為滿分來看寫程式這件事情,會語法可以讓你從0分變成35分,知道函式之後,可以讓你從35分變成70分,2者對於寫程式的重要性就是這樣。

也許會說,你提的是高階語言,那低階語言呢?
以8051組合語言來說,以我之前當助教的經驗來說,很多人覺得很難,我以前還不相信資工的會怕寫程式,在我親自上課、帶課之後,才深刻發現到,原來資工的同學,對於組合語言有種莫名的懼怕,這是我以前在電子科系時候沒有出現過的。
以8051組合語言來說,同樣可以代入上述的2個關鍵,只是稱呼有些不同,在8051組語中,兩者分別是:
1. 語法
2. 指令集

其實8051組語給我感覺比PC上的Java簡單非常多,它的函式(指令集)從頭到尾,從尾到頭,怎麼數也都是那十幾二十個。
不論怎麼變化,永遠都是這些指令集的搭配使用,基本上能夠掌握住指令集,看得懂語法,知道如何用指令集來寫出if, for,那麼基本上8051大概前1/3的課你已經ok了。

同樣的情況也適用在Verilog這類硬體描述語言,尤其是Verilog,它的語法長的跟高階語言比較像,入門其實容易些,因為我這方面不很熟,只修過一個學期的課,能力僅僅只是用C的寫法去寫Verilog,不符合block設計的概念,模擬時還ok,實際下去跑,我相信會有很嚴重的delay問題,細節就不方便拿來解釋了。

電腦其實是很單純的東西,不論它的程式怎麼變化,最基本就是很多很多的指令(指令集),所謂的程式,就是指令集的組合。
當程式的層次提昇之後,指令集已經不足以描述程式的動作了,因此變成了function(函式),但這些函式的設計,本質上和指令集是類似的,當加入物件導向概念之後,function為了適應物件導向的敘述和設計,變成了類別、物件(Class),但本質上來說,仍舊是指令集的延伸,因此程式設計上,就是先找出能夠使用的指令集、function、Class。

而語法也是一樣的情況,因為程式的層次不同,最底層就是使用特定的格式把指令集組合起來,並使用if(8051組語中的JZ xx xx,當暫存器內容等於0的時候跳), for(DJNZ xx xx,當暫存器內容-1等於0之後跳;非8051的單晶片,很多沒有DJNZ這樣的指令,同樣可以用SUB xx xx加上JZ xx xx,讓暫存器內容-1,等於0時跳)讓電腦進行判斷和重覆操作,這就是電腦最基本的操作方式。
而層次不斷的提昇,可以讓程式的複雜度越來越高,但是基本上仍舊脫離不了電腦本質的操作方式(if, for),而為了更接近人的語言,專門設計了int x = 10;這樣的敘述樣式和String x = new String();這樣的敘述樣式,但根本上還是組合函式(組合指令集),並使用if, for的電腦操作。

結論,從上面提到的一堆可以知道,要學寫程式,最快的方式就是了解語法,找出可以用的函式,只要掌握這兩點,我相信任何程式語言都能夠比較快速的上手。

看到這裡其實文章算是結束了,但是可能會有人有疑問,感覺還差了甚麼,也有人會問,上述2點掌握了,我能拿到70分,那要拿80,90甚至更高要怎麼拿?所以我加了這段~

要拿到70分很容易,要拿更高就有難度了,關鍵在於:
3. 了解程式語言的模式、設計

這部分以8051組合語言來敘述很貼切,8051前面1/3除了頭2堂課解說8051的接腳、歷史之外,主要在教基本I/O和語法,先讓同學熟悉語法。
但是從1/3開始,會開始教Timer、中斷、七段顯示器操作、鍵盤掃瞄...等,這每個部分的程式設計都很特別,都具有某些特色,像Timer要使用要先設定某些暫存器,中斷要使用要設定某些暫存器,中斷又能和Timer搭配使用,鍵盤掃瞄要以迴圈方式不斷的檢查按鍵...等,這些就是8051組合語言的模式、設計。
同樣的道理也出現在Java上,Java許多Class我們都需要看Example,而且Class之間使用的方式差異性很大,像是Java的I/O(BufferedReader、BufferedWriter)這種設計就和C的I/O完全不同,沒看過範例,可能很難了解怎麼使用它,這就是Java在I/O的模式、設計。
在Java上同樣情況也發生在資料庫呼叫(JDBC操作),JDBC固定那4,5個步驟,如果沒看過Example,很難理解它要怎麼寫,這就是Java在資料庫操作的模式、設計。
而在Linux上的C也是這樣,因為在Linux上,相對Java來說又是比較低階的程式語言,有許多POSIX特性的設計和function,像我之前寫MYVIDEO時才學到的IOChannel,這在舊版的Java是沒有的,都要用Thread,新版的Java(1.5還是1.6吧~)才加入了類似的機制。
而在Verilog更是明顯,Verilog的設計都以Block為思考方式,設計上比較接近pipeline的概念,程式設計強調的是同時所有Block一起操作,但每個Block只操作一個動作,而且Block設計的程式碼以精簡為訴求,Block內程式愈短,整顆IC在每個clock的delay可以控制的愈短。
這以高階語言來看,有點像是同時設計超多的Thread,每個Thread要求又要像Interrupt內容一樣,愈短愈好。
而程式多半建議以加法器、減法器來組合,概念類似AND、OR、NOT的邏輯閘算式,這就是硬體描述語言的模式、設計。

這部分的經驗愈豐富,看的Example愈多,分數可以拿的愈高,掌握基本的幾個模式、設計,分數可以從70分拉到80甚至90分沒問題。

而我認為最後一個程式設計的要點,算是:
4. 演算法&Model

這點和3有些關係,畢竟很多模式、設計,都是演算法&Model實作出來的,所以第3點和這第4點間的界定有些模糊。
不可否認,電腦其實就是計算機,計算機主要就是用來算數學用的,所以電腦最初的發展,就是用來進行高速運算,一直到現在,儘管電腦有了很多發展方向,但運算能力仍舊是電腦的主要核心,高速運算也一直是電腦發展中一個主要的領域之一。
正因為如此,演算法在電腦的程式設計中,是很重要的部分,目前全世界有數不清的演算法正在發展,但更多的是成熟的電腦演算法,要晉升到電腦高手,程式設計能力要從80~90上升到90以上,學習電腦演算法是不可避免的,正如前面提到的,很多模式、設計都是從演算法、Model實作出來的,但我們無法保證所有程式語言都有提供這些演算法,這時候如果能夠自行寫出符合環境需要的演算法,那麼對於程式效能、程式功能都會有決定性的影響。
而Model也是,因為電腦程式越來越複雜,大量的Interface和Model是不可避免的,這可以降低程式的複雜度,讓程式碼更容易理解,更方便開發,電腦設計中同樣有很多成熟的Model被廣泛運用,這類的Model接觸愈多,對於程式設計的幫助愈大。

我個人評價,當你已經是個腦中有許多演算法設計、許多Model設計,又對於很多程式的模式、設計很有經驗,那麼你可以打聽看看別人對你的電腦評價,應該不會低於85分。

5 則留言:

dabinn 提到...

程式寫的好,好人作到老...

yen3 提到...

這樣子寫Design Patterns, Refactoring 之類的高度工程藝術被忽略了,有點可惜

匿名 提到...

沒什麼可惜的
很多事都是做了才知道問題, 很多系統也是寫了才知道問題, 與其套用 pattern, 倒不如給自己一個完美的期許, 根據需求不斷精修再精修。
以上是個人淺見

yen3 提到...

受教了,謝謝

倒也不會套用pattern,比較習慣寫程式遇到了,或許這個問題會在腦中跳出一個亮光說,喔,好像可以,因此試試,不為了pattern而pattern。這是一件蠻重要的事。

匿名 提到...

不敢說指教, yen3兄提到的不為了pattern而pattern正是小弟要表述的重點
離題了XD, sorry啦, 版主