<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>vgod&#039;s blog &#187; 追求神乎其技的程式設計之道</title>
	<atom:link href="http://blog.vgod.tw/category/divine-code/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.vgod.tw</link>
	<description>資訊 &#124; 科技 &#124; 程式設計 &#124; 人機互動 &#124; MIT &#124; Apple</description>
	<lastBuildDate>Tue, 20 Dec 2011 13:01:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>追求神乎其技的程式設計之道（番外篇）</title>
		<link>http://blog.vgod.tw/2011/02/23/divine-code-extra/</link>
		<comments>http://blog.vgod.tw/2011/02/23/divine-code-extra/#comments</comments>
		<pubDate>Wed, 23 Feb 2011 06:45:41 +0000</pubDate>
		<dc:creator>vgod</dc:creator>
				<category><![CDATA[追求神乎其技的程式設計之道]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.vgod.tw/?p=857</guid>
		<description><![CDATA[我的學習過程 還記得小時候我和我弟上過一個奇特的數學補習班，叫做「功文數學」。他們的「教學」方法非常特別，不像一般的教室會有一個老師在講台上教課，而是每個人會拿到一疊數學題目，每一面都有數個計算問題，像是「10 x 2 = ?」這樣的問題。每次去功文的任務就是把那一疊題目寫完，寫得越快的人就可以越早回家。那些題目說來沒什麼意思，從頭到尾全都是計算問題，難度從最基本的加減乘除，一直到微積分都有。每次寫完題目後，會有個類似老師的角色，拿出解答本幫你對答案，打上成績。如果在那老師能應付的範圍內，他可能還會跟你說說哪裡犯錯了，下次多加油之類的，但如果到了國高中程度的問題時，老師的作用就只剩對答案而已了。 我之所以說這個補習班很奇妙，原因就在於這個教學過程中，講求的是大量的計算和自我學習的能力。我從加減乘除開始，一路這樣寫到了微積分，寫到後來那邊的老師也沒辦法批改了，乾脆把解答本拿給我們看，讓我們自己看解答學。起初我還覺得這個補習班挺不錯的，只要我做得越快就能越早回家，對小孩子來說是個很好的誘因。而且因為大量的訓練，讓我的計算能力變得非常好，國小國中時的數學考試我都不用準備也能很快寫完交卷。但後來我開始覺得不太對勁，很多題目我雖然知道怎麼算，但我其實不懂為什麼要這麼算，或是這麼算的意義是什麼。可是台灣的考試也不管這個，反正你只要能得到答案，根本沒人在意過程是怎樣。 功文數學的這套方法對訓練計算能力而言很有幫助，因為計算就是需要大量的練習才能變快變好。但問題是，計算能力再好，也是只能算已經定義清楚的問題（也就是考卷上的問題），而無法發現新問題並定義問題，更糟的是還會讓人習慣在沒有完全理解背後的概念時只學得方法快速得到答案。 在我高中開始參加程式比賽後，我用了我熟悉的這套方法訓練自己的程式能力，自己一個人大量的找題目練習。每天從早練到晚，即使沒有人教我也覺得很正常，因為我從小就是這樣自學起來的。這樣練了一年後，我能飛快的寫程式和解題，看到熟悉的題型就能馬上開始敲鍵盤，但同時我也開始覺得寫程式變成一種機械化的過程：看題，解題，寫程式，看題，解題，寫程式&#8230;。跟我從小做數學似乎沒兩樣。 我開始覺得無趣。即使我程式寫得再快再好，也只是解出一個別人設計好的問題而已。 心中的聲音不斷的說：「為什麼我要做別人早就知道答案的問題？」 我想要做沒有人做過的事，看到沒有人看到的問題，再親手解決這些問題。 當我開始這麼想的時候，我正在一邊學著做科展。科展全名是科學展覽，意味著要做點跟科學有關的事來展覽。以前的文章提過，我高三時夢想著要讓電腦自己寫程式，我覺得這是一件沒人做過的事，非常酷，所以我就一直專注在這件事上（其實當時就有很多人在做這種研究了，只是我不知道而已）。但從一開始到我被選上去美國參加國際科展時，我都一直不覺得這件事科學在哪，頂多說是一個工程（或工藝）作品。但選上代表後是有些好處的，台大的歐陽明教授給了我一些指引，讓我知道「科學方法」得測量和量化這個作品的結果，才有客觀的數據可以知道它的作用，進而跟其他相似作品比較好壞，也因此我才開始對「做研究」這件事有點概念。（到這時我才想起來，小時候雖然有做一些物理化學實驗，但從沒人跟我說過這些實驗是有一套標準的方法和流程的，當然也沒人跟我說這件事的價值所在。） 雖然做科展挺有趣的，但同時我也對科學感到失望 &#8211; 因為我意識到科學方法沒辦法幫助我們發明新東西，只能用來評估和檢驗已知事物的好壞。至於所謂的創新科學研究，也是得先提出一個假設(hypothesis)，然後再用這套標準方法去驗證它是否成立。但到底要假設什麼事情呢？科學可沒辦法告訴你。 上大學後，我看到當時處在黃金時代的MIT Media Lab所產出的許多創新研究成果，也開始接觸到設計(design)這個領域。我發現Media Lab的人大多有跨領域的背景，像是設計師+電機工程師、或是音樂家+軟體工程師，他們常看到別人看不到的問題，並提出簡單又優雅的解決方法。我以前一直以為做設計的人講求的是美術天份，但後來深入了解後才發現這是個大誤會。設計的目的是解決問題，跟程式設計師其實沒兩樣，只是用的工具是紙筆或模型罷了。（但一個好的設計通常也都很「美」就是了） 雖然如此，設計師和工程師也有很大的不同。設計師對四周環境和日常生活很敏感，常常得在生活中注意各種細節的不完美之處。但工程師成天泡在電腦中，而且很善於使用其實很難用的介面和程式（像Linux、vi、command line、還有各種程式語言），甚至引以為傲，日子久了也就不覺得這些東西有什麼問題。泡在程式碼中的工程師也一樣，如果習慣了和前人或其他人的大便碼相處，久了也就不覺得臭了。 發現這些現象後，我開始學著跳脫出原本習慣的一切，開始注意生活周遭的各種細節，思考為什麼這個東西當初要這樣設計、這樣做有什麼好處和壞處、有沒有更好的方式之類的問題。之後，當我習慣觀察細節後，慢慢察覺到我習慣用的軟體、工具、環境、程式語言，處處都是設計後的結果，而且充滿可以改進和創新的空間。這些東西都不是沒來由的產物，而是經過某些人思考過後的結果，甚至是經過好幾輪的演化結果。可惜平常在學習或教學的時候，很少人會提到這些歷史淵源和演化過程，以至於這些設計都變成理所當然的存在。但如果我們能仔細觀察平常的事物，進一步思考就會發現很多設計都是為了因應當初時空環境的限制，而這些限制現在不一定存在了，所以我們就會有發揮的空間。 眼光拉遠後，能看到的問題更多了。到了這個階段，能力強的人會覺得能解決的問題也很多。但上天給每個人的時間是一樣多的，這時重要的事情反而又變成：「找出最重要、最根本的問題來解決，而不要被眾多的小問題和小機會所分心，才能產生最大的影響力」。 回顧我的學習過程，我會覺得每一個階段都是一塊基石，一塊塊往上疊以後才會具備該有的能力和經驗做下一階段的事情。舉例來說，要是我一開始沒投入程式比賽的練習累積足夠的實作能力，之後我就沒辦法隨心所欲的寫出我想寫的程式，也沒辦法參加科展體會做沒人做過的事有多麼有趣。之後我可能就會一昧沉浸在鑽研各種流行技術中，或是眼高手低說得一嘴好主意但卻做不出什麼來。 雖然學習是一步一步往上走的，但過程中每件事都有反面的效應，讓我不知道是不是做別的選擇會更好。像是我覺得功文數學浪費了我太多時間在數學計算上，而限制了我在其他方面的發展，但同時它也讓我養成靠自己學習的習慣；參加程式競賽也有類似的效應，雖然增強了我的程式能力，但也讓我錯過正常的高中生活和課程（雖然說到目前為止沒有覺得有什麼負面影響）。 無論如何，我相信在成長的過程中適當的大量練習是必要的。異數(Outliers: The Story of Success)一書的作者Gladwell說要精通一件事情至少需要一萬小時的練習，我相信這是真的。我在高中為了比賽所做的練習起碼就超過五千小時，上大學後輕易就超過一萬小時，但其實我也不覺得我真的精通了什麼。經過大量的練習，本來很難的技巧或技術都會變成一種本能，可以很自然的使用它來從事更高階的應用或是建構更複雜的技術。沒有這些基礎，也就很難站在更高的地方看得更遠想得更多，我也不會走在現在的道路上。]]></description>
			<content:encoded><![CDATA[<h3>我的學習過程</h3>
<p>還記得小時候我和我弟上過一個奇特的數學補習班，叫做「功文數學」。他們的「教學」方法非常特別，不像一般的教室會有一個老師在講台上教課，而是每個人會拿到一疊數學題目，每一面都有數個計算問題，像是「10 x 2 = ?」這樣的問題。每次去功文的任務就是把那一疊題目寫完，寫得越快的人就可以越早回家。那些題目說來沒什麼意思，從頭到尾全都是計算問題，難度從最基本的加減乘除，一直到微積分都有。每次寫完題目後，會有個類似老師的角色，拿出解答本幫你對答案，打上成績。如果在那老師能應付的範圍內，他可能還會跟你說說哪裡犯錯了，下次多加油之類的，但如果到了國高中程度的問題時，老師的作用就只剩對答案而已了。</p>
<p>我之所以說這個補習班很奇妙，原因就在於這個教學過程中，講求的是大量的計算和自我學習的能力。我從加減乘除開始，一路這樣寫到了微積分，寫到後來那邊的老師也沒辦法批改了，乾脆把解答本拿給我們看，讓我們自己看解答學。起初我還覺得這個補習班挺不錯的，只要我做得越快就能越早回家，對小孩子來說是個很好的誘因。而且因為大量的訓練，讓我的計算能力變得非常好，國小國中時的數學考試我都不用準備也能很快寫完交卷。但後來我開始覺得不太對勁，很多題目我雖然知道怎麼算，但我其實不懂為什麼要這麼算，或是這麼算的意義是什麼。可是台灣的考試也不管這個，反正你只要能得到答案，根本沒人在意過程是怎樣。</p>
<p>功文數學的這套方法對訓練計算能力而言很有幫助，因為計算就是需要大量的練習才能變快變好。但問題是，計算能力再好，也是只能算已經定義清楚的問題（也就是考卷上的問題），而無法發現新問題並定義問題，更糟的是還會讓人習慣在沒有完全理解背後的概念時只學得方法快速得到答案。</p>
<p>在我高中開始參加程式比賽後，我用了我熟悉的這套方法訓練自己的程式能力，自己一個人大量的找題目練習。每天從早練到晚，即使沒有人教我也覺得很正常，因為我從小就是這樣自學起來的。這樣練了一年後，我能飛快的寫程式和解題，看到熟悉的題型就能馬上開始敲鍵盤，但同時我也開始覺得寫程式變成一種機械化的過程：看題，解題，寫程式，看題，解題，寫程式&#8230;。跟我從小做數學似乎沒兩樣。</p>
<p>我開始覺得無趣。即使我程式寫得再快再好，也只是解出一個別人設計好的問題而已。</p>
<p>心中的聲音不斷的說：「<b>為什麼我要做別人早就知道答案的問題？</b>」</p>
<p>我想要做沒有人做過的事，看到沒有人看到的問題，再親手解決這些問題。</p>
<p>當我開始這麼想的時候，我正在一邊學著做科展。科展全名是科學展覽，意味著要做點跟科學有關的事來展覽。以前的文章提過，我高三時夢想著要讓電腦自己寫程式，我覺得這是一件沒人做過的事，非常酷，所以我就一直專注在這件事上（其實當時就有很多人在做這種研究了，只是我不知道而已）。但從一開始到我被選上去美國參加國際科展時，我都一直不覺得這件事科學在哪，頂多說是一個工程（或工藝）作品。但選上代表後是有些好處的，台大的歐陽明教授給了我一些指引，讓我知道「科學方法」得測量和量化這個作品的結果，才有客觀的數據可以知道它的作用，進而跟其他相似作品比較好壞，也因此我才開始對「做研究」這件事有點概念。（到這時我才想起來，小時候雖然有做一些物理化學實驗，但從沒人跟我說過這些實驗是有一套標準的方法和流程的，當然也沒人跟我說這件事的價值所在。）</p>
<p>雖然做科展挺有趣的，但同時我也對科學感到失望 &#8211; 因為我意識到科學方法沒辦法幫助我們發明新東西，只能用來評估和檢驗已知事物的好壞。至於所謂的創新科學研究，也是得先提出一個假設(hypothesis)，然後再用這套標準方法去驗證它是否成立。但到底要假設什麼事情呢？科學可沒辦法告訴你。</p>
<p>上大學後，我看到當時處在黃金時代的MIT Media Lab所產出的許多創新研究成果，也開始接觸到設計(design)這個領域。我發現Media Lab的人大多有跨領域的背景，像是設計師+電機工程師、或是音樂家+軟體工程師，他們常看到別人看不到的問題，並提出簡單又優雅的解決方法。我以前一直以為做設計的人講求的是美術天份，但後來深入了解後才發現這是個大誤會。設計的目的是解決問題，跟程式設計師其實沒兩樣，只是用的工具是紙筆或模型罷了。（但一個好的設計通常也都很「美」就是了）</p>
<p>雖然如此，設計師和工程師也有很大的不同。設計師對四周環境和日常生活很敏感，常常得在生活中注意各種細節的不完美之處。但工程師成天泡在電腦中，而且很善於使用其實很難用的介面和程式（像Linux、vi、command line、還有各種程式語言），甚至引以為傲，日子久了也就不覺得這些東西有什麼問題。泡在程式碼中的工程師也一樣，如果習慣了和前人或其他人的大便碼相處，久了也就不覺得臭了。</p>
<p>發現這些現象後，我開始學著跳脫出原本習慣的一切，開始注意生活周遭的各種細節，思考為什麼這個東西當初要這樣設計、這樣做有什麼好處和壞處、有沒有更好的方式之類的問題。之後，當我習慣觀察細節後，慢慢察覺到我習慣用的軟體、工具、環境、程式語言，處處都是設計後的結果，而且充滿可以改進和創新的空間。這些東西都不是沒來由的產物，而是經過某些人思考過後的結果，甚至是經過好幾輪的演化結果。可惜平常在學習或教學的時候，很少人會提到這些歷史淵源和演化過程，以至於這些設計都變成理所當然的存在。但如果我們能仔細觀察平常的事物，進一步思考就會發現很多設計都是為了因應當初時空環境的限制，而這些限制現在不一定存在了，所以我們就會有發揮的空間。</p>
<p>眼光拉遠後，能看到的問題更多了。到了這個階段，能力強的人會覺得能解決的問題也很多。但上天給每個人的時間是一樣多的，這時重要的事情反而又變成：「找出最重要、最根本的問題來解決，而不要被眾多的小問題和小機會所分心，才能產生最大的影響力」。</p>
<p>回顧我的學習過程，我會覺得每一個階段都是一塊基石，一塊塊往上疊以後才會具備該有的能力和經驗做下一階段的事情。舉例來說，要是我一開始沒投入程式比賽的練習累積足夠的實作能力，之後我就沒辦法隨心所欲的寫出我想寫的程式，也沒辦法參加科展體會做沒人做過的事有多麼有趣。之後我可能就會一昧沉浸在鑽研各種流行技術中，或是眼高手低說得一嘴好主意但卻做不出什麼來。</p>
<p>雖然學習是一步一步往上走的，但過程中每件事都有反面的效應，讓我不知道是不是做別的選擇會更好。像是我覺得功文數學浪費了我太多時間在數學計算上，而限制了我在其他方面的發展，但同時它也讓我養成靠自己學習的習慣；參加程式競賽也有類似的效應，雖然增強了我的程式能力，但也讓我錯過正常的高中生活和課程（雖然說到目前為止沒有覺得有什麼負面影響）。</p>
<p>無論如何，我相信在成長的過程中適當的大量練習是必要的。異數(Outliers: The Story of Success)一書的作者Gladwell說要精通一件事情至少需要一萬小時的練習，我相信這是真的。我在高中為了比賽所做的練習起碼就超過五千小時，上大學後輕易就超過一萬小時，但其實我也不覺得我真的精通了什麼。經過大量的練習，本來很難的技巧或技術都會變成一種本能，可以很自然的使用它來從事更高階的應用或是建構更複雜的技術。沒有這些基礎，也就很難站在更高的地方看得更遠想得更多，我也不會走在現在的道路上。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.vgod.tw/2011/02/23/divine-code-extra/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>追求神乎其技的程式設計之道（十一）- 抽象化與命名</title>
		<link>http://blog.vgod.tw/2011/01/31/diving-code-11/</link>
		<comments>http://blog.vgod.tw/2011/01/31/diving-code-11/#comments</comments>
		<pubDate>Mon, 31 Jan 2011 03:01:30 +0000</pubDate>
		<dc:creator>vgod</dc:creator>
				<category><![CDATA[追求神乎其技的程式設計之道]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.vgod.tw/?p=903</guid>
		<description><![CDATA[追求神乎其技的程式設計之道系列： 一 二 三 四 五 六 七 八 九 十 休眠已久的神乎其技系列又復活了！這篇文章其實寫很久了，只是一直斷斷續續到今天才完成它，久到讓很多人覺得這系列已經完結了&#8230;。但我想只要我還有在寫程式，這系列就永遠不會結束吧。 簡潔、彈性、效率 我一直覺得寫程式是一種藝術活動。程式語言是一種要求極度精確的表達方法，只要少打一個字母就可能造成完全不同的結果，但同時卻又不限制你要如何達到目標。 程式設計師有極大的自由來讓一個程式按照自己的想法「活起來」，不同人針對同樣的目標所寫的程式也一定不同。有人會用極簡主義來把變數命名為a、b、c，也有人會把用匈牙利命名法讓變數前後長出鬍子和尾巴；有人堅守DRY原則(Don&#8217;t repeat yourself)，只要類似的程式出現兩次，就把他們抽象化成一個函數，也有人用copy/paste寫程式，不管怎麼page up或page down都一直看到一樣的東西還能泰然自若；有人寫程式把所有東西都塞在main裡面，也有人寫個Hello world就要搞一個class HelloWorld（雖然有些時候是被囉嗦的J語言強迫的&#8230;）；有人沒聽過Big O也寫程式寫得很開心，但也有人嫌stdlib的qsort太慢硬是要自己重寫一個&#8230;。 儘管每個人的信仰和原則不同，但大體上程式藝術家也不過是在「簡潔」、「彈性」、「效率」這三大目標上進行一連串的取捨(trade-off)和最佳化。 「簡潔」的程式也「易讀」，沒有多餘的敘述或重複的程式碼，每個概念都只有唯一的一段碼在描述它。如果多了，就容易產生不一致的行為，如果少了，就是沒做到該做的事。有「彈性」的程式容易修改和擴充，只要在一個對的地方彈彈手指，不用因為老闆朝三暮四或是需求改變就得把整個程式重新翻修一次。有「效率」的程式會用最適合的資料結構存放每一樣資料，用最快的演算法做每一項必要的計算，並去除任何不必要的間接行為 (indirection)。 雖然目標很明確，但程式設計之所以像藝術就是因為大部分時候我們都沒辦法兼顧這三項目標：為了效率，可能就得犧牲彈性和簡潔；反過來說，為了彈性或簡潔，也常得犧牲效率作為代價。幸運的是，效率的追求在電腦硬體和編譯器技術的進步下已經不像20年前那麼重要，只要選對資料結構和演算法，幾乎已經沒有必要手動做低階的最佳化。除去效率之外，彈性和簡潔其實是比較容易同時達到而又不互相衝突的目標。要達到這目標，其中關鍵的能力就是今天的主題：「抽象化」(abstraction)。 最簡單但也是最難的事情 很多人沒聽過抽象化這個詞，甚至以為自己不會這件事，但其實從我們宣告第一個變數起，抽象化就已經開始了。 「這個變數要叫什麼名字？」 幫變數命名時，其實就是在賦予那個變數一個「意義」。人的記憶力有限，很難記住大量且沒有意義的資訊。但如果資訊有了一個固定且有邏輯的名字，我們也就有一個容易記憶的符號來代替整個複雜的概念。換句話說，我們可以把非常複雜的概念濃縮為一個容易處理和記憶的小單位，這個過程就叫做「抽象化」。 抽象化可以讓程式變得簡潔。好的程式設計師會習慣從重複的程式碼中找出共同或相似的部份，並且把這個部分提取出來變成一個更通用的概念。任何複雜的概念都可以被抽取出來替換成一個變數、一個函數、一個類別、一個模式、一個模組、甚至是一個系統，並加上適當的命名，就能讓這個程式「一看就懂」，任何註解都不需要寫。抽象化也能讓程式有彈性。經過適當抽象化的程式，每個概念都有一個獨立的「單位」（可能是變數、函數、類別、模組、或系統）可以表示，每個概念中包含的細節也被隱藏在適當的範圍內，不管要修改或擴充原本的程式都能讓需要碰觸的地方減到最少。 雖然抽象化是讓程式簡潔又有彈性的關鍵，但出乎意料的這是一個容易理解卻很難精通的能力。抽象化做得太少，程式會變得凌亂不堪，不同層級的概念和資訊互相交雜在一起，不僅讓程式變得難讀也難改。抽象化做得太多，就是所謂的over design，明明需求只有印一個Hello World，卻用了10種design patterns蓋起101大樓以應付根本就不會出現的「未來需求」。 抽象化這個主題可以講三天三夜講不完，但今天我只想提其中最簡單也最難的事：「命名」。 命名可以說是寫程式時最簡單但也是最難的事了。這件事沒什麼人會教，沒多少書會寫，因為這件事看起來非常容易，即使你把程式裡的變數照字母順序a, b, c, d, e, &#8230;命名也是行得通，反正對編譯器來說變數或函數的名字不過就是一個沒有意義的符號，不管你取什麼名字最終都只是對應到一個像是0&#215;08048374這個樣子的記憶體位置而已。 簡單來說，一個變數是叫「小狗」或是「小貓」，對電腦來說都沒有區別，但對人來說，差別可大了。 很多初學者以為程式是寫給電腦看的，只要看起來好像能跑出正確結果就好，所以變數位置隨便亂放、名字也隨便亂取、每個變數都是public、甚至一個函數有幾百行，為了在一個畫面中塞下更多程式碼還把IDE的字型縮小到要瞇著眼才看得見。也有很多人覺得高手寫的程式看不懂是正常的，等到自己等級提昇後應該就會看得懂了，但其實事實完全不是這樣。我認識的每個高手和大師寫的程式碼都是乾淨、簡單、易懂，即使是極端複雜的演算法，都能直接從程式碼中看懂作者的想法。 Martin Fowler的 &#8220;Refactoring &#8211; Improving The Design of Existing Code&#8221; 一書中有一句話我很喜歡。 [...]]]></description>
			<content:encoded><![CDATA[<p>追求神乎其技的程式設計之道系列：<br />
<a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/05/%e8%bf%bd%e6%b1%82%e7%a5%9e%e4%b9%8e%e5%85%b6%e6%8a%80%e7%9a%84%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93%e4%b8%80%ef%bc%89/" title="(12967 hits)">一</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/07/%e8%bf%bd%e6%b1%82%e7%a5%9e%e4%b9%8e%e5%85%b6%e6%8a%80%e7%9a%84%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93%e4%ba%8c%ef%bc%89/" title="(5609 hits)">二</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/12/%e8%bf%bd%e6%b1%82%e7%a5%9e%e4%b9%8e%e5%85%b6%e6%8a%80%e7%9a%84%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93%e4%b8%89%ef%bc%89/" title="(7043 hits)">三</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/15/%e8%bf%bd%e6%b1%82%e7%a5%9e%e4%b9%8e%e5%85%b6%e6%8a%80%e7%9a%84%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93%e5%9b%9b%ef%bc%89/" title="(5941 hits)">四</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/25/divine-code-5/" title="(7135 hits)">五</a>  <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/08/19/divine-code-6/" title="(6819 hits)">六</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/10/10/divine-code-7/" title="(6088 hits)">七</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2009/03/11/divine-code-8/" title="(4693 hits)">八</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2009/08/13/divine-code-9/" title="(4348 hits)">九</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2009/12/18/divine-code-10/" title="(4564 hits)">十</a><br />
</p>
<p>休眠已久的神乎其技系列又復活了！這篇文章其實寫很久了，只是一直斷斷續續到今天才完成它，久到讓很多人覺得這系列已經完結了&#8230;。但我想只要我還有在寫程式，這系列就永遠不會結束吧。</p>
<h3>簡潔、彈性、效率</h3>
<p>我一直覺得寫程式是一種藝術活動。程式語言是一種要求極度精確的表達方法，只要少打一個字母就可能造成完全不同的結果，但同時卻又不限制你要如何達到目標。</p>
<p>程式設計師有極大的自由來讓一個程式按照自己的想法「活起來」，不同人針對同樣的目標所寫的程式也一定不同。有人會用極簡主義來把變數命名為a、b、c，也有人會把用匈牙利命名法讓變數前後長出鬍子和尾巴；有人堅守DRY原則(Don&#8217;t repeat yourself)，只要類似的程式出現兩次，就把他們抽象化成一個函數，也有人用copy/paste寫程式，不管怎麼page up或page down都一直看到一樣的東西還能泰然自若；有人寫程式把所有東西都塞在main裡面，也有人寫個Hello world就要搞一個class HelloWorld（雖然有些時候是被囉嗦的J語言強迫的&#8230;）；有人沒聽過Big O也寫程式寫得很開心，但也有人嫌stdlib的qsort太慢硬是要自己重寫一個&#8230;。</p>
<p>儘管每個人的信仰和原則不同，但大體上程式藝術家也不過是在「簡潔」、「彈性」、「效率」這三大目標上進行一連串的取捨(trade-off)和最佳化。</p>
<p>「簡潔」的程式也「易讀」，沒有多餘的敘述或重複的程式碼，每個概念都只有唯一的一段碼在描述它。如果多了，就容易產生不一致的行為，如果少了，就是沒做到該做的事。有「彈性」的程式容易修改和擴充，只要在一個對的地方彈彈手指，不用因為老闆朝三暮四或是需求改變就得把整個程式重新翻修一次。有「效率」的程式會用最適合的資料結構存放每一樣資料，用最快的演算法做每一項必要的計算，並去除任何不必要的間接行為 (indirection)。</p>
<p>雖然目標很明確，但程式設計之所以像藝術就是因為大部分時候我們都沒辦法兼顧這三項目標：為了效率，可能就得犧牲彈性和簡潔；反過來說，為了彈性或簡潔，也常得犧牲效率作為代價。幸運的是，效率的追求在電腦硬體和編譯器技術的進步下已經不像20年前那麼重要，只要選對資料結構和演算法，幾乎已經沒有必要手動做低階的最佳化。除去效率之外，彈性和簡潔其實是比較容易同時達到而又不互相衝突的目標。要達到這目標，其中關鍵的能力就是今天的主題：「抽象化」(abstraction)。</p>
<h3>最簡單但也是最難的事情</h3>
<p>很多人沒聽過抽象化這個詞，甚至以為自己不會這件事，但其實從我們宣告第一個變數起，抽象化就已經開始了。</p>
<p>「這個變數要叫什麼名字？」</p>
<p>幫變數命名時，其實就是在賦予那個變數一個「意義」。人的記憶力有限，很難記住大量且沒有意義的資訊。但如果資訊有了一個固定且有邏輯的名字，我們也就有一個容易記憶的符號來代替整個複雜的概念。換句話說，我們可以把非常複雜的概念濃縮為一個容易處理和記憶的小單位，這個過程就叫做「抽象化」。</p>
<p>抽象化可以讓程式變得簡潔。好的程式設計師會習慣從重複的程式碼中找出共同或相似的部份，並且把這個部分提取出來變成一個更通用的概念。任何複雜的概念都可以被抽取出來替換成一個變數、一個函數、一個類別、一個模式、一個模組、甚至是一個系統，並加上適當的命名，就能讓這個程式「一看就懂」，任何註解都不需要寫。抽象化也能讓程式有彈性。經過適當抽象化的程式，每個概念都有一個獨立的「單位」（可能是變數、函數、類別、模組、或系統）可以表示，每個概念中包含的細節也被隱藏在適當的範圍內，不管要修改或擴充原本的程式都能讓需要碰觸的地方減到最少。</p>
<p>雖然抽象化是讓程式簡潔又有彈性的關鍵，但出乎意料的這是一個容易理解卻很難精通的能力。抽象化做得太少，程式會變得凌亂不堪，不同層級的概念和資訊互相交雜在一起，不僅讓程式變得難讀也難改。抽象化做得太多，就是所謂的over design，明明需求只有印一個Hello World，卻用了10種design patterns蓋起101大樓以應付根本就不會出現的「未來需求」。</p>
<p>抽象化這個主題可以講三天三夜講不完，但今天我只想提其中最簡單也最難的事：「命名」。</p>
<p>命名可以說是寫程式時最簡單但也是最難的事了。這件事沒什麼人會教，沒多少書會寫，因為這件事看起來非常容易，即使你把程式裡的變數照字母順序a, b, c, d, e, &#8230;命名也是行得通，反正對編譯器來說變數或函數的名字不過就是一個沒有意義的符號，不管你取什麼名字最終都只是對應到一個像是0&#215;08048374這個樣子的記憶體位置而已。</p>
<p>簡單來說，一個變數是叫「小狗」或是「小貓」，對電腦來說都沒有區別，但對人來說，差別可大了。</p>
<p>很多初學者以為程式是寫給電腦看的，只要看起來好像能跑出正確結果就好，所以變數位置隨便亂放、名字也隨便亂取、每個變數都是public、甚至一個函數有幾百行，為了在一個畫面中塞下更多程式碼還把IDE的字型縮小到要瞇著眼才看得見。也有很多人覺得高手寫的程式看不懂是正常的，等到自己等級提昇後應該就會看得懂了，但其實事實完全不是這樣。我認識的每個高手和大師寫的程式碼都是乾淨、簡單、易懂，即使是極端複雜的演算法，都能直接從程式碼中看懂作者的想法。</p>
<p>Martin Fowler的 &#8220;Refactoring &#8211; Improving The Design of Existing Code&#8221; 一書中有一句話我很喜歡。</p>
<blockquote><p>
Any fool can write code that a computer can understand. Good programmers write code that humans can understand. （任何一個傻瓜都能寫出計算機可以理解的程式碼。唯有寫出人類容易理解的程式碼， 才是優秀的程式員。)
</p></blockquote>
<p>一段好的程式碼是不需要任何額外註解或說明的。如果名字都取得好，每個變數就能適當的解釋了自己的角色，每個函式都說明了自己的功能，整個程式讀起來就會像在讀說明文件一樣自然。在這種境界下，只要有了基本背景知識的程式員應該都要能輕易地看懂。英文中有個詞叫做explain itself很適合用在這，也就是自己應該要能完美的解釋自己的一切，不需要其他的人或文件來幫忙。</p>
<p>但是，命名是很難的一件事，可以說是寫程式中最接近「藝術」的一部分了。我說的命名，不是要用大小寫混雜的「CamelCase」或是底線分隔的「underscore_separated_style」這種風格問題，而是一個方形到底要叫rectangle或是x的差別。名字取得好，不但自己或其他人未來再回來看這份程式碼時容易進入狀況，對於正在開發中的程式也可以減少很多不必要的bug。</p>
<p>我之前當一門課的助教時，有個作業是要學生實作一個西洋棋遊戲，畫面上要有個棋盤，還有該有的棋子。既然是個棋盤，底層很自然的就會用個二維陣列來表示棋盤的狀態，例如說我們會有</p>
<pre>Chess board[N][N]</pre>
<p>這樣子的一個陣列。接下來，真正的問題來了，程式中勢必會有一些兩層的for迴圈去對這個陣列做操作，如果是你會把這兩個迴圈的index變數取做什麼名字？</p>
<p>最常見也最不用腦的index命名就是i和j，在一般沒有特殊意義的迴圈中用i是沒什麼太大問題的，因為大家都知道這只是一個單純的index。但如果用到j，通常就代表程式可能有些臭味了，至於會用到k、l、m&#8230; 那這個程式一定是徹底腐敗了。</p>
<p>我看了很多學生的程式，我發現很多有bug的程式都是用i、j，或是x、y來命名，而那些寫得很漂亮的程式，幾乎都是用row和column來命名（或是他們的縮寫r和c，或是row和col）。</p>
<p>用i、j的問題在哪？</p>
<p>問題在這兩個名字沒有和棋盤的位置有直接關連，看程式的人沒辦法一眼看出你的i到底是指row還是指column，或是指到宇宙裡的一顆星星。即使是正在寫程式的作者本人，也得一直在心中做i是row、j是column的轉換，但只要精神稍不集中，或是吃個飯休息回來，很輕易就會忘記這些隱晦（implicit）的對應關係。而這種隱晦的對應，就是傷害程式碼可讀性和造成bug的通緝要犯之一。有的人為了避免自己忘記這些細節，就會把這種隱晦的關係或假設寫在程式的註解裡。但話說回來，既然要寫，直接寫在程式碼裡不是更好嗎？</p>
<p>除了用i、j的這群人外，還有另外一群用x、y的程式也是讓人非常頭痛，如果要我比較的話，我會說用xy比用ij還糟糕。為什麼？因為這個程式最終要把棋盤畫在螢幕上，而所有2D繪圖的函式庫都是用x、y來表示螢幕上的位置，如果棋盤用xy，螢幕繪圖也用xy，這樣如何分辨這個xy是棋盤的位置還是螢幕的位置？用xy這群人的解決方法都大同小異，比較懶惰的就是用x1、x2，甚至是x和xx；好一點的會用boardx和screenx，但以index變數來說還是太長太囉嗦了。</p>
<p>與其費這麼大力氣區分兩種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。<br />
（在這個程式中很多用xy的人都把row和column順序搞反，導致初始化的盤面整個轉了90度。）</p>
<p>我以前參加程式比賽時，看過很多經過長期訓練的選手因為比賽的時間壓力而養成不好的習慣，像是把所有程式碼寫在main裡面，變數不是aa就是bb這種沒意義的名字。在程式比賽這種特殊的環境裡，每個程式的目的就是解一個有明確輸出入規定的問題，加上有時間限制，所以選手們都是盡量用最短的code來實作自己的想法。這種情況下寫的程式可以說是用完就丟，只要比賽一結束這個程式的生命也就到了盡頭，所以很多人就不會去思考命名的問題。</p>
<p>到大學的時候，我也常幫同學在作業deadline前夕看他們的程式幫忙debug。很奇妙的是，大學課程的期末專題或是作業應該都有充裕的時間可以慢慢「設計」一個程式，但很多人都是在最後一兩天才開始動手，於是在作業死線的壓力下也沒心情去好好設計一個程式的架構，更別提要好好想每一個變數的命名和位置，也就浪費了許多可以好好練習這個命名藝術的機會。</p>
<p>命名和抽象化是一體兩面的事情。當你能把一個概念用一個適當的名稱來稱呼它時，你才有辦法把這個概念當成一個基石往上建構更複雜的事物。在此同時，人們也才能用這些簡單的名稱來討論複雜的概念或想法。如果你在寫程式時常常沒辦法用很簡單的話跟別人解釋你的程式，通常也代表你的程式是一團漿糊，沒有條理和層次。在這種情況下，你怎麼知道漿糊裡是不是黏了一堆臭蟲呢？反過來說，當你能用簡單清晰的白話跟人解釋你的程式時，你也一定能把程式寫得一樣乾淨漂亮有條理。</p>
<p>如果你現在還在用a, b, c這種變數寫程式，不妨先暫停一下，好好想想每個變數的意義是什麼，你的程式就會自然的變得越來越簡潔和漂亮。</p>
<p>（待續）</p>
<p>2/1 更新：<br />
有朋友提到一篇有趣的相關文章：<a href="http://blog.vgod.tw/go.php?http://ronnywang.pixnet.net/blog/post/19938328" title="(1428 hits)">軟體業的重要職缺 命理大師!</a>。這文章說軟體公司應該有個專門掌管命名的人，才能保持整個project的一致性，並順便算個命看看這些名字吉不吉利。</p>
<p>這讓我想到，其實現有open source程式這麼多，我們可以很容易的寫一個「命理大師」程式出來。只要到幾個project host site，像github、google code之類的地方，把所有project裡的程式碼token抓出來做一些簡單的分析和統計，就可以得到一些有趣的資訊和命名時的參考。例如說，我們可以知道有多少程式裡面用Box表示方形，多少程式用Rectangle，多少程式用deleteXXX，多少用removeXXX，他們之間的區別又在哪。甚至在設計library或API時，連function參數的多寡和排列順序，都可以從此得到參考資訊。更進一步，可以用word net把這些token做clustering，之後我們就可以打一些關鍵字，甚至打中文，讓這個程式建議最多人用的習慣命名法&#8230;。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.vgod.tw/2011/01/31/diving-code-11/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>寫書計畫 &#8211; 追求神乎其技的程式設計之道</title>
		<link>http://blog.vgod.tw/2010/01/09/writing-books/</link>
		<comments>http://blog.vgod.tw/2010/01/09/writing-books/#comments</comments>
		<pubDate>Sat, 09 Jan 2010 01:47:27 +0000</pubDate>
		<dc:creator>vgod</dc:creator>
				<category><![CDATA[追求神乎其技的程式設計之道]]></category>
		<category><![CDATA[Book]]></category>

		<guid isPermaLink="false">http://blog.vgod.tw/?p=823</guid>
		<description><![CDATA[人生中很多事情做起來總是比看起來難，不親身去做永遠也無法體會其中的辛酸。最近有出版社跟我聯絡，想幫我把blog內容整理成書，很湊巧的是我也動過幾次這個念頭，所以也沒想太多就答應了。 目前我的計畫是把「追求神乎其技的程式設計之道」系列文章重新整理，並且把後面還沒寫完的連載繼續完成補在書內。雖然是這麼想，但光是要擬定書籍結構就讓我和編輯們傷透腦筋。之前我在寫神乎其技系列時，把我個人的經歷以及對於程式設計一些相關的想法混合在一起，其實就是很隨興的寫。但說到要成書，事情就沒這麼簡單了。首先第一個問題就是，什麼樣的人會對這本書有興趣？是初學程式的人，還是有點經驗的人，或者是程式高手呢？之前曾經有讀者留言過說看了我的文章後都燃起熱血想動手學習程式設計了，說實在這真是超乎我的預期，但如果可以的話我也很希望有人因為看了我的書而立志成為一個優秀的程式設計師。無奈我雖然寫了很多blog文章，但談到寫書還真是第一次&#8230;。 當個沒經驗的新手，我想就是要厚臉皮一點才能快點進步。所以呢，我決定要來公開徵求讀者們的意見，讓這本書可以變得更好。 你可以簡單告訴我你的背景；告訴我你喜歡或不喜歡我這一系列文章的哪部分，為什麼？也可以告訴我哪邊可以寫得更仔細點，哪些地方想要我多補充一些細節或實例；也可以告訴我你覺得書應該怎樣編排，是要分成一篇篇獨立的散文呢，還是一氣呵成連貫到底？要保持現在這樣讓我的經歷和程式心得交織在一起，或是把他們拆成兩部分呢？ 歡迎大家在本文下面留言，或是透過plurk、twitter，也直接寄信給我(vgod _AT_ vgod.tw)，任何想法都很歡迎。即使是單純推一下，或是覺得我太衝動想要阻止我的也很歡迎XD]]></description>
			<content:encoded><![CDATA[<p>人生中很多事情做起來總是比看起來難，不親身去做永遠也無法體會其中的辛酸。最近有出版社跟我聯絡，想幫我把blog內容整理成書，很湊巧的是我也動過幾次這個念頭，所以也沒想太多就答應了。</p>
<p>目前我的計畫是把<a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/category/divine-code/" title="(3473 hits)">「追求神乎其技的程式設計之道」</a>系列文章重新整理，並且把後面還沒寫完的連載繼續完成補在書內。雖然是這麼想，但光是要擬定書籍結構就讓我和編輯們傷透腦筋。之前我在寫神乎其技系列時，把我個人的經歷以及對於程式設計一些相關的想法混合在一起，其實就是很隨興的寫。但說到要成書，事情就沒這麼簡單了。首先第一個問題就是，什麼樣的人會對這本書有興趣？是初學程式的人，還是有點經驗的人，或者是程式高手呢？之前曾經有讀者留言過說看了我的文章後都燃起熱血想動手學習程式設計了，說實在這真是超乎我的預期，但如果可以的話我也很希望有人因為看了我的書而立志成為一個優秀的程式設計師。無奈我雖然寫了很多blog文章，但談到寫書還真是第一次&#8230;。</p>
<p>當個沒經驗的新手，我想就是要厚臉皮一點才能快點進步。所以呢，我決定要來公開徵求讀者們的意見，讓這本書可以變得更好。</p>
<p>你可以簡單告訴我你的背景；告訴我你喜歡或不喜歡我這一系列文章的哪部分，為什麼？也可以告訴我哪邊可以寫得更仔細點，哪些地方想要我多補充一些細節或實例；也可以告訴我你覺得書應該怎樣編排，是要分成一篇篇獨立的散文呢，還是一氣呵成連貫到底？要保持現在這樣讓我的經歷和程式心得交織在一起，或是把他們拆成兩部分呢？</p>
<p>歡迎大家在本文下面留言，或是透過<a href="http://blog.vgod.tw/go.php?http://www.plurk.com/vgod" title="(3484 hits)">plurk</a>、<a href="http://blog.vgod.tw/go.php?http://twitter.com/vgod" title="(704 hits)">twitter</a>，也直接寄信給我(vgod _AT_ vgod.tw)，任何想法都很歡迎。即使是單純推一下，或是覺得我太衝動想要阻止我的也很歡迎XD</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.vgod.tw/2010/01/09/writing-books/feed/</wfw:commentRss>
		<slash:comments>43</slash:comments>
		</item>
		<item>
		<title>追求神乎其技的程式設計之道（十）</title>
		<link>http://blog.vgod.tw/2009/12/18/divine-code-10/</link>
		<comments>http://blog.vgod.tw/2009/12/18/divine-code-10/#comments</comments>
		<pubDate>Fri, 18 Dec 2009 05:25:57 +0000</pubDate>
		<dc:creator>vgod</dc:creator>
				<category><![CDATA[追求神乎其技的程式設計之道]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.vgod.tw/?p=785</guid>
		<description><![CDATA[追求神乎其技的程式設計之道系列：一 二 三 四 五 六 七 八 九 程式設計師的生產力之謎 很多人都聽說過，同樣是寫程式，一個頂尖程式設計師和一個普通程式設計師之間的生產力可以有十倍甚至百倍的差距。這是其他行業很少見到的現象，於是不禁令人納悶，為什麼會這樣呢？ 其實單就解決同一個問題的coding能力來說，差別還不至於這麼巨大。我在高中參加奧林匹亞和大學參加ACM比賽時，已經遇過全世界數一數二的coding高手，這些人每天都在練習解題和實做各種複雜的演算法和資料結構，隨便說一個演算法都能直接把code透過肌肉記憶反射出來給你。他們能在數十分鐘內想出高效率的演算法並寫成程式解決一個複雜的難題，即使我高中時已經花了一整年在訓練，依然不是他們的對手。這些人除了絕頂聰明外，每個人在高中時少說也寫過至少十萬行的code。但我發現，即使他們能解一般人解不出來的問題，打字快到鍵盤會冒煙，在做一個大系統時，這方面的差距還不一定會如此明顯。 所以我想，除了先天的智商和後天對於寫程式的熟悉度與經驗外，一定還有什麼因素造成巨大的生產力差異。 我後來發現，程式設計師和其他行業有個很大的不同點：一般行業只能在現有的工具上磨練自身的技術，但程式設計師除了磨練技術外，還可以獨自創造、修改自己使用的工具；換句話說，程式設計師的能力就是在電腦上創作出更好的軟體，不但能便利他人，也同時能增進自身使用電腦的工作效率。舉例來說，理髮師能磨練使用剪刀和設計髮型的技術，但理髮師並不知道怎麼發明及製造新的剪刀讓自己更有效率的剪頭髮；電機、化工、土木工程師要設計IC、化學製程、建築結構，但他們得依賴電腦軟體才能設計，並且靠許多大型機器和工具才能生產，即使想提昇自身的工作效率，也不是自己一個人想做就能辦到的。但軟體工程師就不同了，我們只靠一台電腦就能工作，我們的工具是軟體，我們的產出也是軟體，我們的所依賴的一切都是軟體，只要自己願意投入心力，隨時可以修改每天使用的工具和系統讓自己更有效率的工作。 這一點可以說是程式設計師的先天優勢，也是頂尖的程式設計師和普通程式設計師的生產力差距的關鍵。 Eat Our Own Dog Food 我發現厲害的程式設計師常有種共同特質：寫工具給自己用，解決自己日常工作碰到的問題或改善自己的工作效率。英文有句話叫eat one&#8217;s own dog food，字面上意思是說一家公司應該要吃自己做出來的狗食，實際上是引申為一家公司應該要在內部用自己的產品解決自身的問題，才能發現真正的問題，並且說服人這東西真的很實用。Google是奉行「吃狗食」原則的典型公司，Google內部有一個獨立的搜尋引擎搜尋公司內部網路的資料，新技術也都能在上面先行測試；Google內有獨立的gmail、google docs，都在對外公開前先讓內部的人實際用上好一陣子；Google甚至做了自己的Linux distribution給工程師用、自己的compiler、自己的瀏覽器&#8230;。 會這樣做的動機其實很簡單：如果我每天都要花10分鐘手動做同樣的事情無數次，為什麼不花一個小時寫個程式把這件事情自動化，以後可以省下更多時間做點真正有意義的事；如果我每天都要用這個彆腳的軟體，忍受他設計上的不便，為什麼不想法辦改善它或自己做一個呢？ 程式設計師每天都用電腦在工作，尤其做一個系統時常常需要花時間做一些瑣碎的工作，像是編輯設定檔、把一些檔案搬來搬去、重開伺服器、清除暫存檔&#8230;等等。這些工作通常不難，但可能步驟繁雜，或是每個步驟都要等待它慢慢完成，累積起來每天就很容易浪費許多時間手動做這些無趣的事情上。 出於「懶惰」的美德，頂尖的程式設計師工作時想的不只有產出最終產品就好，而是如何花最少力氣最少時間把產品做到最好。但這件事說來容易做來難，能不能實行往往跟程式設計師工作的系統環境有很大關係。 UNIX是Programmer的天堂 如果要說我高中時期最大的收穫是什麼，我想有兩件事的重要程度不相上下：一是我確認了自己對寫程式的熱情，並且花了足夠多時間打好基礎；二是我在這段時間內摸熟了Linux，並且愛上了UNIX世界工作的哲學。 UNIX可以說是一個非常適合程式設計師工作的天堂，UNIX的工作哲學（泛指所有UNIX like的系統，像是Linux、BSD、Mac OS X..等等）是提供許多小工具，每樣小工具只做一件事，使用者可以合併使用多種工具完成複雜的工作。此外，UNIX的工具都是以command line為介面，非常適合寫script做自動化的操作。而在Windows的世界中則完全不同，Windows上的軟體傾向於提供整合式的GUI環境，把所有相關或可能會用到的功能全都一手包下，雖然方便使用者，可以點幾個按鈕就自動做完所有事情，但對於程式設計師來說其實不是一件好事。 以寫程式的工具來說，在UNIX下可以選自己喜歡的文字編輯器，不管是Vim或Emacs，也可以選自己喜歡的compiler，可以用makefile加上command line工具自動化整個程式編譯、測試、執行的流程，並且隨時都可以加入shell script或是perl script把開發流程中瑣碎的工作一併自動處理，不管需求有多麼特別，這種完全自訂的流程彈性可以說是無限大。 但在Windows環境，主流開發軟體以整合開發環境(IDE)為主，像Visual studio這種無所不包的巨獸，對於新手來說按一個鍵就能搞定一切，不用去想底下的細節，實在方便得很。可是依賴於IDE卻有個致命缺點：只要是IDE的設計者一開始沒考慮到的事，你就沒辦法做。 舉例來說，早期visual studio不支援版本控制系統(version control system)時，程式設計師就很難把版本控制整合到開發過程中（例如說在編譯成功時自動commit、或是自動加入新的原始碼&#8230;）；即使到現在visual studio已經支援了一些常見的版本控制系統，用它的人依然要看這個支援的清單包含哪些系統，如果是想用新的系統，或是用非標準的方法使用這些系統，恐怕只能遺憾的兩手一攤什麼事也不能做。有些IDE雖然有提供plugin功能（像是Eclipse），但其實也沒好到哪，因為IDE龐大無比，寫plugin的難度和所需時間遠高於使用者手動完成這些日常瑣事所花的力氣，自然不會有多少人願意去做。 簡單來說，用IDE的話，程式設計師沒辦法掌控自己用的工具，也沒辦法改善開發流程中的問題，開發效率的極限很自然會被IDE限制住。但UNIX上的環境就不一樣了，採用多種工具的組合讓自己能掌控開發流程中每個步驟。因為每個步驟和所用的工具都是透明的，只要有需求或是發現哪裡可以改善，很容易可以從滿手的工具中抓出一個來解決，或是寫個迷你的script來自動處理較複雜的工作。即使哪天有新的小工具出現（例如說一個新的版本控制系統），因為每個小工具都是獨立運作，靠程式設計師自行整合的，所以也比較容易把舊的「零件」替換掉。除此之外，open source興起後，帶有原始碼的系統更帶給程式設計師一個「完全控制」的機會，除了能替換零件外，有能力的人還能直接對零件本身做修改以符合自己的需求。種種因素加起來，讓程式設計師不再被單一個工具能力所限制，而是手中握有無數可以自由運用的籌碼，唯一的限制只有自身的創意和熱情而已。 狗食是生產力的關鍵 我一直覺得念資訊系的人不應該依賴於用IDE寫程式，當然這並不只是因為「用command line才是真男人」這種geeky的理念，而是念資訊系的應該要能擅長於「把電腦能做的事交給電腦做」。今日的軟體介面大多是以多數的日常使用者為目標，雖然方便操作，但設計者不可能把所有使用者可能會想做的工作列表做出各種排列組合放在選單裡。如果是設計者沒考慮到的功能，使用者往往也只能手動慢慢處理。但程式設計師和一般使用者是不同的，程式設計師的能力就是和電腦溝通，讓電腦用我們想要的方式幫我們完成工作。如果我每天要重複按照順序按100個不同的按鈕，為什麼不寫個程式自動按這100個按鈕？ 我跟一些人聊過這個想法，但典型的反應是「正事都做不完了，哪裡有時間先做一個工具？」 但我覺得很諷刺的是，正是因為抱持這種觀念才會讓生產力低落，所以讓正事做不完，時間越緊迫就越不敢花時間做這種沒有立即產出的事情。相反地，如果在意識到自己已經三番兩次手動重複執行同樣的冗長工作時，就應該靜下來好好想想是不是有什麼辦法可以讓電腦來做這些事，只要常有這種想法，寫這些script和小工具所節省下來的時間和自己得到的經驗是一輩子都用得上的。 [...]]]></description>
			<content:encoded><![CDATA[<p>追求神乎其技的程式設計之道系列：<a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/05/%e8%bf%bd%e6%b1%82%e7%a5%9e%e4%b9%8e%e5%85%b6%e6%8a%80%e7%9a%84%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93%e4%b8%80%ef%bc%89/" title="(12967 hits)">一</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/07/%e8%bf%bd%e6%b1%82%e7%a5%9e%e4%b9%8e%e5%85%b6%e6%8a%80%e7%9a%84%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93%e4%ba%8c%ef%bc%89/" title="(5609 hits)">二</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/12/%e8%bf%bd%e6%b1%82%e7%a5%9e%e4%b9%8e%e5%85%b6%e6%8a%80%e7%9a%84%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93%e4%b8%89%ef%bc%89/" title="(7043 hits)">三</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/15/%e8%bf%bd%e6%b1%82%e7%a5%9e%e4%b9%8e%e5%85%b6%e6%8a%80%e7%9a%84%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93%e5%9b%9b%ef%bc%89/" title="(5941 hits)">四</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/25/divine-code-5/" title="(7135 hits)">五</a>  <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/08/19/divine-code-6/" title="(6819 hits)">六</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/10/10/divine-code-7/" title="(6088 hits)">七</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2009/03/11/divine-code-8/" title="(4693 hits)">八</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2009/08/13/divine-code-9/" title="(4348 hits)">九</a><br />
</p>
<h3>程式設計師的生產力之謎</h3>
<p>很多人都聽說過，同樣是寫程式，一個頂尖程式設計師和一個普通程式設計師之間的生產力可以有十倍甚至百倍的差距。這是其他行業很少見到的現象，於是不禁令人納悶，為什麼會這樣呢？</p>
<p>其實單就解決同一個問題的coding能力來說，差別還不至於這麼巨大。我在高中參加奧林匹亞和大學參加ACM比賽時，已經遇過全世界數一數二的coding高手，這些人每天都在練習解題和實做各種複雜的演算法和資料結構，隨便說一個演算法都能直接把code透過肌肉記憶反射出來給你。他們能在數十分鐘內想出高效率的演算法並寫成程式解決一個複雜的難題，即使我高中時已經花了一整年在訓練，依然不是他們的對手。這些人除了絕頂聰明外，每個人在高中時少說也寫過至少十萬行的code。但我發現，即使他們能解一般人解不出來的問題，打字快到鍵盤會冒煙，在做一個大系統時，這方面的差距還不一定會如此明顯。</p>
<p>所以我想，除了先天的智商和後天對於寫程式的熟悉度與經驗外，一定還有什麼因素造成巨大的生產力差異。</p>
<p>我後來發現，程式設計師和其他行業有個很大的不同點：一般行業只能在現有的工具上磨練自身的技術，但程式設計師除了磨練技術外，還可以獨自創造、修改自己使用的工具；換句話說，程式設計師的能力就是在電腦上創作出更好的軟體，不但能便利他人，也同時能增進自身使用電腦的工作效率。舉例來說，理髮師能磨練使用剪刀和設計髮型的技術，但理髮師並不知道怎麼發明及製造新的剪刀讓自己更有效率的剪頭髮；電機、化工、土木工程師要設計IC、化學製程、建築結構，但他們得依賴電腦軟體才能設計，並且靠許多大型機器和工具才能生產，即使想提昇自身的工作效率，也不是自己一個人想做就能辦到的。但軟體工程師就不同了，我們只靠一台電腦就能工作，我們的工具是軟體，我們的產出也是軟體，我們的所依賴的一切都是軟體，只要自己願意投入心力，隨時可以修改每天使用的工具和系統讓自己更有效率的工作。</p>
<p>這一點可以說是程式設計師的先天優勢，也是頂尖的程式設計師和普通程式設計師的生產力差距的關鍵。</p>
<h3>Eat Our Own Dog Food</h3>
<p>我發現厲害的程式設計師常有種共同特質：寫工具給自己用，解決自己日常工作碰到的問題或改善自己的工作效率。英文有句話叫eat one&#8217;s own dog food，字面上意思是說一家公司應該要吃自己做出來的狗食，實際上是引申為一家公司應該要在內部用自己的產品解決自身的問題，才能發現真正的問題，並且說服人這東西真的很實用。Google是奉行「吃狗食」原則的典型公司，Google內部有一個獨立的搜尋引擎搜尋公司內部網路的資料，新技術也都能在上面先行測試；Google內有獨立的gmail、google docs，都在對外公開前先讓內部的人實際用上好一陣子；Google甚至做了自己的Linux distribution給工程師用、自己的compiler、自己的瀏覽器&#8230;。</p>
<p>會這樣做的動機其實很簡單：如果我每天都要花10分鐘手動做同樣的事情無數次，為什麼不花一個小時寫個程式把這件事情自動化，以後可以省下更多時間做點真正有意義的事；如果我每天都要用這個彆腳的軟體，忍受他設計上的不便，為什麼不想法辦改善它或自己做一個呢？</p>
<p>程式設計師每天都用電腦在工作，尤其做一個系統時常常需要花時間做一些瑣碎的工作，像是編輯設定檔、把一些檔案搬來搬去、重開伺服器、清除暫存檔&#8230;等等。這些工作通常不難，但可能步驟繁雜，或是每個步驟都要等待它慢慢完成，累積起來每天就很容易浪費許多時間手動做這些無趣的事情上。</p>
<p>出於「懶惰」的美德，頂尖的程式設計師工作時想的不只有產出最終產品就好，而是如何花最少力氣最少時間把產品做到最好。但這件事說來容易做來難，能不能實行往往跟程式設計師工作的系統環境有很大關係。</p>
<h3>UNIX是Programmer的天堂</h3>
<p>如果要說我高中時期最大的收穫是什麼，我想有兩件事的重要程度不相上下：一是我確認了自己對寫程式的熱情，並且花了足夠多時間打好基礎；二是我在這段時間內摸熟了Linux，並且愛上了UNIX世界工作的哲學。</p>
<p>UNIX可以說是一個非常適合程式設計師工作的天堂，UNIX的工作哲學（泛指所有UNIX like的系統，像是Linux、BSD、Mac OS X..等等）是提供許多小工具，每樣小工具只做一件事，使用者可以合併使用多種工具完成複雜的工作。此外，UNIX的工具都是以command line為介面，非常適合寫script做自動化的操作。而在Windows的世界中則完全不同，Windows上的軟體傾向於提供整合式的GUI環境，把所有相關或可能會用到的功能全都一手包下，雖然方便使用者，可以點幾個按鈕就自動做完所有事情，但對於程式設計師來說其實不是一件好事。</p>
<p>以寫程式的工具來說，在UNIX下可以選自己喜歡的文字編輯器，不管是Vim或Emacs，也可以選自己喜歡的compiler，可以用makefile加上command line工具自動化整個程式編譯、測試、執行的流程，並且隨時都可以加入shell script或是perl script把開發流程中瑣碎的工作一併自動處理，不管需求有多麼特別，這種完全自訂的流程彈性可以說是無限大。</p>
<p>但在Windows環境，主流開發軟體以整合開發環境(IDE)為主，像Visual studio這種無所不包的巨獸，對於新手來說按一個鍵就能搞定一切，不用去想底下的細節，實在方便得很。可是依賴於IDE卻有個致命缺點：只要是IDE的設計者一開始沒考慮到的事，你就沒辦法做。</p>
<p>舉例來說，早期visual studio不支援版本控制系統(version control system)時，程式設計師就很難把版本控制整合到開發過程中（例如說在編譯成功時自動commit、或是自動加入新的原始碼&#8230;）；即使到現在visual studio已經支援了一些常見的版本控制系統，用它的人依然要看這個支援的清單包含哪些系統，如果是想用新的系統，或是用非標準的方法使用這些系統，恐怕只能遺憾的兩手一攤什麼事也不能做。有些IDE雖然有提供plugin功能（像是Eclipse），但其實也沒好到哪，因為IDE龐大無比，寫plugin的難度和所需時間遠高於使用者手動完成這些日常瑣事所花的力氣，自然不會有多少人願意去做。</p>
<p>簡單來說，用IDE的話，程式設計師沒辦法掌控自己用的工具，也沒辦法改善開發流程中的問題，開發效率的極限很自然會被IDE限制住。但UNIX上的環境就不一樣了，採用多種工具的組合讓自己能掌控開發流程中每個步驟。因為每個步驟和所用的工具都是透明的，只要有需求或是發現哪裡可以改善，很容易可以從滿手的工具中抓出一個來解決，或是寫個迷你的script來自動處理較複雜的工作。即使哪天有新的小工具出現（例如說一個新的版本控制系統），因為每個小工具都是獨立運作，靠程式設計師自行整合的，所以也比較容易把舊的「零件」替換掉。除此之外，open source興起後，帶有原始碼的系統更帶給程式設計師一個「完全控制」的機會，除了能替換零件外，有能力的人還能直接對零件本身做修改以符合自己的需求。種種因素加起來，讓程式設計師不再被單一個工具能力所限制，而是手中握有無數可以自由運用的籌碼，唯一的限制只有自身的創意和熱情而已。</p>
<h3>狗食是生產力的關鍵</h3>
<p>我一直覺得念資訊系的人不應該依賴於用IDE寫程式，當然這並不只是因為「用command line才是真男人」這種geeky的理念，而是念資訊系的應該要能擅長於「把電腦能做的事交給電腦做」。今日的軟體介面大多是以多數的日常使用者為目標，雖然方便操作，但設計者不可能把所有使用者可能會想做的工作列表做出各種排列組合放在選單裡。如果是設計者沒考慮到的功能，使用者往往也只能手動慢慢處理。但程式設計師和一般使用者是不同的，程式設計師的能力就是和電腦溝通，讓電腦用我們想要的方式幫我們完成工作。如果我每天要重複按照順序按100個不同的按鈕，為什麼不寫個程式自動按這100個按鈕？</p>
<p>我跟一些人聊過這個想法，但典型的反應是「正事都做不完了，哪裡有時間先做一個工具？」</p>
<p>但我覺得很諷刺的是，正是因為抱持這種觀念才會讓生產力低落，所以讓正事做不完，時間越緊迫就越不敢花時間做這種沒有立即產出的事情。相反地，如果在意識到自己已經三番兩次手動重複執行同樣的冗長工作時，就應該靜下來好好想想是不是有什麼辦法可以讓電腦來做這些事，只要常有這種想法，寫這些script和小工具所節省下來的時間和自己得到的經驗是一輩子都用得上的。</p>
<p>現在有許多open source軟體一開始都只是程式設計師為了方便自己所寫的小工具，在做正事的時候撥出時間先做好工具，然後不知不覺可能就成了偉大的軟體。最有名的例子是Knuth為了寫他的The Art Of Computer Programming，他竟然先重頭自己打造一個針對數學環境設計的排版系統，最後就成了著名的TeX。他不但完成了電腦科學界的聖經，還「順便」完成了一個經典的排版系統並分享給全世界使用。</p>
<p>如果持續抱持著這種態度寫程式，說不定你我也能成為下一個Knuth呢? (笑)</p>
<p>(待續)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.vgod.tw/2009/12/18/divine-code-10/feed/</wfw:commentRss>
		<slash:comments>39</slash:comments>
		</item>
		<item>
		<title>追求神乎其技的程式設計之道（九）</title>
		<link>http://blog.vgod.tw/2009/08/13/divine-code-9/</link>
		<comments>http://blog.vgod.tw/2009/08/13/divine-code-9/#comments</comments>
		<pubDate>Thu, 13 Aug 2009 02:22:49 +0000</pubDate>
		<dc:creator>vgod</dc:creator>
				<category><![CDATA[追求神乎其技的程式設計之道]]></category>
		<category><![CDATA[Life]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.vgod.tw/?p=578</guid>
		<description><![CDATA[追求神乎其技的程式設計之道系列：一 二 三 四 五 六 七 八 最近被很多人提醒這個神乎其技系列停在第八集很久了&#8230;（汗）。其實這集草稿已經存很久了，今天總算決定要把它告一段落後貼出來。 先來個題外話，台灣最近遭受莫拉克颱風帶來的巨大災難之苦，雖然我人不在台灣能幫上的忙很小，但還是希望災區的所有人都能平安度過這次災難。 高中到大學 春天的國際科展結束後，我的高中生活也即將劃下句點。回顧高中三年，從校內的資訊比賽一路走到奧林匹亞的國際舞台，在保送大學資格的保護下，到高三又誤打誤撞變成國際科展的代表。雖然從結果看來一切都是如此美好，但在我剛升上高中時，沒有人知道未來會發生什麼事。我爸媽只想要我好好唸書，考上好大學；而我對學校教的科目早已失去興趣，每天都只想泡在電腦前探索這個神秘盒子的內部。於是每次考試結束，家裡就會因為我的爛成績而引發一次大戰，我爸媽也會一再的限制我坐在電腦前的時間。 就像七龍珠裡的標準情節一樣，悟空總是可以和敵人奮戰到垂死邊緣才爆發出最後一擊取得勝利，我總覺得在逆境時才能看出一個人真正的意志力和求生能力。雖然我爸媽能不斷縮減我能用電腦的時間，但他們可沒辦法限制我在學校做什麼或是面對課本時心裡到底在想些什麼。我還記得高一時，我天天都帶著Introduction To Algorithms（當時還是第一版，很多人叫它白皮書）到學校，不管上課時老師講得多麼口沫橫飛或是下課同學們玩得多開心，我都是看我自己的書。有時碰上管得嚴的老師，我就不看書開始想ACM的題目，用筆在白紙上寫code。我還記得當時為了手邊要隨時有充裕的題目可以想，我把ACM online judge上所有的題目全都印了出來放在一個資料夾裡隨時帶在身邊。 現在想想我那時瘋狂的程度真是難以想像，我當時心思幾乎完全沒放在學校課業上，就連體育課我都躲在樹蔭下想題目的解法。於是到了要升高二選類組時，家裡又爆發了第N次的世界大戰。 還記得升高二前有個考資優班的機會，我爸媽非常想要我去考考看，但我死都不答應。我很堅持的原因是，中一中的數理資優班非常奇怪，進去後就自動變成第三類組，也就是要多念一科生物，但我已經很確定未來我只想念資訊相關的科系，所以我只想選二類，不想浪費時間多念一科生物。就為了這件事，爭執的戰火延伸到我花太多時間在電腦上未來會考不上好學校之類的陳腔濫調上。 台灣父母似乎都想要孩子選擇他們覺得的安全、穩定的路，但我大概天生叛逆了點，說什麼都只想堅持自己的路。不管成功的可能性有多小，或是風險有多大，我覺得我就是應該照著心中的聲音去走。跟他們吵了一陣子後，我決定跟他們立下一個約定：讓我完全自由到高二，如果我沒辦法在資訊比賽拿到夠好的成績足以保送大學，那我到聯考前就都不碰電腦，即使我考不上大學也是我自己的決定所造成的。 從此以後，我就更認真的拼命研究演算法，研究歷年來所有大大小小資訊比賽的題目，只要我醒著的時間，腦袋就全速運轉放在這些東西上。雖然理論上我應該是背水一戰，但那時心裡其實沒有太大壓力，反而覺得可以每天都在玩自己有興趣的東西很幸福很開心，如果比賽結果不好，那可能只是說明我沒有這個天份和這個命而已。 現在回想起來，我覺得當時的我真是不怕死到了極點。要靠資訊比賽保送，至少也要進入奧林匹亞的培訓營，並成為留到第二階段的最後十人之一才有機會（有機會的意思是大學有可能會拒收&#8230;）。簡單的說就是實力大概要在全國高中生的前十名就是了。 我想我當時一定沒有想這麼多，只傻傻的做自己想做的事，所以才會這麼有勇氣立下聯考前都不碰電腦的可怕約定。還好我運氣很好，上了高二後從第一場校內賽就把我累積一年的力量爆發出來，就這樣一路打進培訓營甚至還選上國手。 順利拿到保送資格後，父母鬆了一口氣，於是就完全放任我花更多時間泡在電腦裡了。到高三時，我誤打誤撞說要參加國際科展，於是就有了正當理由請公假，各科老師對我的缺席也見怪不怪。高三我幾乎每天都待在教官室裡玩Linux、架各種系統和server來玩，雖說要做科展，但其實也是對什麼有興趣就玩什麼。（可能很多人覺得奇怪，為什麼會待在教官室&#8230; 因為教官室是少數有電腦有網路，我又能自由進出的地方。再加上當時有教官找我幫忙做網站，所以&#8230;.） 到了要畢業的時候，我才發現我高三幾乎都沒踏進教室過，班上的同學我也幾乎都不認識。雖然在自己的世界裡過得很開心，但要畢業時才發現我的高中生活和其他人都不一樣。班上老師們對我也頗有微詞，所以畢業前我還碰到了一個可怕的畢業危機：我高三的學科被當了九科&#8230;&#8230;。（現在想起來還真難想像，到底有哪九科啊orz&#8230;） 這件事大概是我一帆風順的高中生活中最驚悚的一件事了。雖然台大已經張開手等我進去，但要是高中不能畢業，那我不就變成比櫻木花道還悲慘的笑話了嗎&#8230;。（註：櫻木花道在全國大賽前發現被當太多科無法參賽，所以只好閉關唸書準備補考，當然最後還是順利過關去參賽，不然灌籃高手就畫不下去了。）漫畫中的主角當然不會被要補考這種小事打倒，但現實生活中誰知道呢&#8230; orz 在畢業前遭受到如此巨大的危機，實在完全出乎我的意料之外。還好當時帶我們參加比賽的指導老師非常挺我，幫我跟各科老師要一個補考的機會。學校也很好心不打算找我麻煩，就讓我把考卷帶回家寫一天。隔天交出去後我就沒再得知過關於成績的事，我甚至不知道我畢業時每一科的成績，但總之我還是拿到畢業證書了（汗）。 回想起年輕時的瘋狂，真是覺得很不可思議。如果我當時沒有堅持自己的想法，而依照爸媽的意思「好好唸書」，我想現在的我一定過著完全不同的人生，至少不太可能憑聯考進入台大資訊系，而現在也不會在MIT了..。 (待續)]]></description>
			<content:encoded><![CDATA[<p>追求神乎其技的程式設計之道系列：<a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/05/%e8%bf%bd%e6%b1%82%e7%a5%9e%e4%b9%8e%e5%85%b6%e6%8a%80%e7%9a%84%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93%e4%b8%80%ef%bc%89/" title="(12967 hits)">一</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/07/%e8%bf%bd%e6%b1%82%e7%a5%9e%e4%b9%8e%e5%85%b6%e6%8a%80%e7%9a%84%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93%e4%ba%8c%ef%bc%89/" title="(5609 hits)">二</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/12/%e8%bf%bd%e6%b1%82%e7%a5%9e%e4%b9%8e%e5%85%b6%e6%8a%80%e7%9a%84%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93%e4%b8%89%ef%bc%89/" title="(7043 hits)">三</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/15/%e8%bf%bd%e6%b1%82%e7%a5%9e%e4%b9%8e%e5%85%b6%e6%8a%80%e7%9a%84%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93%e5%9b%9b%ef%bc%89/" title="(5941 hits)">四</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/25/divine-code-5/" title="(7135 hits)">五</a>  <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/08/19/divine-code-6/" title="(6819 hits)">六</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/10/10/divine-code-7/" title="(6088 hits)">七</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2009/03/11/divine-code-8/" title="(4693 hits)">八</a><br />
</p>
<p>最近被很多人提醒這個神乎其技系列停在第八集很久了&#8230;（汗）。其實這集草稿已經存很久了，今天總算決定要把它告一段落後貼出來。</p>
<p>先來個題外話，台灣最近遭受莫拉克颱風帶來的巨大災難之苦，雖然我人不在台灣能幫上的忙很小，但還是希望災區的所有人都能平安度過這次災難。</p>
<h2>高中到大學</h2>
<p>春天的國際科展結束後，我的高中生活也即將劃下句點。回顧高中三年，從校內的資訊比賽一路走到奧林匹亞的國際舞台，在保送大學資格的保護下，到高三又誤打誤撞變成國際科展的代表。雖然從結果看來一切都是如此美好，但在我剛升上高中時，沒有人知道未來會發生什麼事。我爸媽只想要我好好唸書，考上好大學；而我對學校教的科目早已失去興趣，每天都只想泡在電腦前探索這個神秘盒子的內部。於是每次考試結束，家裡就會因為我的爛成績而引發一次大戰，我爸媽也會一再的限制我坐在電腦前的時間。</p>
<p>就像七龍珠裡的標準情節一樣，悟空總是可以和敵人奮戰到垂死邊緣才爆發出最後一擊取得勝利，我總覺得在逆境時才能看出一個人真正的意志力和求生能力。雖然我爸媽能不斷縮減我能用電腦的時間，但他們可沒辦法限制我在學校做什麼或是面對課本時心裡到底在想些什麼。我還記得高一時，我天天都帶著Introduction To Algorithms（當時還是第一版，很多人叫它白皮書）到學校，不管上課時老師講得多麼口沫橫飛或是下課同學們玩得多開心，我都是看我自己的書。有時碰上管得嚴的老師，我就不看書開始想ACM的題目，用筆在白紙上寫code。我還記得當時為了手邊要隨時有充裕的題目可以想，我把ACM online judge上所有的題目全都印了出來放在一個資料夾裡隨時帶在身邊。</p>
<p>現在想想我那時瘋狂的程度真是難以想像，我當時心思幾乎完全沒放在學校課業上，就連體育課我都躲在樹蔭下想題目的解法。於是到了要升高二選類組時，家裡又爆發了第N次的世界大戰。</p>
<p>還記得升高二前有個考資優班的機會，我爸媽非常想要我去考考看，但我死都不答應。我很堅持的原因是，中一中的數理資優班非常奇怪，進去後就自動變成第三類組，也就是要多念一科生物，但我已經很確定未來我只想念資訊相關的科系，所以我只想選二類，不想浪費時間多念一科生物。就為了這件事，爭執的戰火延伸到我花太多時間在電腦上未來會考不上好學校之類的陳腔濫調上。</p>
<p>台灣父母似乎都想要孩子選擇他們覺得的安全、穩定的路，但我大概天生叛逆了點，說什麼都只想堅持自己的路。不管成功的可能性有多小，或是風險有多大，我覺得我就是應該照著心中的聲音去走。跟他們吵了一陣子後，我決定跟他們立下一個約定：讓我完全自由到高二，如果我沒辦法在資訊比賽拿到夠好的成績足以保送大學，那我到聯考前就都不碰電腦，即使我考不上大學也是我自己的決定所造成的。</p>
<p>從此以後，我就更認真的拼命研究演算法，研究歷年來所有大大小小資訊比賽的題目，只要我醒著的時間，腦袋就全速運轉放在這些東西上。雖然理論上我應該是背水一戰，但那時心裡其實沒有太大壓力，反而覺得可以每天都在玩自己有興趣的東西很幸福很開心，如果比賽結果不好，那可能只是說明我沒有這個天份和這個命而已。</p>
<p>現在回想起來，我覺得當時的我真是不怕死到了極點。要靠資訊比賽保送，至少也要進入奧林匹亞的培訓營，並成為留到第二階段的最後十人之一才有機會（有機會的意思是大學有可能會拒收&#8230;）。簡單的說就是實力大概要在全國高中生的前十名就是了。</p>
<p>我想我當時一定沒有想這麼多，只傻傻的做自己想做的事，所以才會這麼有勇氣立下聯考前都不碰電腦的可怕約定。還好我運氣很好，上了高二後從第一場校內賽就把我累積一年的力量爆發出來，就這樣一路打進培訓營甚至還選上國手。</p>
<p>順利拿到保送資格後，父母鬆了一口氣，於是就完全放任我花更多時間泡在電腦裡了。到高三時，我誤打誤撞說要參加國際科展，於是就有了正當理由請公假，各科老師對我的缺席也見怪不怪。高三我幾乎每天都待在教官室裡玩Linux、架各種系統和server來玩，雖說要做科展，但其實也是對什麼有興趣就玩什麼。（可能很多人覺得奇怪，為什麼會待在教官室&#8230; 因為教官室是少數有電腦有網路，我又能自由進出的地方。再加上當時有教官找我幫忙做網站，所以&#8230;.）</p>
<p>到了要畢業的時候，我才發現我高三幾乎都沒踏進教室過，班上的同學我也幾乎都不認識。雖然在自己的世界裡過得很開心，但要畢業時才發現我的高中生活和其他人都不一樣。班上老師們對我也頗有微詞，所以畢業前我還碰到了一個可怕的畢業危機：我高三的學科被當了九科&#8230;&#8230;。（現在想起來還真難想像，到底有哪九科啊orz&#8230;）</p>
<p>這件事大概是我一帆風順的高中生活中最驚悚的一件事了。雖然台大已經張開手等我進去，但要是高中不能畢業，那我不就變成比櫻木花道還悲慘的笑話了嗎&#8230;。（註：櫻木花道在全國大賽前發現被當太多科無法參賽，所以只好閉關唸書準備補考，當然最後還是順利過關去參賽，不然灌籃高手就畫不下去了。）漫畫中的主角當然不會被要補考這種小事打倒，但現實生活中誰知道呢&#8230; orz</p>
<p>在畢業前遭受到如此巨大的危機，實在完全出乎我的意料之外。還好當時帶我們參加比賽的指導老師非常挺我，幫我跟各科老師要一個補考的機會。學校也很好心不打算找我麻煩，就讓我把考卷帶回家寫一天。隔天交出去後我就沒再得知過關於成績的事，我甚至不知道我畢業時每一科的成績，但總之我還是拿到畢業證書了（汗）。</p>
<p>回想起年輕時的瘋狂，真是覺得很不可思議。如果我當時沒有堅持自己的想法，而依照爸媽的意思「好好唸書」，我想現在的我一定過著完全不同的人生，至少不太可能憑聯考進入台大資訊系，而現在也不會在MIT了..。</p>
<p><a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2009/12/18/divine-code-10/" title="(4564 hits)">(待續)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.vgod.tw/2009/08/13/divine-code-9/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>追求神乎其技的程式設計之道(八）</title>
		<link>http://blog.vgod.tw/2009/03/11/divine-code-8/</link>
		<comments>http://blog.vgod.tw/2009/03/11/divine-code-8/#comments</comments>
		<pubDate>Wed, 11 Mar 2009 03:38:09 +0000</pubDate>
		<dc:creator>vgod</dc:creator>
				<category><![CDATA[追求神乎其技的程式設計之道]]></category>
		<category><![CDATA[Life]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.vgod.tw/?p=515</guid>
		<description><![CDATA[追求神乎其技的程式設計之道系列：一 二 三 四 五 六 七 第八集終於寫完了&#8230;。雖然我寒假過得很輕鬆悠閒，但不知道為什麼人就是會在很閒的時候不做平常一直說沒空做的事，然後硬是要在很多作業和工作時開始寫blog&#8230;.。雖然開學後又開始變忙了，但我到目前還是每個禮拜都跑去滑雪，這樣看來這一系列最後突然會變成追求神乎其技的滑雪之道也說不一定XD 前言夠多了，本集將繼續我在高三時朦朧無知的學習故事&#8230;。 Intel ISEF國際科展 在第五集裡提到我一直以來都夢想著讓電腦學會自己寫程式。就在我把這個想法的雛型用基因演算法實做出來後，沒想到竟然真的看到了一點結果，電腦真的能透過基因演算法來產生出一個能夠正確運作的程式！ 在高三時，已經取得保送資格的我對學校的課業時在沒什麼興趣，於是我想閒著也是閒著，乾脆就把這個點子拿去參加科展看看，這樣一來我就又有理由可以請公假了（笑）。當時似乎是因為已經來不及報名全國科展了，所以我就跑去報名了國際科展，但那時我其實完全不知道這兩種科展有什麼差別。後來查了一下才知道，原來台灣的國際科展除了是一種比賽外，主要的目的其實是要選出代表去參加其他國家（如美國、法國、加拿大&#8230;）的科展活動；而一般的全國科展就是一個區域至全國性的展覽兼比賽，在全國選出前幾名後就結束了。 2001年時，那時科教館還在建中對面，那也是我第一次踏進科教館的大門。在展場內把自己的海報貼上看板後，我就到處逛逛欣賞別人的作品。因為資訊科在高中不是正式科目，參加的人比起其他科來說少了許多，但其中還是有些非常驚人的作品出現。當時有個建中的學弟Eric，他寫了一個用類神經網路辨識並動態追蹤影像中人眼位置的程式，於是他就用了個普通的攝影機加上這程式，就變成可以用眼睛控制滑鼠游標的神奇裝置。 除了Eric的作品外，其他的作品看起來大多只是某種現有產品或課本上習題的複製品，並沒有什麼令人特別印象深刻的東西出現。說起來這其實也不奇怪，因為在高中階段要自己學好一個程式語言其實並不容易，在基礎還未打穩前，即使有再多創意也無法發揮出來。而很可惜的是，很多人上了大學終於學會寫程式後，創意和熱情也被磨損的差不多了；而畢業後雖然已經有了基本功力，但卻只能照著老闆開的規格刻畫死板的功能與介面，與其說是程式設計師不如說是程式工匠。 我覺得台灣人的能力並不差，但社會中卻瀰漫著一股抄襲與仿冒的氣息，從最近的酪梨壽司事件(相關抄襲事件還可參考MMDays的整理)，可以看出抄襲風氣在台灣並不只是小時候在學校抄抄作業而已；媒體工作者在報導中任意抄襲及轉載是種不尊重自己專業的表現，不但隱含著一種應付了事的心態，更代表著這些人對於自己的工作沒有熱情，更沒有著一點堅持。如果要說我在美國看到這邊和台灣有什麼最大的不同，我想關鍵的差異就在對自己的工作有沒有熱情和堅持而已了。 在評審的過程中，有兩個教授一起來聽我介紹我的作品。因為我沒有任何參加科展的經驗，也沒做什麼講稿或準備就去了，一切只能靠臨場發揮，還好教授們還蠻喜歡我的作品，一來一往的討論之下才讓我不至於太緊張而說不出話來。 自己的介紹結束後，終於鬆了一口氣，教授們對我的作品似乎感到非常新奇和有興趣，後來還問了我「如果再給你兩個月，你能做出更好的結果嗎？」這問題聽起來像是要給我個機會再繼續深入研究下去，難道是意味著要選我當代表嗎？當時我對於得獎其實是沒什麼興趣和期望的，只是想看看別人對這個東西的意見，但如果有人喜歡當然是很棒的事情。這問題無非是給我挑戰的機會，我腦中還有很多改進的想法，如果有更多時間，一定還能做出更棒的結果。所以，我就毫不猶豫的就回答了：「可以，當然可以！」 到了頒獎典禮時，司儀一一宣佈每個學科的獲獎人以及之後要代表台灣去哪個國家參展，同時也頒發一些企業贊助的特別獎。我原本一直以為Eric的作品應該是穩拿第一的，畢竟相較之下我的作品並不夠成熟和完整，甚至連個能稱上科學實驗後的結果都沒有。但這個新奇的點子威力還是很大，我完全沒預料到無心插柳參加科展竟然讓我拿到了Intel頒發的電腦科學最佳獎，並且還選上了美國代表，之後可以代表台灣去美國參加Intel主辦的國際科學暨工程展(ISEF, International Science and Engineering Fair)。 程式設計之內功心法 得獎當然很開心，這是對於我這個想法和努力的肯定，但隨之而來的也是一股很大的壓力。我得代表台灣站出去，到美國跟來自世界各地的教授、學者、參展代表用英文介紹我的作品，那不能像在台灣這樣輕輕鬆鬆跟教授聊聊天就好，我要用不熟悉的語言跟不熟悉的外國人介紹我這個只花一兩個月做出來的雛型作品&#8230; 光想到這個背都涼了。 選上科展代表跟選上奧林匹亞國手是完全不同的感覺。奧林匹亞對我來說是個已經努力很久的目標，我很清楚自己的實力有多少，我對自己花了將近一年所打下的基礎很有信心，而且我對比賽本身已經非常了解，出國比賽不過就是做我已經很擅長的事情而已，一點都不需要害怕和擔心；但選上科展代表真的完全是意料之外的事情，我自覺還沒有花足夠的功夫在這問題上研究，就像一個腳底有油漆還到處亂跑的小鬼，糊里糊塗的鬼畫符被長輩當成畢卡索的作品一樣。 驚恐之餘，我還是警覺到我得開始做很多事來讓我能充滿信心出國去參展。我得趕快把英文練好，至少要能流利的跟人介紹作品，還要能回答各種問題；我還得了解Intel ISEF到底在幹麼，參展代表要做些什麼事；最重要的是還得繼續在這個作品上做更多研究，看能不能在兩個月內做出更好的結果。 參加科展讓我意外領悟到一些事，我發現我高一開始花了一年多投入資訊比賽所得到的並不只是那塊獎牌與一堆獎狀，在練習的過程中，我把台中圖書館所能借到的演算法和資料結構的書全都看過了，就連冼鏡光當初在微電腦傳真雜誌上的專欄也被我從圖書館地下室的陳年庫藏中挖出來，一本一本的影印裝訂起來。我收集了我所能找到的所有大大小小資訊比賽歷年來的題目，加上當時ACM Online Judge上做過的四百多題，我當時參加比賽幾乎都是看完題目馬上就能想完所有可行的演算法和所搭配的資料結構，並用直覺挑出能最快寫出來且又最有效率的解法。除了解決問題的方法外，我也能輕易的把任何想法寫成程式碼，只要能把過程講出來，就能毫不猶豫寫出code來。 這個花了一年多練出來的功夫，讓我到今天都受用無窮。這種感覺就像唸完九陽真經後內力大幅提昇，之後不管再練什麼武功都是易如反掌。在高中時，我改以Linux作為我主要的工作環境，同時也幫中一中架起BBS，並自己架了web server、mail server來玩玩。這些系統底層的功夫乍看之下跟寫程式沒什麼關係，但我後來發現要做各種能在現實生活中應用的軟體系統，總是會碰到這些現有系統的細節問題。 我以前在大學時常觀察別人的project會碰到什麼阻礙，而開發不順利的原因幾乎都是被一些瑣碎的細節所絆住而導致嚴重的進度落後。這些細節都是些小事，甚至跟寫程式沒有直接相關，但總是會讓人陷於泥沼之中。舉一個簡單的例子，假設要在Linux上寫程式需要用到某個library，動手前得先安裝一下。這個看似簡單的安裝其實牽扯到許多瑣碎的細節，像是：distro有沒有提供package可以直接透過網路安裝? 沒有的話就要自己編譯，那就得知道如何用configure、make等工具；編譯中可能還會發生缺少其他相依的工具或package的情形，這時還要能從錯誤訊息中看出到底少了什麼東西，並且想辦法先安裝起來&#8230;。這些事情跟寫程式的理念其實一點關係都沒有，但很殘酷的是，有許多人都會被這種細節所絆倒而中途放棄。 紮實的內功和熟悉系統底層的基本武功帶給我非常有效率的實做能力，我可以在想出新的idea的同時馬上勾勒出實做上大大小小的細節；我可以很快設計出核心的高效率演算法，也知道系統各部份的功能有什麼現有的library或系統可以利用，這兩種能力讓我能快速完成prototype。我只怕沒有夠好的點子，完全不會擔心是不是真的能做得出來。 不久前有位數字先生開了一個程式速成班，號稱能在4堂課內教會web程式的開發，只要帶著點子過去就能在上完課後開始創業。我覺得學寫程式本身其實不用很久，我也曾教過一個12歲的小朋友寫程式，兩個禮拜總共約十小時就足夠讓他掌握基本的程式邏輯概念，包括變數、迴圈、if、陣列、抽象化..。但認真說起來這些東西只是基礎內功，有了內功後自己還是要花很多時間去學相關的底層武功，像是要做web程式還得摸熟web server的架設和管理、UINX的shell和系統管理、各種相關網路傳輸協定、資料庫的使用和管理、前端的HTML和CSS設計&#8230;.。光web程式所牽扯到的實做細節就多如牛毛，如果要在完全沒有穩固基礎的情況下同時學這麼多東西，只要一旦出現問題，一個對系統從上到下每個環節都不熟悉的人是完全沒辦法鎖定問題發生點的。而debug的基本概念就是要先鎖定問題發生的地方，要做到這件事的先決條件就是要很有信心的先排除一些不可能的地方，再做些假設並驗證假設是否成立來判斷可能問題。如果對每個環節都沒有充分的經驗，我不覺得這樣的人有能力清楚的定位出問題所在，更別提是否能獨力完成一個像樣的完整系統。 每個人都聽過成功是一分的天才加上九十九分的努力，如果說天才是能想出絕妙idea的能力，那我覺得還有個關鍵是，要在有點子前先做過夠多的努力打好基礎，等到靈光一現時才能把握住機會馬上實現它。如果等到一分的天才出現時，才準備開始做九十九分的努力，那很容易就會被許多基礎能力不足所帶來的挫折感和障礙所壓垮。 (待續)]]></description>
			<content:encoded><![CDATA[<p>追求神乎其技的程式設計之道系列：<a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/05/%e8%bf%bd%e6%b1%82%e7%a5%9e%e4%b9%8e%e5%85%b6%e6%8a%80%e7%9a%84%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93%e4%b8%80%ef%bc%89/" title="(12967 hits)">一</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/07/%e8%bf%bd%e6%b1%82%e7%a5%9e%e4%b9%8e%e5%85%b6%e6%8a%80%e7%9a%84%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93%e4%ba%8c%ef%bc%89/" title="(5609 hits)">二</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/12/%e8%bf%bd%e6%b1%82%e7%a5%9e%e4%b9%8e%e5%85%b6%e6%8a%80%e7%9a%84%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93%e4%b8%89%ef%bc%89/" title="(7043 hits)">三</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/15/%e8%bf%bd%e6%b1%82%e7%a5%9e%e4%b9%8e%e5%85%b6%e6%8a%80%e7%9a%84%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93%e5%9b%9b%ef%bc%89/" title="(5941 hits)">四</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/25/divine-code-5/" title="(7135 hits)">五</a>  <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/08/19/divine-code-6/" title="(6819 hits)">六</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/10/10/divine-code-7/" title="(6088 hits)">七</a><br />
</p>
<p>第八集終於寫完了&#8230;。雖然我寒假過得很輕鬆悠閒，但不知道為什麼人就是會在很閒的時候不做平常一直說沒空做的事，然後硬是要在很多作業和工作時開始寫blog&#8230;.。雖然開學後又開始變忙了，但我到目前還是每個禮拜都跑去滑雪，這樣看來這一系列最後突然會變成追求神乎其技的滑雪之道也說不一定XD</p>
<p>前言夠多了，本集將繼續我在高三時朦朧無知的學習故事&#8230;。</p>
<h3>Intel ISEF國際科展</h3>
<p>在<a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/25/divine-code-5/" title="(7135 hits)">第五集</a>裡提到我一直以來都夢想著讓電腦學會自己寫程式。就在我把這個想法的雛型用基因演算法實做出來後，沒想到竟然真的看到了一點結果，電腦真的能透過基因演算法來產生出一個能夠正確運作的程式！</p>
<p>在高三時，已經取得保送資格的我對學校的課業時在沒什麼興趣，於是我想閒著也是閒著，乾脆就把這個點子拿去參加科展看看，這樣一來我就又有理由可以請公假了（笑）。當時似乎是因為已經來不及報名全國科展了，所以我就跑去報名了國際科展，但那時我其實完全不知道這兩種科展有什麼差別。後來查了一下才知道，原來台灣的國際科展除了是一種比賽外，主要的目的其實是要選出代表去參加其他國家（如美國、法國、加拿大&#8230;）的科展活動；而一般的全國科展就是一個區域至全國性的展覽兼比賽，在全國選出前幾名後就結束了。</p>
<p>2001年時，那時科教館還在建中對面，那也是我第一次踏進科教館的大門。在展場內把自己的海報貼上看板後，我就到處逛逛欣賞別人的作品。因為資訊科在高中不是正式科目，參加的人比起其他科來說少了許多，但其中還是有些非常驚人的作品出現。當時有個建中的學弟Eric，他寫了一個用類神經網路辨識並動態追蹤影像中人眼位置的程式，於是他就用了個普通的攝影機加上這程式，就變成可以用眼睛控制滑鼠游標的神奇裝置。</p>
<p>除了Eric的作品外，其他的作品看起來大多只是某種現有產品或課本上習題的複製品，並沒有什麼令人特別印象深刻的東西出現。說起來這其實也不奇怪，因為在高中階段要自己學好一個程式語言其實並不容易，在基礎還未打穩前，即使有再多創意也無法發揮出來。而很可惜的是，很多人上了大學終於學會寫程式後，創意和熱情也被磨損的差不多了；而畢業後雖然已經有了基本功力，但卻只能照著老闆開的規格刻畫死板的功能與介面，與其說是程式設計師不如說是程式工匠。</p>
<p>我覺得台灣人的能力並不差，但社會中卻瀰漫著一股抄襲與仿冒的氣息，從最近的<a href="http://blog.vgod.tw/go.php?http://www.cwyuni.tw/blog/post/23336465" title="(2188 hits)">酪梨壽司事件</a>(相關抄襲事件還可參考<a href="http://blog.vgod.tw/go.php?http://mmdays.com/2009/03/08/taiwan_copycat_media/" title="(1853 hits)">MMDays的整理</a>)，可以看出抄襲風氣在台灣並不只是小時候在學校抄抄作業而已；媒體工作者在報導中任意抄襲及轉載是種不尊重自己專業的表現，不但隱含著一種應付了事的心態，更代表著這些人對於自己的工作沒有熱情，更沒有著一點堅持。如果要說我在美國看到這邊和台灣有什麼最大的不同，我想關鍵的差異就在對自己的工作有沒有熱情和堅持而已了。</p>
<p>在評審的過程中，有兩個教授一起來聽我介紹我的作品。因為我沒有任何參加科展的經驗，也沒做什麼講稿或準備就去了，一切只能靠臨場發揮，還好教授們還蠻喜歡我的作品，一來一往的討論之下才讓我不至於太緊張而說不出話來。</p>
<p>自己的介紹結束後，終於鬆了一口氣，教授們對我的作品似乎感到非常新奇和有興趣，後來還問了我「如果再給你兩個月，你能做出更好的結果嗎？」這問題聽起來像是要給我個機會再繼續深入研究下去，難道是意味著要選我當代表嗎？當時我對於得獎其實是沒什麼興趣和期望的，只是想看看別人對這個東西的意見，但如果有人喜歡當然是很棒的事情。這問題無非是給我挑戰的機會，我腦中還有很多改進的想法，如果有更多時間，一定還能做出更棒的結果。所以，我就毫不猶豫的就回答了：「可以，當然可以！」</p>
<p>到了頒獎典禮時，司儀一一宣佈每個學科的獲獎人以及之後要代表台灣去哪個國家參展，同時也頒發一些企業贊助的特別獎。我原本一直以為Eric的作品應該是穩拿第一的，畢竟相較之下我的作品並不夠成熟和完整，甚至連個能稱上科學實驗後的結果都沒有。但這個新奇的點子威力還是很大，我完全沒預料到無心插柳參加科展竟然讓我拿到了Intel頒發的電腦科學最佳獎，並且還選上了美國代表，之後可以代表台灣去美國參加Intel主辦的國際科學暨工程展(ISEF, International Science and Engineering Fair)。</p>
<h3>程式設計之內功心法</h3>
<p>得獎當然很開心，這是對於我這個想法和努力的肯定，但隨之而來的也是一股很大的壓力。我得代表台灣站出去，到美國跟來自世界各地的教授、學者、參展代表用英文介紹我的作品，那不能像在台灣這樣輕輕鬆鬆跟教授聊聊天就好，我要用不熟悉的語言跟不熟悉的外國人介紹我這個只花一兩個月做出來的雛型作品&#8230; 光想到這個背都涼了。</p>
<p>選上科展代表跟選上奧林匹亞國手是完全不同的感覺。奧林匹亞對我來說是個已經努力很久的目標，我很清楚自己的實力有多少，我對自己花了將近一年所打下的基礎很有信心，而且我對比賽本身已經非常了解，出國比賽不過就是做我已經很擅長的事情而已，一點都不需要害怕和擔心；但選上科展代表真的完全是意料之外的事情，我自覺還沒有花足夠的功夫在這問題上研究，就像一個腳底有油漆還到處亂跑的小鬼，糊里糊塗的鬼畫符被長輩當成畢卡索的作品一樣。</p>
<p>驚恐之餘，我還是警覺到我得開始做很多事來讓我能充滿信心出國去參展。我得趕快把英文練好，至少要能流利的跟人介紹作品，還要能回答各種問題；我還得了解Intel ISEF到底在幹麼，參展代表要做些什麼事；最重要的是還得繼續在這個作品上做更多研究，看能不能在兩個月內做出更好的結果。</p>
<p>參加科展讓我意外領悟到一些事，我發現我高一開始花了一年多投入資訊比賽所得到的並不只是那塊獎牌與一堆獎狀，在練習的過程中，我把台中圖書館所能借到的演算法和資料結構的書全都看過了，就連冼鏡光當初在微電腦傳真雜誌上的專欄也被我從圖書館地下室的陳年庫藏中挖出來，一本一本的影印裝訂起來。我收集了我所能找到的所有大大小小資訊比賽歷年來的題目，加上當時ACM Online Judge上做過的四百多題，我當時參加比賽幾乎都是看完題目馬上就能想完所有可行的演算法和所搭配的資料結構，並用直覺挑出能最快寫出來且又最有效率的解法。除了解決問題的方法外，我也能輕易的把任何想法寫成程式碼，只要能把過程講出來，就能毫不猶豫寫出code來。</p>
<p>這個花了一年多練出來的功夫，讓我到今天都受用無窮。這種感覺就像唸完九陽真經後內力大幅提昇，之後不管再練什麼武功都是易如反掌。在高中時，我改以Linux作為我主要的工作環境，同時也幫中一中架起BBS，並自己架了web server、mail server來玩玩。這些系統底層的功夫乍看之下跟寫程式沒什麼關係，但我後來發現要做各種能在現實生活中應用的軟體系統，總是會碰到這些現有系統的細節問題。</p>
<p>我以前在大學時常觀察別人的project會碰到什麼阻礙，而開發不順利的原因幾乎都是被一些瑣碎的細節所絆住而導致嚴重的進度落後。這些細節都是些小事，甚至跟寫程式沒有直接相關，但總是會讓人陷於泥沼之中。舉一個簡單的例子，假設要在Linux上寫程式需要用到某個library，動手前得先安裝一下。這個看似簡單的安裝其實牽扯到許多瑣碎的細節，像是：distro有沒有提供package可以直接透過網路安裝? 沒有的話就要自己編譯，那就得知道如何用configure、make等工具；編譯中可能還會發生缺少其他相依的工具或package的情形，這時還要能從錯誤訊息中看出到底少了什麼東西，並且想辦法先安裝起來&#8230;。這些事情跟寫程式的理念其實一點關係都沒有，但很殘酷的是，有許多人都會被這種細節所絆倒而中途放棄。</p>
<p>紮實的內功和熟悉系統底層的基本武功帶給我非常有效率的實做能力，我可以在想出新的idea的同時馬上勾勒出實做上大大小小的細節；我可以很快設計出核心的高效率演算法，也知道系統各部份的功能有什麼現有的library或系統可以利用，這兩種能力讓我能快速完成prototype。我只怕沒有夠好的點子，完全不會擔心是不是真的能做得出來。</p>
<p>不久前有位數字先生開了一個程式速成班，號稱能在4堂課內教會web程式的開發，只要帶著點子過去就能在上完課後開始創業。我覺得學寫程式本身其實不用很久，我也曾教過一個12歲的小朋友寫程式，兩個禮拜總共約十小時就足夠讓他掌握基本的程式邏輯概念，包括變數、迴圈、if、陣列、抽象化..。但認真說起來這些東西只是基礎內功，有了內功後自己還是要花很多時間去學相關的底層武功，像是要做web程式還得摸熟web server的架設和管理、UINX的shell和系統管理、各種相關網路傳輸協定、資料庫的使用和管理、前端的HTML和CSS設計&#8230;.。光web程式所牽扯到的實做細節就多如牛毛，如果要在完全沒有穩固基礎的情況下同時學這麼多東西，只要一旦出現問題，一個對系統從上到下每個環節都不熟悉的人是完全沒辦法鎖定問題發生點的。而debug的基本概念就是要先鎖定問題發生的地方，要做到這件事的先決條件就是要很有信心的先排除一些不可能的地方，再做些假設並驗證假設是否成立來判斷可能問題。如果對每個環節都沒有充分的經驗，我不覺得這樣的人有能力清楚的定位出問題所在，更別提是否能獨力完成一個像樣的完整系統。</p>
<p>每個人都聽過成功是一分的天才加上九十九分的努力，如果說天才是能想出絕妙idea的能力，那我覺得還有個關鍵是，要在有點子前先做過夠多的努力打好基礎，等到靈光一現時才能把握住機會馬上實現它。如果等到一分的天才出現時，才準備開始做九十九分的努力，那很容易就會被許多基礎能力不足所帶來的挫折感和障礙所壓垮。</p>
<p><a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2009/08/13/divine-code-9/" title="(4348 hits)">(待續)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.vgod.tw/2009/03/11/divine-code-8/feed/</wfw:commentRss>
		<slash:comments>30</slash:comments>
		</item>
		<item>
		<title>追求神乎其技的程式設計之道(七）</title>
		<link>http://blog.vgod.tw/2008/10/10/divine-code-7/</link>
		<comments>http://blog.vgod.tw/2008/10/10/divine-code-7/#comments</comments>
		<pubDate>Fri, 10 Oct 2008 04:56:08 +0000</pubDate>
		<dc:creator>vgod</dc:creator>
				<category><![CDATA[追求神乎其技的程式設計之道]]></category>
		<category><![CDATA[Life]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.vgod.tw/?p=480</guid>
		<description><![CDATA[追求神乎其技的程式設計之道系列：一 二 三 四 五 六 這次拖稿了很久，雖然下禮拜就要期中考了，但我決定還是要趁這個作業都剛交出去的忙碌低峰期來補上一篇，不然真不知道下一篇要等到什麼時候了&#8230;（泣） 思考的高度 上一篇談到了優秀程式設計師的第一要件：「熱情」，這一篇我想要談我覺得熱情之外最重要的能力：「思考」，特別是抽象化的思考能力。 寫程式可以說是一件進入門檻很低的工作，拜現代的GUI開發工具以及大量的open source library所賜，很多低階、跟硬體和作業系統直接相關的細節都被隱藏起來了，所以說其實只要學會某種程式語言並且會把自己的想法鉅細靡遺的轉換為程式碼，就可以說自己會寫程式了。到達這個階段並不困難，只要有心學習的話即使是國中生自己看看書或到巨X電腦上上課都能學會。那麼究竟要如何跨過這個階段，讓自己能和巨X電腦的畢業生有所區隔呢？我認為關鍵就在思考的高度。 寫程式需要的思考能力第一是邏輯思考，主要其實就是用正確、清晰的邏輯表達想法而已，說來簡單但要做好也是需要一定時間的訓練。第二是抽象化思考，這是許多人忽略掉的一點，也是我覺得區隔一個平凡與偉大程式設計師的重要特質。 我覺得所有的程式都可以看成一個巨大的金字塔，頂端是這個程式的最終目標，一個模糊的概念；底部是細節的程式碼。而中間是一個經由不斷切割與抽象化所構成的高塔，每一個程式都是切割為許多的元件、模組，再切為更細的class和function，再來是最底下的變數與邏輯判斷式。 很有趣的是，不同的人看這個塔就會有不同的樣子。初學者看到的塔只有兩層，他們和人溝通的方法是鉅細靡遺的描述程式碼：「我在這裡寫個for，第一次把i設成0，在迴圈內每次檢查這個陣列的第i個元素&#8230;」，在他們眼中只有程式的目標和程式碼本身，所以還可能會寫出下面這種讓人哭笑不得的註解： &#160; &#160;a = 1; &#160;// 把a設為1 有些經驗後，會再多看到一層，利用function把一段程式碼包裝起來，賦予一個名字和獨特的意義。學會這個後，就可以利用抽象化後的function名稱來溝通，例如：「我在這個迴圈裡每次都用isCaptial來檢查這個字串是不是都是大寫&#8230;」再接下去呢，可以再利用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，但這裡就不要這麼講究了）寫起來大概是這樣： &#160; PhoneData contacts&#91;N&#93; = &#123;&#8230;..&#125;; String number&#91;MAX_NUMBERS&#93;; int count = 0; &#160; for&#40;int i = [...]]]></description>
			<content:encoded><![CDATA[<p>追求神乎其技的程式設計之道系列：<a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/05/%e8%bf%bd%e6%b1%82%e7%a5%9e%e4%b9%8e%e5%85%b6%e6%8a%80%e7%9a%84%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93%e4%b8%80%ef%bc%89/" title="(12967 hits)">一</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/07/%e8%bf%bd%e6%b1%82%e7%a5%9e%e4%b9%8e%e5%85%b6%e6%8a%80%e7%9a%84%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93%e4%ba%8c%ef%bc%89/" title="(5609 hits)">二</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/12/%e8%bf%bd%e6%b1%82%e7%a5%9e%e4%b9%8e%e5%85%b6%e6%8a%80%e7%9a%84%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93%e4%b8%89%ef%bc%89/" title="(7043 hits)">三</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/15/%e8%bf%bd%e6%b1%82%e7%a5%9e%e4%b9%8e%e5%85%b6%e6%8a%80%e7%9a%84%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93%e5%9b%9b%ef%bc%89/" title="(5941 hits)">四</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/25/divine-code-5/" title="(7135 hits)">五</a>  <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/08/19/divine-code-6/" title="(6819 hits)">六</a><br />
</p>
<p>這次拖稿了很久，雖然下禮拜就要期中考了，但我決定還是要趁這個作業都剛交出去的忙碌低峰期來補上一篇，不然真不知道下一篇要等到什麼時候了&#8230;（泣）</p>
<h3>思考的高度</h3>
<p>上一篇談到了優秀程式設計師的第一要件：「熱情」，這一篇我想要談我覺得熱情之外最重要的能力：「思考」，特別是抽象化的思考能力。</p>
<p>寫程式可以說是一件進入門檻很低的工作，拜現代的GUI開發工具以及大量的open source library所賜，很多低階、跟硬體和作業系統直接相關的細節都被隱藏起來了，所以說其實只要學會某種程式語言並且會把自己的想法鉅細靡遺的轉換為程式碼，就可以說自己會寫程式了。到達這個階段並不困難，只要有心學習的話即使是國中生自己看看書或到巨X電腦上上課都能學會。那麼究竟要如何跨過這個階段，讓自己能和巨X電腦的畢業生有所區隔呢？我認為關鍵就在思考的高度。</p>
<p>寫程式需要的思考能力第一是邏輯思考，主要其實就是用正確、清晰的邏輯表達想法而已，說來簡單但要做好也是需要一定時間的訓練。第二是抽象化思考，這是許多人忽略掉的一點，也是我覺得區隔一個平凡與偉大程式設計師的重要特質。</p>
<p>我覺得所有的程式都可以看成一個巨大的金字塔，頂端是這個程式的最終目標，一個模糊的概念；底部是細節的程式碼。而中間是一個經由不斷切割與抽象化所構成的高塔，每一個程式都是切割為許多的元件、模組，再切為更細的class和function，再來是最底下的變數與邏輯判斷式。</p>
<p>很有趣的是，不同的人看這個塔就會有不同的樣子。初學者看到的塔只有兩層，他們和人溝通的方法是鉅細靡遺的描述程式碼：「我在這裡寫個for，第一次把i設成0，在迴圈內每次檢查這個陣列的第i個元素&#8230;」，在他們眼中只有程式的目標和程式碼本身，所以還可能會寫出下面這種讓人哭笑不得的註解：</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;a = <span class="nu0">1</span>; &nbsp;<span class="co1">// 把a設為1</span></div>
</li>
</ol>
</div>
<p>有些經驗後，會再多看到一層，利用function把一段程式碼包裝起來，賦予一個名字和獨特的意義。學會這個後，就可以利用抽象化後的function名稱來溝通，例如：「我在這個迴圈裡每次都用isCaptial來檢查這個字串是不是都是大寫&#8230;」再接下去呢，可以再利用class，利用design patterns，利用更大的模組、子系統來溝通，認真說起來，這其實是一個無止境的切割。</p>
<p>在資訊科學這個領域，抽象化是個無窮無盡的必要行為。因為世間萬物實在太多太複雜，我們只好不斷把東西歸類，並賦予一個名稱、一個意義，經由這樣的過程我們才能用抽象的語言和符號來溝通，避免每次都要從最底層的瑣碎細節開始說起。而平凡和偉大的程式設計師，我覺得他們之間的差別就在於能看到多少這個高塔中間的分層。厲害的高手都很善於切換自己思考的高度，一下能跟你討論高階的系統架構設計，一下又能深入到最底下的組合語言和二進位除錯。他們腦中除了有這高塔每一層的詳盡平面圖，甚至也非常了解不同樓層之間的交互關係。而平凡的程式設計師大多只能專注於自己所開發的範圍，對於其上的架構或其下的細節都不一定能理清頭緒，萬一出現bug也會搞不清楚到底是哪一層出了錯，而被完全無關的細節絆住手腳。</p>
<h3>程式語言決定了思考的高度</h3>
<p>大部分資訊系學生接觸的第一個語言是C語言，其實我覺得到了21世紀還從C語言開始教是非常值得商議的一件事。我在台大時曾當過兩次計算機概論的助教，雖然大一學生同時還在修計算機程式設計（也就是教C語言的課），但我在課上也同時教他們學Python。</p>
<p>有人問我：「只學C語言不夠嗎？」。如果是為了畢業後能找工作，其實學C就夠了，因為幾乎所有公司都只考基本的C語言能力，也就是說他們認定只要會寫C就能勝任日後的工作。事實上大部分大學都不太教程式語言的，會教C也只是因為大一總得選一個語言教，而C還是老得辣，加上大部分教授也只會這個，所以自然就決定是它了。近年來因為物件導向風行，所以大部分學校還會教個Java或C++，但這也是因為要教物件導向的概念，而不是以教這個語言為目的。除了這兩種外，大概就剩下組合語言了，而這也是因為要教電腦最核心的CPU運作方式，所以才會順便教到的。</p>
<p>程式語言的地位在資訊系其實一直很卑微，大部分教授覺得這只是一個基本工具，就像螺絲起子和鐵鎚一樣。但我一直覺得程式語言是很重要的工具，它不只是讓人用不同語法和電腦溝通，而是讓人能用完全不同的思考方式來解決問題。簡單的說，我覺得程式語言就是決定思考高度的一個關鍵因素，而這也間接決定了寫程式的能力。</p>
<p>舉一個簡單的例子，高階的script語言幾乎都內建map這個資料結構。(也就是一對一的對應表，給它一個key，就能很快的找到其對應的value。有的語言稱為dictionary、hash、或associative array。）如果寫習慣Python或Ruby的人，一定會很直覺的用map來儲存任何對應關係，甚至用來表示會動態變更欄位的struct。但是，在C語言裡沒有這種東西，這讓很多只會寫C的人直覺的用陣列加上linear search來存放這種對應關係。如果資料結構學得好的人，會知道這樣寫效率很差，但很多時候因為沒有方便的library，也懶得自己寫一個高效率的map（不過是存一個電話簿，我難道要先寫一個紅黑樹嗎？），就妥協於沒效率的儲存方法。</p>
<p>這就是一個被程式語言限制住的典型例子。在高階語言用map存東西實在太容易了，所以這會變成思考時的一個小單位，跟人溝通或是規劃架構時都能隨時拿來用。但相反地，在低階語言裡，要有效率又簡單的儲存這種對應關係實在很麻煩，所以人們在思考時會傾向選擇容易的方法來做，而自然忽略掉了以map為基礎的解決方法。</p>
<p>除了script language外，functional language也是另一個進化到神乎其技路上必備的技能。functional language是以function為基礎來思考的程式語言，典型的代表是LISP、Scheme、Haskell。（這邊所說的function是higher order function，可以以其他function為參數的function，和C語言裡的function是不同的概念。）在functional的世界最棒的特性是程式可以只靠function間的相互組合而生成，不用迴圈不用if一樣可以達成同樣的目的。</p>
<p>舉例來說，如果我要要從一個電話簿中挑出所有姓張的人，並傳回他們的電話，用低階語言（其實我指的是imperative language，但這裡就不要這麼講究了）寫起來大概是這樣：</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">PhoneData contacts<span class="br0">&#91;</span>N<span class="br0">&#93;</span> = <span class="br0">&#123;</span>&#8230;..<span class="br0">&#125;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw4">String</span> number<span class="br0">&#91;</span>MAX_NUMBERS<span class="br0">&#93;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw4">int</span> count = <span class="nu0">0</span>; &nbsp;</div>
</li>
<li class="li2">
<div class="de2"><span class="kw1">for</span><span class="br0">&#40;</span><span class="kw4">int</span> i = <span class="nu0">0</span>; i &lt; N; i++<span class="br0">&#41;</span><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">if</span><span class="br0">&#40;</span> !strncmp<span class="br0">&#40;</span> contacts<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.<span class="me1">name</span>, <span class="st0">&quot;張&quot;</span>, <span class="nu0">1</span> <span class="br0">&#41;</span> <span class="br0">&#41;</span> <span class="co1">// well, 讓我們假設這個strncmp支援unicode</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; ret<span class="br0">&#91;</span>count++<span class="br0">&#93;</span> = contacts<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.<span class="me1">number</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">return</span> ret;</div>
</li>
</ol>
</div>
<p>用低階語言寫程式必須不斷處理瑣碎的細節，像是要開多大的陣列、要弄一個額外的counting變數、要用迴圈一個個檢查陣列&#8230;.。當腦袋裡充滿這些細節時，是很難切換到更高的角度思考的。而functional language提供完全不同的思考方式來解決同樣的問題，以下我用Ruby的語法寫同樣的程式(Ruby具備許多functional language的特性，但不全然是個functional language）：</p>
</pre>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">contacts = <span class="br0">&#91;</span> <span class="br0">&#123;</span> <span class="st0">'name'</span> =&gt; <span class="st0">'...'</span>, <span class="st0">'number'</span> =&gt; <span class="st0">'...'</span> <span class="br0">&#125;</span>, ... <span class="br0">&#93;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">return</span> contacts.<span class="me1">find_all</span><span class="br0">&#123;</span> |c| c<span class="br0">&#91;</span><span class="st0">'name'</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="nu0">0</span>,<span class="nu0">1</span><span class="br0">&#93;</span> == <span class="st0">'張'</span> <span class="br0">&#125;</span>.<span class="me1">map</span><span class="br0">&#123;</span> |c| c<span class="br0">&#91;</span><span class="st0">'number'</span><span class="br0">&#93;</span><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>是的，你沒看錯，就只有兩行，而且真正做事的只有一行而已。這裡用到的是functional language的基本工具：filter(Ruby裡叫find_all）和map。這兩個function特別的地方在於他們能用來取代一般需要迴圈才能做的事，並賦予除了「迴圈」以外更高階的抽象意義。filter的意思是過濾，可以從一個陣列中用一個給定的function為條件來去除不合條件的元素；而map的意義是對應和轉換，可以用一個給定的function作為規則把一個陣列中的每個元素全轉換成另一個樣子。</p>
<p>多了這一層抽象化後，寫程式的思考方式會變得完全不同。迴圈不再只是迴圈，而是可以根據它的目的將之區分為map或filter（其實還有更多，這邊只是先舉兩個做例子），思考時便能以組合這些小元件的方式來構思程式的寫法。這裡提供的不只是語法上的簡便而已，而是整個思維的大躍進，以及思考高度的提昇。</p>
<p>這就是為什麼我要教大一新生Python。Python融合imperative language、object-oriented language、以及functional language，語法簡單清楚威力又強大。雖然他們學過後不見得會繼續用Python，但有了不同語言的概念後，思考的高度會完全不同，寫出來的程式品質自然也不同。</p>
<p>(待續)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.vgod.tw/2008/10/10/divine-code-7/feed/</wfw:commentRss>
		<slash:comments>34</slash:comments>
		</item>
		<item>
		<title>追求神乎其技的程式設計之道(六）</title>
		<link>http://blog.vgod.tw/2008/08/19/divine-code-6/</link>
		<comments>http://blog.vgod.tw/2008/08/19/divine-code-6/#comments</comments>
		<pubDate>Tue, 19 Aug 2008 15:54:31 +0000</pubDate>
		<dc:creator>vgod</dc:creator>
				<category><![CDATA[追求神乎其技的程式設計之道]]></category>
		<category><![CDATA[Life]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.vgod.tw/?p=439</guid>
		<description><![CDATA[追求神乎其技的程式設計之道系列：一 二 三 四 五 最近新玩具太多，差點讓我的blog被N82系列文章淹沒了。幸虧即時看到qing兄兩篇不錯的文章 程式設計的兩個觀點 (1/2)和程式設計的兩個觀點 (2/2)，讓我決定還是來早點把這個系列寫完，不然就快變富奸了。 qing兄的兩篇文章指出程式員的兩種型態，一是重視演算法、資料結構、執行效率的「效率魔人」，二是重視程式架構、擴充性、彈性、可理解性的「架構狂」。這兩種人其實都很好，要完成一個偉大的軟體，團隊中兩種人一定都要有。比較糟糕的是，有很多「第三型態人」，他們的信念只有一條：「程式只要會動就好」。第三型態人不在乎效率，也不管架構漂不漂亮，上面要求他做什麼，他就想辦法東湊西湊，從Google找程式剪貼，從MSDN抓範例來用，反正只要能隨便測過一個case就能交差了。 其實第三型態人也不一定是不懂演算法、不懂design patterns，他們常常只是因為火燒屁股了，就不管三七二十一先弄出可以動的程式再說，效率或架構等到下一階段再來改就好&#8230;。問題是，下一階段又有新的功能要做，這些人再度面臨抉擇時還是會決定先讓程式「會動再說」。我看過很多各式各樣的程式員，只要碰到這種人，同樣的過程是履試不爽不斷出現。 所以要成為一個優秀的程式設計師的關鍵是什麼？關鍵不在於coding速度有多快、懂多少演算法，或是背了多少patterns，最重要的是「熱情」！ 偉大的程式設計師都非常喜歡寫程式，寫程式的過程是一種絕妙的享受，他們執著的地方或許不同，可能是程式的效率，也可能是開發的效率，甚至是架構的彈性或是程式碼的精簡美觀程度，但他們都非常想要並堅持自己應該寫出「好程式」。熱情能驅動他們把軟體的某一個面向雕琢到極致，這需要超乎常人的毅力和堅持，以及絕不向壓力妥協的精神。只要具備這種熱情，不管你在乎的是什麼，都可以成為一名偉大的程式設計大師。 P.S. 雖然這篇文章講的東西很八股，但我發現這真的非常重要，看一個人的熱情就能知道他做出來的成品是什麼樣子。如果是我來面試，我一定會在面試時觀察這人有沒有喜歡寫程式的熱情，沒有熱情的人容易向現實壓力低頭，也不會要有不斷精益求精的信念，在如此競爭的時代是很難生存的。 P.S.2 要追求神乎其技前，當然要先知道自己的目標是什麼樣子，所以我本來想在這篇寫一個優秀的程式設計師應該要有的特質和能力，但才寫了第一項就落落長。所以還是等待下一篇再繼續這個主題好了。（路人：「這不就是擺明要當富奸嗎！」） (待續)]]></description>
			<content:encoded><![CDATA[<p>追求神乎其技的程式設計之道系列：<a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/05/%e8%bf%bd%e6%b1%82%e7%a5%9e%e4%b9%8e%e5%85%b6%e6%8a%80%e7%9a%84%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93%e4%b8%80%ef%bc%89/" title="(12967 hits)">一</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/07/%e8%bf%bd%e6%b1%82%e7%a5%9e%e4%b9%8e%e5%85%b6%e6%8a%80%e7%9a%84%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93%e4%ba%8c%ef%bc%89/" title="(5609 hits)">二</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/12/%e8%bf%bd%e6%b1%82%e7%a5%9e%e4%b9%8e%e5%85%b6%e6%8a%80%e7%9a%84%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93%e4%b8%89%ef%bc%89/" title="(7043 hits)">三</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/15/%e8%bf%bd%e6%b1%82%e7%a5%9e%e4%b9%8e%e5%85%b6%e6%8a%80%e7%9a%84%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93%e5%9b%9b%ef%bc%89/" title="(5941 hits)">四</a> <a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/07/25/divine-code-5/" title="(7135 hits)">五</a><br />
</p>
<p>最近新玩具太多，差點讓我的blog被N82系列文章淹沒了。幸虧即時看到qing兄兩篇不錯的文章 <a href="http://blog.vgod.tw/go.php?http://www.javaworld.com.tw/roller/qing/entry/%E7%A8%8B%E5%BC%8F%E8%A8%AD%E8%A8%88%E7%9A%84%E5%85%A9%E5%80%8B%E8%A7%80%E9%BB%9E_1_2" title="(4545 hits)">程式設計的兩個觀點 (1/2)</a>和<a href="http://blog.vgod.tw/go.php?http://www.javaworld.com.tw/roller/qing/entry/%E7%A8%8B%E5%BC%8F%E8%A8%AD%E8%A8%88%E7%9A%84%E5%85%A9%E5%80%8B%E8%A7%80%E9%BB%9E_2_2" title="(3300 hits)">程式設計的兩個觀點 (2/2)</a>，讓我決定還是來早點把這個系列寫完，不然就快變<a href="http://blog.vgod.tw/go.php?http://uncyclopedia.tw/wiki/%E5%AF%8C%E5%A5%B8" title="(1812 hits)">富奸</a>了。</p>
<p>qing兄的兩篇文章指出程式員的兩種型態，一是重視演算法、資料結構、執行效率的「效率魔人」，二是重視程式架構、擴充性、彈性、可理解性的「架構狂」。這兩種人其實都很好，要完成一個偉大的軟體，團隊中兩種人一定都要有。比較糟糕的是，有很多「第三型態人」，他們的信念只有一條：「程式只要會動就好」。第三型態人不在乎效率，也不管架構漂不漂亮，上面要求他做什麼，他就想辦法東湊西湊，從Google找程式剪貼，從MSDN抓範例來用，反正只要能隨便測過一個case就能交差了。</p>
<p>其實第三型態人也不一定是不懂演算法、不懂design patterns，他們常常只是因為火燒屁股了，就不管三七二十一先弄出可以動的程式再說，效率或架構等到下一階段再來改就好&#8230;。問題是，下一階段又有新的功能要做，這些人再度面臨抉擇時還是會決定先讓程式「會動再說」。我看過很多各式各樣的程式員，只要碰到這種人，同樣的過程是履試不爽不斷出現。</p>
<p>所以要成為一個優秀的程式設計師的關鍵是什麼？關鍵不在於coding速度有多快、懂多少演算法，或是背了多少patterns，最重要的是「熱情」！</p>
<p>偉大的程式設計師都非常喜歡寫程式，寫程式的過程是一種絕妙的享受，他們執著的地方或許不同，可能是程式的效率，也可能是開發的效率，甚至是架構的彈性或是程式碼的精簡美觀程度，但他們都非常想要並堅持自己應該寫出「好程式」。熱情能驅動他們把軟體的某一個面向雕琢到極致，這需要超乎常人的毅力和堅持，以及絕不向壓力妥協的精神。只要具備這種熱情，不管你在乎的是什麼，都可以成為一名偉大的程式設計大師。</p>
<p>
P.S. 雖然這篇文章講的東西很八股，但我發現這真的非常重要，看一個人的熱情就能知道他做出來的成品是什麼樣子。如果是我來面試，我一定會在面試時觀察這人有沒有喜歡寫程式的熱情，沒有熱情的人容易向現實壓力低頭，也不會要有不斷精益求精的信念，在如此競爭的時代是很難生存的。
</p>
<p>
P.S.2 要追求神乎其技前，當然要先知道自己的目標是什麼樣子，所以我本來想在這篇寫一個優秀的程式設計師應該要有的特質和能力，但才寫了第一項就落落長。所以還是等待下一篇再繼續這個主題好了。（路人：「這不就是擺明要當富奸嗎！」）
</p>
<p><a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/10/10/divine-code-7/" title="(6088 hits)">(待續)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.vgod.tw/2008/08/19/divine-code-6/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>追求神乎其技的程式設計之道(五）</title>
		<link>http://blog.vgod.tw/2008/07/25/divine-code-5/</link>
		<comments>http://blog.vgod.tw/2008/07/25/divine-code-5/#comments</comments>
		<pubDate>Thu, 24 Jul 2008 17:44:16 +0000</pubDate>
		<dc:creator>vgod</dc:creator>
				<category><![CDATA[追求神乎其技的程式設計之道]]></category>
		<category><![CDATA[Life]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.vgod.tw/?p=375</guid>
		<description><![CDATA[讓電腦自己寫程式的夢 在高三突然對於讓電腦自己寫程式產生興趣後，我每天就都想著這件事，夢想著未來某一天的電腦能跟我一起寫程式，當我把程式目的說給它聽時，它就一邊把細部的程式碼產生出來：我不用想如何命名變數，或是要用什麼演算法，還是我到底要不要把這個功能變成獨立的class&#8230;；我只要動動嘴巴：「我想寫一個橫向捲軸的射擊遊戲。玩家操縱著會變形的飛機，還有四種武器。第一關要長這樣這樣&#8230;&#8230;」，然後電腦就幫我把遊戲寫出來了！如果真的可以這樣，那該有多好啊！（如果真的成真，恐怕我也要失業了？）[註一] 這個想法實在太讓人興奮了，雖然說這是一個遙遠的夢想（其實那時候我並沒有覺得這麼遙遠，只能說自己太不自量力XD），但也開啟我對於人工智慧、程式語言結構、軟體工程等領域的高度興趣。 寫程式很難？ 在高中時代頗不知天高地厚的我，一邊嘗試著利用基因演算法(Genetic Algorithms)讓電腦自己產生程式碼，一邊研究各種程式語言的結構和特性。靠直覺摸索出利用tree作為中介來描述一個程式後（那時沒唸過compiler，不知道這個其實就是Abstract Syntax Tree)，我突然就對這個想法的可行性信心大增，所以一時衝動就去報名了國際科展，打算把這個想法實做出來。 真的做了以後才發現，最難的部份不是產生出程式碼。如果你把程式語言的基本元素，像是if、for、變數、運算符號等東西做成一塊塊磁體，然後拿給一隻猴子玩，那麼牠其實也能拼出一堆程式給你，問題是：「你要怎麼知道這些程式碼真的達到了你想要的目的？」 悟出這個道理後，我突然了解寫程式最難的部份是在驗證程式碼真的跟你所想表達的事情完全相同。（所以說我對於各家軟體公司的QA地位都低於RD其實感到很不平） 基本上，我們只能設計大量的可能輸入值丟進程式裡，並比對程式跑出來的結果和我們想要的輸出相不相同。即使在這種情況下，我們也只能說這個程式在測試過的這些輸入值上所產生的結果是正確的。也就是說，除非我們測試過所有可能的輸入（這意味著無限多種可能），不然永遠沒辦法知道某個程式是對還是錯。除此之外，即使只測試一個輸入值，也還有個很嚴重的問題：「我們怎麼知道這個程式要跑多久？」換句話說，當你程式跑下去，你怎麼知道他是掉入一個無窮迴圈，還是其實正在拼命計算當中？ 我在參加國際科展時，認識了歐陽明教授，他告訴我這個問題叫做Halting problem，Alan Turing在70年前就證明了這是一個無解的問題。知道這件事後，才發現自己所知實在太少，對於資訊科學的基本知識實在非常不足，但這次經驗其實也給了我一個明確的方向，讓我把書中的理論和實際的目標連結在一起。 見樹又見林的學習之道 提到書本中的理論，有很多人問過我要怎麼學習寫程式或資訊相關的知識，我順便在這邊分享些心得給大家參考。 常看到許多人抱怨大學裡學的東西都是理論，畢業後找工作時才發現什麼都不會都得重學；當然企業也會抱怨，大學應該多教一些實務課程，不然出社會後還得重新訓練。說來說去，一致的口徑指向理論和實務是打死也扯不上關係的樣子，尤其念資工的人更常這麼說：「學校為什麼不教C#？為什麼不教我做網頁？好歹也要教個HTML嘛！」 我覺得學習任何事物，一定要有充分的興趣才會有效率，在不知道所學為何的情況下被逼著學習是非常痛苦且沒有效率的。最近看了一本書：沒有資優班，珍視每個孩子的芬蘭教育，書中提到芬蘭教育成功的秘密在於「見樹又見林」，這句話也是我對於如何學習最想分享的秘訣。 台灣的教育方法是「先見樹，再見林」，也就是先教你細部的方法和技術，等你都學會之後（或是硬背起來之後），出社會後就會知道為什麼要學這些東西。（很多人小時候都聽過「等你長大就知道唸書有多重要」吧。可是現在比較多人畢業後反而說「我不知道之前念那麼多書有什麼用」）在這種體制之下，許多人在還沒見到整片森林的美景前就被一棵棵大樹搞得暈頭轉向，痛苦萬分，在不知道「學了這個可以做什麼」的情況下，不管學什麼都會覺得沒有意義沒有動力。 而「見樹又見林」的學習方式，是先找到能引起自己興趣的目標，讓自己有個理由去認真學習，之後再往細部的技術和理論去學習。我從小就很想自己寫遊戲，為了達成這個目標，我就四處尋找相關的資料，慢慢的我就知道自己應該要學好一個快速的低階語言（像是C++），如果要寫繪圖引擎可能還得學一點圖學的理論和技術，如果要做網路連線還得學網路相關的技術&#8230;。 這裡有個重點是，不要看過森林後就忘記它，而又迷失在幾棵樹幹上，要讓自己一直重複見樹又見林的過程。 這跟如何有效開發軟體的秘訣是一樣的。一個有效率的軟體開發方式是用iterative process，把包含設計、實做、測試的iteration時間縮短，但要一直不斷重複這個iteration無數次來改進現有的成果。同理，在已經有目標的狀況下學習時，每當學會一些新東西，就要馬上試著把它實現出來，即使是只有幾行程式碼的prototype也沒關係。只要一直不斷的學，這個prototype就會一直被改進，一直加進最新學到的知識和技術而更接近最終的目標。 同時動腦也動手(註二)，用這種角度來學習就能充分了解自己學會的東西可以用在什麼地方，馬上得到回饋的成就感還會刺激自己繼續向前進，形成一個非常有效率的學習循環。用這種角度看學校教的東西，就能知道書本上的理論可以用在哪，並且又欠缺哪些實務知識讓自己無法做出想要的東西。 這方法理論上可以擴展到任何事物的學習，重點在找到有興趣的目標和書本裡知識的連結，我覺得這是老師應該要出力的地方，無奈的是台灣的教育體制把中小學老師們變成出考題和改考卷的機器人&#8230;.。 註一: 其實，現在真的有這樣的研究，而且驚人的是目前已經有了非常接近我想像中未來的雛型。最讓我興奮的是MIT Media Lab的Hugo Liu和Henry Lieberman做的Metafor：只要對電腦用英文描述你要的程式，電腦就自動把Python code生出來給你&#8230;.。 註二: 話說，MIT的校徽上就是一個拿著鎚子的工匠和一個拿著書的學者，所代表的意義就是 &#8220;Mind and Hand&#8221;，也就是期望每個學生都能手腦並用，除了做夢外也要實做出來才算數啊。 (待續)]]></description>
			<content:encoded><![CDATA[<h3>讓電腦自己寫程式的夢</h3>
<p>在高三突然對於讓電腦自己寫程式產生興趣後，我每天就都想著這件事，夢想著未來某一天的電腦能跟我一起寫程式，當我把程式目的說給它聽時，它就一邊把細部的程式碼產生出來：我不用想如何命名變數，或是要用什麼演算法，還是我到底要不要把這個功能變成獨立的class&#8230;；我只要動動嘴巴：「我想寫一個橫向捲軸的射擊遊戲。玩家操縱著會變形的飛機，還有四種武器。第一關要長這樣這樣&#8230;&#8230;」，然後電腦就幫我把遊戲寫出來了！如果真的可以這樣，那該有多好啊！（如果真的成真，恐怕我也要失業了？）[註一]</p>
<p>這個想法實在太讓人興奮了，雖然說這是一個遙遠的夢想（其實那時候我並沒有覺得這麼遙遠，只能說自己太不自量力XD），但也開啟我對於人工智慧、程式語言結構、軟體工程等領域的高度興趣。</p>
<h3>寫程式很難？</h3>
<p>在高中時代頗不知天高地厚的我，一邊嘗試著利用基因演算法(Genetic Algorithms)讓電腦自己產生程式碼，一邊研究各種程式語言的結構和特性。靠直覺摸索出利用tree作為中介來描述一個程式後（那時沒唸過compiler，不知道這個其實就是Abstract Syntax Tree)，我突然就對這個想法的可行性信心大增，所以一時衝動就去報名了國際科展，打算把這個想法實做出來。</p>
<p>真的做了以後才發現，最難的部份不是產生出程式碼。如果你把程式語言的基本元素，像是if、for、變數、運算符號等東西做成一塊塊磁體，然後拿給一隻猴子玩，那麼牠其實也能拼出一堆程式給你，問題是：「你要怎麼知道這些程式碼真的達到了你想要的目的？」</p>
<p>悟出這個道理後，我突然了解寫程式最難的部份是在驗證程式碼真的跟你所想表達的事情完全相同。（所以說我對於各家軟體公司的QA地位都低於RD其實感到很不平）</p>
<p>基本上，我們只能設計大量的可能輸入值丟進程式裡，並比對程式跑出來的結果和我們想要的輸出相不相同。即使在這種情況下，我們也只能說這個程式在測試過的這些輸入值上所產生的結果是正確的。也就是說，除非我們測試過所有可能的輸入（這意味著無限多種可能），不然永遠沒辦法知道某個程式是對還是錯。除此之外，即使只測試一個輸入值，也還有個很嚴重的問題：「我們怎麼知道這個程式要跑多久？」換句話說，當你程式跑下去，你怎麼知道他是掉入一個無窮迴圈，還是其實正在拼命計算當中？</p>
<p>我在參加國際科展時，認識了<a href="http://blog.vgod.tw/go.php?http://www.cmlab.csie.ntu.edu.tw/~ming/" title="(1364 hits)">歐陽明教授</a>，他告訴我這個問題叫做<a href="http://blog.vgod.tw/go.php?http://en.wikipedia.org/wiki/Halting_problem" title="(955 hits)">Halting problem</a>，Alan Turing在70年前就證明了這是一個無解的問題。知道這件事後，才發現自己所知實在太少，對於資訊科學的基本知識實在非常不足，但這次經驗其實也給了我一個明確的方向，讓我把書中的理論和實際的目標連結在一起。</p>
<h3>見樹又見林的學習之道</h3>
<p>提到書本中的理論，有很多人問過我要怎麼學習寫程式或資訊相關的知識，我順便在這邊分享些心得給大家參考。</p>
<p>常看到許多人抱怨大學裡學的東西都是理論，畢業後找工作時才發現什麼都不會都得重學；當然企業也會抱怨，大學應該多教一些實務課程，不然出社會後還得重新訓練。說來說去，一致的口徑指向理論和實務是打死也扯不上關係的樣子，尤其念資工的人更常這麼說：「學校為什麼不教C#？為什麼不教我做網頁？好歹也要教個HTML嘛！」</p>
<p><a href="http://www.books.com.tw/exep/assp.php/vgod/exep/prod/booksfile.php?item=0010408051"><img class="book alignright" src="http://www.books.com.tw/exep/lib/image.php?image=http://addons.books.com.tw/G/001/1/0010408051.jpg&#038;width=200&#038;height=280&#038;quality=80" /><br />
</a></p>
<p>我覺得學習任何事物，一定要有充分的興趣才會有效率，在不知道所學為何的情況下被逼著學習是非常痛苦且沒有效率的。最近看了一本書：<a href="http://blog.vgod.tw/go.php?http://www.books.com.tw/exep/assp.php/vgod/exep/prod/booksfile.php?item=0010408051" title="(1287 hits)">沒有資優班，珍視每個孩子的芬蘭教育</a>，書中提到芬蘭教育成功的秘密在於「見樹又見林」，這句話也是我對於如何學習最想分享的秘訣。</p>
<p>台灣的教育方法是「先見樹，再見林」，也就是先教你細部的方法和技術，等你都學會之後（或是硬背起來之後），出社會後就會知道為什麼要學這些東西。（很多人小時候都聽過「等你長大就知道唸書有多重要」吧。可是現在比較多人畢業後反而說「我不知道之前念那麼多書有什麼用」）在這種體制之下，許多人在還沒見到整片森林的美景前就被一棵棵大樹搞得暈頭轉向，痛苦萬分，在不知道「學了這個可以做什麼」的情況下，不管學什麼都會覺得沒有意義沒有動力。</p>
<p>而「見樹又見林」的學習方式，是先找到能引起自己興趣的目標，讓自己有個理由去認真學習，之後再往細部的技術和理論去學習。我從小就很想自己寫遊戲，為了達成這個目標，我就四處尋找相關的資料，慢慢的我就知道自己應該要學好一個快速的低階語言（像是C++），如果要寫繪圖引擎可能還得學一點圖學的理論和技術，如果要做網路連線還得學網路相關的技術&#8230;。</p>
<p>這裡有個重點是，不要看過森林後就忘記它，而又迷失在幾棵樹幹上，要讓自己一直重複見樹又見林的過程。</p>
<p>這跟如何有效開發軟體的秘訣是一樣的。一個有效率的軟體開發方式是用<a href="http://blog.vgod.tw/go.php?http://en.wikipedia.org/wiki/Iterative_development" title="(749 hits)">iterative process</a>，把包含設計、實做、測試的iteration時間縮短，但要一直不斷重複這個iteration無數次來改進現有的成果。同理，在已經有目標的狀況下學習時，每當學會一些新東西，就要馬上試著把它實現出來，即使是只有幾行程式碼的prototype也沒關係。只要一直不斷的學，這個prototype就會一直被改進，一直加進最新學到的知識和技術而更接近最終的目標。</p>
<p>同時動腦也動手(註二)，用這種角度來學習就能充分了解自己學會的東西可以用在什麼地方，馬上得到回饋的成就感還會刺激自己繼續向前進，形成一個非常有效率的學習循環。用這種角度看學校教的東西，就能知道書本上的理論可以用在哪，並且又欠缺哪些實務知識讓自己無法做出想要的東西。</p>
<p>這方法理論上可以擴展到任何事物的學習，重點在找到有興趣的目標和書本裡知識的連結，我覺得這是老師應該要出力的地方，無奈的是台灣的教育體制把中小學老師們變成出考題和改考卷的機器人&#8230;.。</p>
<p>
註一:<br />
其實，現在真的有這樣的研究，而且驚人的是目前已經有了非常接近我想像中未來的雛型。最讓我興奮的是MIT Media Lab的<a href="http://blog.vgod.tw/go.php?http://larifari.org/" title="(965 hits)">Hugo Liu</a>和<a href="http://blog.vgod.tw/go.php?http://web.media.mit.edu/~lieber/" title="(675 hits)">Henry Lieberman</a>做的<a href="http://blog.vgod.tw/go.php?http://web.media.mit.edu/~hugo/publications/papers/IUI2005-metafor.pdf" title="(1462 hits)">Metafor</a>：只要對電腦用英文描述你要的程式，電腦就自動把Python code生出來給你&#8230;.。
</p>
<p>
註二:<br />
話說，<a href="http://blog.vgod.tw/go.php?http://en.wikipedia.org/wiki/Mit" title="(830 hits)">MIT</a>的校徽上就是一個拿著鎚子的工匠和一個拿著書的學者，所代表的意義就是 &#8220;Mind and Hand&#8221;，也就是期望每個學生都能手腦並用，除了做夢外也要實做出來才算數啊。
</p>
<p><a href="http://blog.vgod.tw/go.php?http://blog.vgod.tw/2008/08/19/divine-code-6/" title="(6819 hits)">(待續)</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.vgod.tw/2008/07/25/divine-code-5/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>追求神乎其技的程式設計之道(四）</title>
		<link>http://blog.vgod.tw/2008/07/15/%e8%bf%bd%e6%b1%82%e7%a5%9e%e4%b9%8e%e5%85%b6%e6%8a%80%e7%9a%84%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93%e5%9b%9b%ef%bc%89/</link>
		<comments>http://blog.vgod.tw/2008/07/15/%e8%bf%bd%e6%b1%82%e7%a5%9e%e4%b9%8e%e5%85%b6%e6%8a%80%e7%9a%84%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93%e5%9b%9b%ef%bc%89/#comments</comments>
		<pubDate>Tue, 15 Jul 2008 09:53:51 +0000</pubDate>
		<dc:creator>vgod</dc:creator>
				<category><![CDATA[追求神乎其技的程式設計之道]]></category>
		<category><![CDATA[Life]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.vgod.tw/?p=363</guid>
		<description><![CDATA[程式設計到底是什麼? 2000年IOI在北京舉辦，這年台灣的代表隊成績還算不錯，拿到三銀一銅，比較可惜的是我第一天表現不理想而落到了銅牌，雖然不至於兩手空空無顏面對江東父老，但也知道自己的實力大概就在銀牌和銅牌的邊緣處吧。IOI結束後，我又回到了學校，但因為已經取得大學保送資格，在學校其實也是輕鬆寫意，成天就看自己的書或研究自己有興趣的東西。 在這段時間中，我開始有所警覺，我發現我雖然很會寫程式解題，但那都是一兩百行以內的小程式，真實世界的程式根本不是這個樣子的！雖然我能很快看出一個問題該用什麼演算法效率最高，並且在很短的時間內把自己的想法正確地轉換成程式碼，但我還是不知道市面上的軟體或遊戲是怎麼做出來的。 我這時才開始接觸C++和物件導向的概念，我突然發現要寫個大程式還真不是簡單的事，除了程式語言外，還有好多瑣碎的函式庫得學。像是要畫圖就要學2D的SDL或是3D的OpenGL，要做Windows GUI程式就要學Windows SDK或是MFC，要寫網路連線就得學socket，要讓遊戲執行順暢甚至得用組合語言寫某些部分&#8230;。好多好多東西不斷湧出來，學這些東西很有趣，因為我一邊學就會一邊聯想到學會這個功能後可以用在遊戲裡的什麼地方，於是整個學習過程就像把我夢想中的拼圖一塊一塊拼上去一樣，非常有成就感。 邊寫這種實用性的程式時，我也發現以往在比賽中累積了很多不好的習慣，像是濫用全域變數、變數隨便命名、把整個程式塞在main裡&#8230;。這些壞習慣在寫小程式看不出來有什麼差別，但隨著程式規模變大，這就變成了很致命的習慣。而這種習慣一但養成，之後會變得更難改，所以強烈建議初學程式設計的朋友們，一開始就不要偷懶，從認真幫變數想個好名字開始吧！ 這段期間也讓我想了很多關於程式設計的有趣問題，像是寫程式到底算是科學+工程，還是藝術？寫程式必須要非常非常精確，任何一個字打錯都可能會讓整個程式跑出完全不同的結果，這對於天生就容易犯錯的人類來說實在是艱鉅的挑戰。為了避免錯誤太多，我們只能用一些固定的流程並強迫程式設計師遵守，讓可能的錯誤減到最低，這就是所謂的軟體工程。雖然有工程的影子，但寫程式卻是很難精確管理的工作，因為面對同樣的問題，不同的人絕對會寫出不同的程式，甚至是提出不同的解決方法﹔有的程式可能要跑三天三夜，有的程式卻能在瞬間得到正確解答﹔有的程式碼雜亂不堪，也有的程式碼井然有序清晰易讀﹔有的人要花三天寫1000行，也有人能在一天寫100行就達到完全相同的效果﹔這些程式的目的可能完全相同，但呈現方法卻有千萬種，軟體工程難道可以限制每個程式設計師大腦運作的方式和速度嗎？ 從程式碼的觀點來看，不同的人寫出的程式碼也一定不相同。從程式碼的排版、命名、段落安排、抽象化程度、運作流程可以看出作者的個性、態度、思考邏輯及深度。從這個角度來看，寫程式更像是種藝術，就像是畫筆或樂器一樣是一種表達自我並將思想具體化的工具。 另外我很感興趣的是，人一定要寫程式才能叫電腦做這麼多複雜的工作嗎？能不能教電腦寫程式，讓人只要告訴電腦要寫什麼樣的程式就好？或是有沒有更簡單更方便的方法能和電腦溝通，並且保有同樣的控制力？ 就在被這個問題困擾著的同時，我意外從一本書看到基因演算法(Genetic Algorithms)這個名詞。稍微研究過後讓我大吃一驚，因為我發現基因演算法是一個超級有效率的搜尋演算法，可以在幾近無限廣大的可能解裡面很快找到接近最佳解的答案。所以，我很快想到了，如果想要讓電腦寫程式，其實就是告訴他要寫的程式要達到什麼目的，並讓他在幾近無限大的可能程式中找出能跑出我們需要答案的那個程式。這是一種把寫程式視為搜尋的概念，我當時想到這件事非常興奮，但我並不知道其實早就有人想出同樣的概念(這叫Genetic Programming)，並已經做了許多研究。 其實有時候無知是件好事，這樣才會有勇氣在不知道這個問題有多難的情況下去嘗試看看。如果我當初就知道這問題其實是能拿好幾個博士學位甚至是得到圖靈獎(Turing Award, 資訊界的諾貝爾獎)的難題，我可能連繼續嘗試的勇氣都不會有了。 (待續)]]></description>
			<content:encoded><![CDATA[<h3>程式設計到底是什麼?</h3>
<p>2000年IOI在北京舉辦，這年台灣的代表隊成績還算不錯，拿到三銀一銅，比較可惜的是我第一天表現不理想而落到了銅牌，雖然不至於兩手空空無顏面對江東父老，但也知道自己的實力大概就在銀牌和銅牌的邊緣處吧。IOI結束後，我又回到了學校，但因為已經取得大學保送資格，在學校其實也是輕鬆寫意，成天就看自己的書或研究自己有興趣的東西。</p>
<p>在這段時間中，我開始有所警覺，我發現我雖然很會寫程式解題，但那都是一兩百行以內的小程式，真實世界的程式根本不是這個樣子的！雖然我能很快看出一個問題該用什麼演算法效率最高，並且在很短的時間內把自己的想法正確地轉換成程式碼，但我還是不知道市面上的軟體或遊戲是怎麼做出來的。</p>
<p>我這時才開始接觸C++和物件導向的概念，我突然發現要寫個大程式還真不是簡單的事，除了程式語言外，還有好多瑣碎的函式庫得學。像是要畫圖就要學2D的SDL或是3D的OpenGL，要做Windows GUI程式就要學Windows SDK或是MFC，要寫網路連線就得學socket，要讓遊戲執行順暢甚至得用組合語言寫某些部分&#8230;。好多好多東西不斷湧出來，學這些東西很有趣，因為我一邊學就會一邊聯想到學會這個功能後可以用在遊戲裡的什麼地方，於是整個學習過程就像把我夢想中的拼圖一塊一塊拼上去一樣，非常有成就感。</p>
<p>邊寫這種實用性的程式時，我也發現以往在比賽中累積了很多不好的習慣，像是濫用全域變數、變數隨便命名、把整個程式塞在main裡&#8230;。這些壞習慣在寫小程式看不出來有什麼差別，但隨著程式規模變大，這就變成了很致命的習慣。而這種習慣一但養成，之後會變得更難改，所以強烈建議初學程式設計的朋友們，一開始就不要偷懶，從認真幫變數想個好名字開始吧！</p>
<p>這段期間也讓我想了很多關於程式設計的有趣問題，像是寫程式到底算是科學+工程，還是藝術？寫程式必須要非常非常精確，任何一個字打錯都可能會讓整個程式跑出完全不同的結果，這對於天生就容易犯錯的人類來說實在是艱鉅的挑戰。為了避免錯誤太多，我們只能用一些固定的流程並強迫程式設計師遵守，讓可能的錯誤減到最低，這就是所謂的軟體工程。雖然有工程的影子，但寫程式卻是很難精確管理的工作，因為面對同樣的問題，不同的人絕對會寫出不同的程式，甚至是提出不同的解決方法﹔有的程式可能要跑三天三夜，有的程式卻能在瞬間得到正確解答﹔有的程式碼雜亂不堪，也有的程式碼井然有序清晰易讀﹔有的人要花三天寫1000行，也有人能在一天寫100行就達到完全相同的效果﹔這些程式的目的可能完全相同，但呈現方法卻有千萬種，軟體工程難道可以限制每個程式設計師大腦運作的方式和速度嗎？</p>
<p>從程式碼的觀點來看，不同的人寫出的程式碼也一定不相同。從程式碼的排版、命名、段落安排、抽象化程度、運作流程可以看出作者的個性、態度、思考邏輯及深度。從這個角度來看，寫程式更像是種藝術，就像是畫筆或樂器一樣是一種表達自我並將思想具體化的工具。</p>
<p>另外我很感興趣的是，人一定要寫程式才能叫電腦做這麼多複雜的工作嗎？能不能教電腦寫程式，讓人只要告訴電腦要寫什麼樣的程式就好？或是有沒有更簡單更方便的方法能和電腦溝通，並且保有同樣的控制力？</p>
<p>就在被這個問題困擾著的同時，我意外從一本書看到基因演算法(Genetic Algorithms)這個名詞。稍微研究過後讓我大吃一驚，因為我發現基因演算法是一個超級有效率的搜尋演算法，可以在幾近無限廣大的可能解裡面很快找到接近最佳解的答案。所以，我很快想到了，如果想要讓電腦寫程式，其實就是告訴他要寫的程式要達到什麼目的，並讓他在幾近無限大的可能程式中找出能跑出我們需要答案的那個程式。這是一種把寫程式視為搜尋的概念，我當時想到這件事非常興奮，但我並不知道其實早就有人想出同樣的概念(這叫Genetic Programming)，並已經做了許多研究。</p>
<p>其實有時候無知是件好事，這樣才會有勇氣在不知道這個問題有多難的情況下去嘗試看看。如果我當初就知道這問題其實是能拿好幾個博士學位甚至是得到圖靈獎(Turing Award, 資訊界的諾貝爾獎)的難題，我可能連繼續嘗試的勇氣都不會有了。</p>
<p>(待續)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.vgod.tw/2008/07/15/%e8%bf%bd%e6%b1%82%e7%a5%9e%e4%b9%8e%e5%85%b6%e6%8a%80%e7%9a%84%e7%a8%8b%e5%bc%8f%e8%a8%ad%e8%a8%88%e4%b9%8b%e9%81%93%e5%9b%9b%ef%bc%89/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>

