<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en" xml:base="http://fcamel.twbbs.org/wp-atom.php">
	<title type="text">fcamel's blog</title>
	<subtitle type="text">自強不息的駱駝有草吃</subtitle>

	<updated>2009-11-08T03:18:06Z</updated>
	<generator uri="http://wordpress.org/" version="2.7">WordPress</generator>

	<link rel="alternate" type="text/html" href="http://fcamel.twbbs.org" />
	<id>http://fcamel.twbbs.org/feed/atom/</id>
	

			<link rel="self" href="http://feeds.feedburner.com/fcamel" type="application/atom+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry>
		<author>
			<name>fcamel</name>
					</author>
		<title type="html"><![CDATA[我學 TDD 的方式]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/fcamel/~3/mc4xZauxiaw/" />
		<id>http://fcamel.twbbs.org/?p=945</id>
		<updated>2009-11-08T03:18:06Z</updated>
		<published>2009-11-08T03:02:42Z</published>
		<category scheme="http://fcamel.twbbs.org" term="All" /><category scheme="http://fcamel.twbbs.org" term="Programming" /><category scheme="http://fcamel.twbbs.org" term="Refactoring" /><category scheme="http://fcamel.twbbs.org" term="Testing" />		<summary type="html"><![CDATA[學 TDD ( 測試驅動開發 ) 的動機請見《為什麼要寫 unit test？為什麼要先寫測試？》。這篇簡記一下我學習 TDD 的方式：

TDD 的流程、精神：網路上零散的短文 [1] 和 Kent Beck 的書《Test Driven Development: By Example 》。
Testing 的技巧：從 Google 的 Agile Coach Miško Hevery 的 Blog 學。
Refactoring 的技巧：從 Martin Fowler 的書《重構：改善既有程式的設計》以及他的 Blog 學


看完書後，大致上是從大師的 Blog 跳著看有興趣（或著說，讀起來比較有感覺）的部份。自己寫個一陣子就看個幾篇，待思考消化後再回頭試著用自己的方式寫出來。如此反覆進行。最重要的是在自己的環境裡，用自己的方式進行 TDD，感受會更明確。
TDD 的概念很簡單，看過例子後應該能馬上使用，但無法立即精通 TDD 。它是一個習慣，而培養習慣需要時間累積。養成習慣後，接著需要提昇測試和重構的技巧，才能逐步提昇效果並降低使用 TDD 的成本。如同過去學 Design Pattern 或其它寫程式的技巧一般，需要讀書和時間練習。我在前幾次使用 TDD 時有犯一些錯，使得效果打折，有感受到一些好處，但也對一些壞處感到疑惑。直到寫了
五、六個小專案後，才釐清一些疑慮，確信 TDD 是很划算的取捨，從而決定持續使用 TDD。最近用它寫超過一萬行程式，更加感受到它的威力。
備註

Java 的例子可見 The [...]]]></summary>
		<content type="html" xml:base="http://fcamel.twbbs.org/archives/2009/11/08/945/">&lt;p&gt;學 &lt;a href="http://fcamel.twbbs.org/archives/2009/03/09/747/" &gt;TDD ( 測試驅動開發 )&lt;/a&gt; 的動機請見&lt;a href="/archives/2009/06/13/849/"&gt;《為什麼要寫 unit test？為什麼要先寫測試？》&lt;/a&gt;。這篇簡記一下我學習 TDD 的方式：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;TDD 的流程、精神：網路上零散的短文 [1] 和 Kent Beck 的書&lt;a href="http://www.amazon.com/Test-Driven-Development-Kent-Beck/dp/0321146530" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.amazon.com');"&gt;《Test Driven Development: By Example 》&lt;/a&gt;。&lt;/li&gt;
&lt;li&gt;Testing 的技巧：從 Google 的 Agile Coach &lt;a href="http://misko.hevery.com/" onclick="javascript:pageTracker._trackPageview('/outbound/article/misko.hevery.com');"&gt;Miško Hevery 的 Blog&lt;/a&gt; 學。&lt;/li&gt;
&lt;li&gt;Refactoring 的技巧：從 Martin Fowler 的書&lt;a href="http://www.books.com.tw/exep/prod/booksfile.php?item=0010231852" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.books.com.tw');"&gt;《重構：改善既有程式的設計》&lt;/a&gt;以及他的 &lt;a href="http://martinfowler.com/articles.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/martinfowler.com');"&gt;Blog &lt;/a&gt;學&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span id="more-945"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;看完書後，大致上是從大師的 Blog 跳著看有興趣（或著說，讀起來比較有感覺）的部份。自己寫個一陣子就看個幾篇，待思考消化後再回頭試著用自己的方式寫出來。如此反覆進行。&lt;strong&gt;最重要的是在自己的環境裡，用自己的方式進行 TDD，感受會更明確。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;TDD 的概念很簡單，看過例子後應該能馬上使用，但無法立即精通 TDD 。&lt;strong&gt;它是一個習慣，而培養習慣需要時間累積。&lt;/strong&gt;養成習慣後，接著&lt;strong&gt;需要提昇測試和重構的技巧，才能逐步提昇效果並降低使用 TDD 的成本。&lt;/strong&gt;如同過去學 Design Pattern 或其它寫程式的技巧一般，需要讀書和時間練習。我在前幾次使用 TDD 時有犯一些錯，使得效果打折，有感受到一些好處，但也對一些壞處感到疑惑。直到寫了&lt;br /&gt;
五、六個小專案後，才釐清一些疑慮，確信 TDD 是很划算的取捨，從而決定持續使用 TDD。最近用它&lt;a href="/archives/2009/10/29/928/"&gt;寫超過一萬行程式&lt;/a&gt;，更加感受到它的威力。&lt;/p&gt;
&lt;h4&gt;備註&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Java 的例子可見 &lt;a href="http://butunclebob.com/ArticleS.UncleBob.TheBowlingGameKata" onclick="javascript:pageTracker._trackPageview('/outbound/article/butunclebob.com');"&gt;The Bowling Game Kata&lt;/a&gt;；Python 的例子可見 Dive into Python 3 &lt;a href="http://diveintopython3.org/unit-testing.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/diveintopython3.org');"&gt;介紹 unittest module 的章節&lt;/a&gt;和&lt;a href="http://diveintopython3.org/refactoring.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/diveintopython3.org');"&gt;介紹 refactoring 的章節&lt;/a&gt;。《Dive into Python 3》的例子比較不像真實的 TDD，為了教學方便，作者直接寫最終版的測試碼。若要看原汁原味的演化過程，看 Java 的例子或 Kent Beck 的書較適當。&lt;/li&gt;
&lt;/ol&gt;
&lt;img src="http://feeds.feedburner.com/~r/fcamel/~4/mc4xZauxiaw" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://fcamel.twbbs.org/archives/2009/11/08/945/#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://fcamel.twbbs.org/archives/2009/11/08/945/feed/atom/" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://fcamel.twbbs.org/archives/2009/11/08/945/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>fcamel</name>
					</author>
		<title type="html"><![CDATA[賀！Python 寫破萬行記念！]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/fcamel/~3/q17zYSbKu5U/" />
		<id>http://fcamel.twbbs.org/?p=928</id>
		<updated>2009-10-29T16:32:58Z</updated>
		<published>2009-10-29T15:40:10Z</published>
		<category scheme="http://fcamel.twbbs.org" term="All" /><category scheme="http://fcamel.twbbs.org" term="Programming" /><category scheme="http://fcamel.twbbs.org" term="Python" /><category scheme="http://fcamel.twbbs.org" term="Testing" />		<summary type="html"><![CDATA[這是我獨力寫過最大的專案了，從八月初開始寫，不知不覺寫到破萬行啊，而且其中有四千多行是測試碼，貫徹當初 TDD 到底的決心。

不得不說，幸虧有用 TDD，不然測試碼大概會丟三落四的，愈後面會愈痛苦，最後就會想砍掉重練。開發過程裡遇過幾次很難改的情況（第一次發生在寫到兩千多行時），幸好仗著測試碼夠齊全，將相關程式重構後，不知不覺就把新功能寫好了。
有時沒啥想法，不知怎麼改較好，就想說「總之就先重構，船到橋頭自然直」。結果這招矇對的機率還滿高的，有時還會發覺比原本構想更簡單的做法。有些人認為重構成本很高，且短期沒有產值，似乎不適合常做。事實上，在測試碼充沛且時常重構的情況下，可以三兩下完成重構，再加上版本管理系統的輔助，重構失敗立即重來，十分方便。
使用 TDD 偶而會有意外收獲，發覺巧妙設計。有時即使看個數次，還是學不會自己完成目標用上的新技巧，感覺好像用外掛過關，卻不知道自己怎麼過的。最後只能期望下回遇到類似的處理，TDD 仍能導引出良好的設計。對照《物件導向程式的九個體操練習》來看，發現在 TDD 的導引之下，自然地會做出較佳的設計（因為較差的設計不好測），而且會因地制宜，做出貼近需求的做法，不會 overdesign。
雖說在很久以前就確定 TDD 是正確的路，也領悟出可測性 (testability) 是首要之務，為了可測性而改變原本的設計也是合適的決定。還是需要許多實際經驗，才能更充份地體會這些原則帶來的影響。我喜歡 freedom 說過的一句話「 system design 一直都是 trade-off」，經過這一年多的歷練 [1]，我更肯定 TDD 帶來的 trade-off 是值得的，加強寫測試碼的技術絕對是值回票價的投資。
咦？這篇好像離題成行銷 TDD，回頭來補講 Python 的心得。寫這個專案的途中接觸到比較深的 Python 議題，像是用 ctypes 包 C/C++ API 很方便；好用的畫圖函式庫 matplotlib；還有一拖拉庫的速度問題讓我學了不少，比方說：

cProfile 絕對是找瓶頸的頭號幫手，做 profiling 時也不會拖慢多少。除演算法的考量外，別自己亂猜浪費時間。
list 很大但不需用到 sublist 或 index 的功能時，可以用 generator 改寫。
若有個欄位被存取數百萬次以上，用 data field 會比用 method 快上不少，因為 Python 的 function call [...]]]></summary>
		<content type="html" xml:base="http://fcamel.twbbs.org/archives/2009/10/29/928/">&lt;p&gt;這是我獨力寫過最大的專案了，從八月初開始寫，不知不覺寫到破萬行啊，而且其中有四千多行是測試碼，貫徹當初 TDD 到底的決心。&lt;/p&gt;
&lt;p&gt;&lt;span id="more-928"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;不得不說，幸虧有用 TDD，不然測試碼大概會丟三落四的，愈後面會愈痛苦，最後就會想砍掉重練。開發過程裡遇過幾次很難改的情況（第一次發生在寫到兩千多行時），幸好仗著測試碼夠齊全，將相關程式重構後，不知不覺就把新功能寫好了。&lt;/p&gt;
&lt;p&gt;有時沒啥想法，不知怎麼改較好，就想說「總之就先重構，船到橋頭自然直」。結果這招矇對的機率還滿高的，有時還會發覺比原本構想更簡單的做法。有些人認為重構成本很高，且短期沒有產值，似乎不適合常做。事實上，在測試碼充沛且時常重構的情況下，可以三兩下完成重構，再加上版本管理系統的輔助，重構失敗立即重來，十分方便。&lt;/p&gt;
&lt;p&gt;使用 TDD 偶而會有意外收獲，發覺巧妙設計。有時即使看個數次，還是學不會自己完成目標用上的新技巧，感覺好像用外掛過關，卻不知道自己怎麼過的。最後只能期望下回遇到類似的處理，TDD 仍能導引出良好的設計。對照&lt;a href="http://ihower.idv.tw/blog/archives/1960" onclick="javascript:pageTracker._trackPageview('/outbound/article/ihower.idv.tw');"&gt;《物件導向程式的九個體操練習》&lt;/a&gt;來看，發現在 TDD 的導引之下，自然地會做出較佳的設計（因為較差的設計不好測），而且會因地制宜，做出貼近需求的做法，不會 overdesign。&lt;/p&gt;
&lt;p&gt;雖說在很久以前就確定 TDD 是正確的路，也領悟出可測性 (testability) 是首要之務，為了可測性而改變原本的設計也是合適的決定。還是需要許多實際經驗，才能更充份地體會這些原則帶來的影響。我喜歡 freedom 說過的一句話「 system design 一直都是 trade-off」，經過這一年多的歷練 [1]，我更肯定 TDD 帶來的 trade-off 是值得的，加強寫測試碼的技術絕對是值回票價的投資。&lt;/p&gt;
&lt;p&gt;咦？這篇好像離題成行銷 TDD，回頭來補講 Python 的心得。寫這個專案的途中接觸到比較深的 Python 議題，像是用 ctypes 包 C/C++ API 很方便；好用的畫圖函式庫 matplotlib；還有一拖拉庫的速度問題讓我學了不少，比方說：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;cProfile 絕對是找瓶頸的頭號幫手，做 profiling 時也不會拖慢多少。除演算法的考量外，別自己亂猜浪費時間。&lt;/li&gt;
&lt;li&gt;list 很大但不需用到 sublist 或 index 的功能時，可以用 generator 改寫。&lt;/li&gt;
&lt;li&gt;若有個欄位被存取數百萬次以上，用 data field 會比用 method 快上不少，因為 Python 的 function call 不快。&lt;/li&gt;
&lt;li&gt;collections.defaultdict 比 dict.get(key, default_value) 快上一些。&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.dabeaz.com/blog/2009/08/inside-inside-python-gil-presentation.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.dabeaz.com');"&gt;CPython 使用 GIL 造成 multi-thread 比 single-thread 還慢&lt;/a&gt;，要想用多 CPU 加速，可以用 2.6 內建的 multiprocessing。multiprocessing 用法不難，可是有一堆小細節會爆炸，要仔細讀&lt;a href="http://docs.python.org/library/multiprocessing.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/docs.python.org');"&gt;官方文件&lt;/a&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;雖說調速度很辛苦，整體來看還是值得的，而且 Python 和 C/C++ 之間溝通很容易，針對效能改寫的成本不高，更何況有測試碼撐著，修改很容易。讓我覺得用 Python 快速開發原型，針對瓶頸用 C/C++ 改寫或平行化的流程還挺不錯的。&lt;/p&gt;
&lt;p&gt;除了以上這堆拉里拉雜的收獲，更大的收獲是學到了一個專案的演化過程。過去自己太心急，什麼都想一開始做到最好，擔心後期會愈來愈難改，災難一發不可收拾。結果是搞得自己很累，開發效率很差、程式品質漸漸變糟也不知道從何改善。後來放開心胸，延伸 TDD 的精神，先做最主要的部份，再慢慢修補小問題：像是註解、模組文件格式、行寛該定多少 [2]、某設計會不會太慢、會不會太髒等。稍微轉換思維、改變自己的習慣，會發現過去許多困擾都不見了，似乎多明白了一點「擁抱變化」的含意了 [3]。&lt;/p&gt;
&lt;h4&gt;備註&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;接觸 TDD 的概念；用它實作近十個小專案包含 C++、Java、Python 三種語言；單一專案寫了上萬行的程式。&lt;/li&gt;
&lt;li&gt;我後來習慣用 85。這樣用 24&amp;#8243; 螢幕配 putty 預設字型大小，用 VIM 剛好可以垂直分割成兩個視窗而不會折行。&lt;/li&gt;
&lt;li&gt;話說我以前一直覺得這個詞很嘴炮啊。&lt;/li&gt;
&lt;/ol&gt;
&lt;img src="http://feeds.feedburner.com/~r/fcamel/~4/q17zYSbKu5U" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://fcamel.twbbs.org/archives/2009/10/29/928/#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://fcamel.twbbs.org/archives/2009/10/29/928/feed/atom/" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://fcamel.twbbs.org/archives/2009/10/29/928/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>fcamel</name>
					</author>
		<title type="html"><![CDATA[寫 Python 測試碼的好幫手]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/fcamel/~3/RLjR-HyZQTM/" />
		<id>http://fcamel.twbbs.org/?p=918</id>
		<updated>2009-10-04T13:33:25Z</updated>
		<published>2009-09-22T14:42:43Z</published>
		<category scheme="http://fcamel.twbbs.org" term="All" /><category scheme="http://fcamel.twbbs.org" term="Programming" /><category scheme="http://fcamel.twbbs.org" term="Python" /><category scheme="http://fcamel.twbbs.org" term="Testing" />		<summary type="html"><![CDATA[前陣子用 TDD 寫了個六千多行的工具，這篇記錄一下過程中惠我良多的好幫手。

unittest
內建模組。
用法見官網介紹或《Dive into Python 3》的第九章 Unit Testing ( 有附帶介紹 TDD ) ，如同 Java 的 JUnit 3.x，用 unittest.TestCase 來寫 test case 很方便。
coverage
安裝方式：easy_install coverage。
Code coverage 是分析測試碼品質的方法，標示出測試碼沒有執行到那幾行程式碼。使用 Code coverage 的基本精神是：Code coverage 的數據高不表示測試碼有效，但數據低的話，測試品質必定不好。至於高低要如何界定？這得看專案的類型，比方科學計算型的程式，要求 80% 以上並不過份；而有一堆圖形介面的程式，可能連到 60% 都很難。
coverage 官網有簡單易懂的使用例子。由於 Python 的功能限制，coverage 無法作到像 Java 那麼全面。coverage 的限制以及 Code coverage 的注意事項，詳見作者的說明：&#8220;Coverage testing, the good and the bad.&#8221;
nose
安裝方式： easy_install nose。
寫 unittest 時，管理 test [...]]]></summary>
		<content type="html" xml:base="http://fcamel.twbbs.org/archives/2009/09/22/918/">&lt;p&gt;前陣子用 &lt;a href="/archives/2009/03/09/747/"&gt;TDD&lt;/a&gt; 寫了個六千多行的工具，這篇記錄一下過程中惠我良多的好幫手。&lt;/p&gt;
&lt;p&gt;&lt;span id="more-918"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4&gt;unittest&lt;/h4&gt;
&lt;p&gt;內建模組。&lt;/p&gt;
&lt;p&gt;用法見&lt;a href="http://docs.python.org/library/unittest.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/docs.python.org');"&gt;官網介紹&lt;/a&gt;或&lt;a href="http://diveintopython3.org/unit-testing.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/diveintopython3.org');"&gt;《Dive into Python 3》的第九章 Unit Testing&lt;/a&gt; ( 有附帶介紹 TDD ) ，如同 Java 的 JUnit 3.x，用 unittest.TestCase 來寫 test case 很方便。&lt;/p&gt;
&lt;h4&gt;coverage&lt;/h4&gt;
&lt;p&gt;安裝方式：easy_install coverage。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Code_coverage" onclick="javascript:pageTracker._trackPageview('/outbound/article/en.wikipedia.org');"&gt;Code coverage&lt;/a&gt; 是分析測試碼品質的方法，標示出測試碼沒有執行到那幾行程式碼。使用 &lt;a href="http://en.wikipedia.org/wiki/Code_coverage" onclick="javascript:pageTracker._trackPageview('/outbound/article/en.wikipedia.org');"&gt;Code coverage&lt;/a&gt; 的基本精神是：&lt;a href="http://en.wikipedia.org/wiki/Code_coverage" onclick="javascript:pageTracker._trackPageview('/outbound/article/en.wikipedia.org');"&gt;Code coverage&lt;/a&gt; 的數據高不表示測試碼有效，但數據低的話，測試品質必定不好。至於高低要如何界定？這得看專案的類型，比方科學計算型的程式，要求 80% 以上並不過份；而有一堆圖形介面的程式，可能連到 60% 都很難。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://nedbatchelder.com/code/coverage/" onclick="javascript:pageTracker._trackPageview('/outbound/article/nedbatchelder.com');"&gt;coverage 官網&lt;/a&gt;有簡單易懂的使用例子。由於 Python 的功能限制，&lt;a href="http://nedbatchelder.com/code/coverage/" onclick="javascript:pageTracker._trackPageview('/outbound/article/nedbatchelder.com');"&gt;coverage&lt;/a&gt; 無法作到像 Java 那麼全面。&lt;a href="http://nedbatchelder.com/code/coverage/" onclick="javascript:pageTracker._trackPageview('/outbound/article/nedbatchelder.com');"&gt;coverage&lt;/a&gt; 的限制以及 &lt;a href="http://en.wikipedia.org/wiki/Code_coverage" onclick="javascript:pageTracker._trackPageview('/outbound/article/en.wikipedia.org');"&gt;Code coverage&lt;/a&gt; 的注意事項，詳見作者的說明：&lt;a href="http://us.pycon.org/2009/conference/schedule/event/26/" onclick="javascript:pageTracker._trackPageview('/outbound/article/us.pycon.org');"&gt;&amp;#8220;Coverage testing, the good and the bad.&amp;#8221;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;nose&lt;/h4&gt;
&lt;p&gt;安裝方式： easy_install nose。&lt;/p&gt;
&lt;p&gt;寫 unittest 時，管理 test suit 是件很瑣碎又易犯錯的事，相信很多人會想說，能不能跑個程式，自行搜集目錄下全部的測試碼並自動執行。沒錯，大家的心聲 &lt;a href="http://somethingaboutorange.com/mrl/projects/nose/0.11.1/index.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/somethingaboutorange.com');"&gt;nose&lt;/a&gt; 聽到了！這裡直接用例子說明 &lt;a href="http://somethingaboutorange.com/mrl/projects/nose/0.11.1/index.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/somethingaboutorange.com');"&gt;nose&lt;/a&gt; 的使用方式：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;執行目前目錄下所有測試：

&lt;div class="wp_syntax"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="line_numbers"&gt;&lt;pre&gt;1
&lt;/pre&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre class="shell" style="font-family:monospace;"&gt;nosetests&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;執行目前目錄下所有測試並附上子目錄 pkg1、pkg2 的 &lt;a href="http://en.wikipedia.org/wiki/Code_coverage" onclick="javascript:pageTracker._trackPageview('/outbound/article/en.wikipedia.org');"&gt;Code coverage&lt;/a&gt; 資訊：

&lt;div class="wp_syntax"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="line_numbers"&gt;&lt;pre&gt;1
&lt;/pre&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre class="shell" style="font-family:monospace;"&gt;nosetests --with-coverage --cover-package=pkg1,pkg2 --cover-erase&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;不要執行 slow_test.py：

&lt;div class="wp_syntax"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="line_numbers"&gt;&lt;pre&gt;1
&lt;/pre&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre class="shell" style="font-family:monospace;"&gt;nosetests -e slow_test.py&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;使用四個 CPU 平行執行測試：

&lt;div class="wp_syntax"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="line_numbers"&gt;&lt;pre&gt;1
&lt;/pre&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre class="shell" style="font-family:monospace;"&gt;nosetests --processes=4&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#8211;with-coverage 需要先裝 &lt;a href="http://nedbatchelder.com/code/coverage/" onclick="javascript:pageTracker._trackPageview('/outbound/article/nedbatchelder.com');"&gt;coverage&lt;/a&gt;；&amp;#8211;process 得另裝 package multiprocessing ( easy_install multiprocessing )，相關說明詳見 &lt;a href="http://somethingaboutorange.com/mrl/projects/nose/0.11.1/plugins/multiprocess.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/somethingaboutorange.com');"&gt;Multiprocess: parallel testing&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;另外，若要讓 &lt;a href="http://somethingaboutorange.com/mrl/projects/nose/0.11.1/index.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/somethingaboutorange.com');"&gt;nose&lt;/a&gt; 跳過物件 A 的測試，就在程式裡寫上&lt;/p&gt;

&lt;div class="wp_syntax"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="line_numbers"&gt;&lt;pre&gt;1
&lt;/pre&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre class="python" style="font-family:monospace;"&gt;A.__test__ = &lt;span style="color: #008000;"&gt;False&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;比方若不想測模組 mod，就在 mod.py 裡寫上&lt;/p&gt;

&lt;div class="wp_syntax"&gt;&lt;table&gt;&lt;tr&gt;&lt;td class="line_numbers"&gt;&lt;pre&gt;1
&lt;/pre&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;pre class="python" style="font-family:monospace;"&gt;__test__ = &lt;span style="color: #008000;"&gt;False&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;sqlite3&lt;/h4&gt;
&lt;p&gt;內建模組。&lt;/p&gt;
&lt;p&gt;用法見&lt;a href="http://docs.python.org/library/sqlite3.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/docs.python.org');"&gt;官網介紹&lt;/a&gt;。在測試資料庫時，個人覺得 local database 比 &lt;a href="http://martinfowler.com/articles/mocksArentStubs.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/martinfowler.com');"&gt;mock&lt;/a&gt; 好用，方便準備資料，測起來也比較踏實，而且使用 memory mode 可大幅減少執行時間。附帶一提，&lt;a href="http://www.sqlite.org/" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.sqlite.org');"&gt;sqlite&lt;/a&gt; 跨 C、Python、Java 等語言，支援 SQL 92，執行速度又快，相當好用。&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/fcamel/~4/RLjR-HyZQTM" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://fcamel.twbbs.org/archives/2009/09/22/918/#comments" thr:count="2" />
		<link rel="replies" type="application/atom+xml" href="http://fcamel.twbbs.org/archives/2009/09/22/918/feed/atom/" thr:count="2" />
		<thr:total>2</thr:total>
	<feedburner:origLink>http://fcamel.twbbs.org/archives/2009/09/22/918/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>fcamel</name>
					</author>
		<title type="html"><![CDATA[Honey &#038; Clover I, II 觀後感]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/fcamel/~3/e4PLDRdUIiI/" />
		<id>http://fcamel.twbbs.org/?p=910</id>
		<updated>2009-09-21T00:25:08Z</updated>
		<published>2009-09-20T15:17:21Z</published>
		<category scheme="http://fcamel.twbbs.org" term="ACG" /><category scheme="http://fcamel.twbbs.org" term="Animation" />		<summary type="html"><![CDATA[
又看了一次 Honey &#038; Clover 第一部和第二部，已經明白劇情發展的我，這次還是一樣被情節給牽動著，忍不住一集集地看下去，而且更能注意細節，更能感受到作者細膩的鋪陳。

看完許久，仍然無法用文筆表達情緒的我，只好照老樣子看著別人的心得，和著劇中插曲讓感覺漸漸褪去。最後的結局，究竟小育是抱著什麼樣的心情，將那份點心交給竹本的呢？
小育想傳達的心意，竹本確實地收到了。一再地重覆看著這段，我不知道自己感受到的是什麼，劇中插曲的歌詞是這麼寫著的：


   平靜清澈的溪水，毫不躊躇地向前流淌。
   令人懷念的午後熏風，吹拂著濕透的脖頸。
   野兔不停奔跑的樣子，白百合的耀眼花姿，
   夜空中閃耀的星群，都理所當然地在我眼中。
   相信一定會觸碰到的幻影，
   充斥著言語的底片中的街道延續著。
   再見吧，再見吧，向著不知何時的你。
   如果還能遇見你就好了。
只能不斷地聽著插曲，試著沉浸在兩人的心情中，隨手寫出片段的思緒。
小育和竹本彼此的心意，不是友情、愛情之類的字眼可以表示的，那究竟是什麼呢？對於他們而言，這樣的分別又代表什麼呢？為什麼如此的不捨？為什麼如此地感傷？滿腹疑問的我似乎明白答案為何，卻無法述諸言語，或是不願述諸言語。於是不斷重覆聽著插曲、重覆想著兩人的心情、隨手敲著鍵盤，讓這份情感深刻地注入內心深處。對於祝福的人以及被祝福的人都能幸福，感到無比地欣慰，只是感傷也隨著揮之不去。
]]></summary>
		<content type="html" xml:base="http://fcamel.twbbs.org/archives/2009/09/20/910/">&lt;p&gt;&lt;a href="http://www.flickr.com/photos/12203797@N00/3937596080/" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.flickr.com');" title="Honey &amp;amp; Clover by fcamel, on Flickr"&gt;&lt;img src="http://farm3.static.flickr.com/2573/3937596080_6a4750bf54.jpg" width="500" height="281" alt="Honey &amp;amp; Clover" /&gt;&lt;/a&gt;&lt;br /&gt;
又看了一次 Honey &amp;#038; Clover 第一部和第二部，已經明白劇情發展的我，這次還是一樣被情節給牽動著，忍不住一集集地看下去，而且更能注意細節，更能感受到作者細膩的鋪陳。&lt;/p&gt;
&lt;p&gt;&lt;span id="more-910"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;看完許久，仍然無法用文筆表達情緒的我，只好照老樣子看著別人的心得，和著劇中插曲讓感覺漸漸褪去。最後的結局，究竟小育是抱著什麼樣的心情，將那份點心交給竹本的呢？&lt;/p&gt;
&lt;p&gt;小育想傳達的心意，竹本確實地收到了。一再地重覆看著這段，我不知道自己感受到的是什麼，劇中插曲的歌詞是這麼寫著的：&lt;/p&gt;
&lt;p&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/E_qcHT9tSXI&amp;#038;hl=en&amp;#038;fs=1&amp;#038;"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/E_qcHT9tSXI&amp;#038;hl=en&amp;#038;fs=1&amp;#038;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;
   平靜清澈的溪水，毫不躊躇地向前流淌。&lt;br /&gt;
   令人懷念的午後熏風，吹拂著濕透的脖頸。&lt;br /&gt;
   野兔不停奔跑的樣子，白百合的耀眼花姿，&lt;br /&gt;
   夜空中閃耀的星群，都理所當然地在我眼中。&lt;/p&gt;
&lt;p&gt;   相信一定會觸碰到的幻影，&lt;br /&gt;
   充斥著言語的底片中的街道延續著。&lt;br /&gt;
   再見吧，再見吧，向著不知何時的你。&lt;br /&gt;
   如果還能遇見你就好了。&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;只能不斷地聽著插曲，試著沉浸在兩人的心情中，隨手寫出片段的思緒。&lt;/p&gt;
&lt;p&gt;小育和竹本彼此的心意，不是友情、愛情之類的字眼可以表示的，那究竟是什麼呢？對於他們而言，這樣的分別又代表什麼呢？為什麼如此的不捨？為什麼如此地感傷？滿腹疑問的我似乎明白答案為何，卻無法述諸言語，或是不願述諸言語。於是不斷重覆聽著插曲、重覆想著兩人的心情、隨手敲著鍵盤，讓這份情感深刻地注入內心深處。對於祝福的人以及被祝福的人都能幸福，感到無比地欣慰，只是感傷也隨著揮之不去。&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/fcamel/~4/e4PLDRdUIiI" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://fcamel.twbbs.org/archives/2009/09/20/910/#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://fcamel.twbbs.org/archives/2009/09/20/910/feed/atom/" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://fcamel.twbbs.org/archives/2009/09/20/910/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>fcamel</name>
					</author>
		<title type="html"><![CDATA[康特的難題]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/fcamel/~3/t81k40a-x_k/" />
		<id>http://fcamel.twbbs.org/?p=903</id>
		<updated>2009-09-06T06:16:33Z</updated>
		<published>2009-09-06T06:13:20Z</published>
		<category scheme="http://fcamel.twbbs.org" term="All" /><category scheme="http://fcamel.twbbs.org" term="Book" /><category scheme="http://fcamel.twbbs.org" term="Fiction" /><category scheme="http://fcamel.twbbs.org" term="Research" />		<summary type="html"><![CDATA[書籍基本資料：《康特的難題》。
看到中後半時，由於相當在意某位角色出奇的應對方式，讓我不得不硬衝了兩小時看到結尾，導致我破例到淩晨兩點才睡，上回這樣挑燈夜戰讀小說，應該是國高中時看金庸小說吧？

若以一般小說來說，算是普普吧。但這本揭開科學界的生活，並用非科學界人士質疑科學界視為常識的文化，還有點出女性科學界的困境，都很有意思，可滿足我對科學界人性的好奇心。像是學界慣於使用的「我們」，究竟意指為何？作者順序的含意？提出想法和執行實驗何者較為重要？實驗室成員是合作者，還是手下？害怕被盜用想法而不敢發表，以及急於發表以追求第一發現者榮譽的衝突？實驗數據不如預期，做些「適當」的調整，是修正誤差還是照假？女性學者在追求終身職和小孩之間的抉擇？書中點出許多與科學誠實、無私、公正、理性、分享等特質矛盾的人性弱點，有許多令人深省的地方。角色的佈局也滿有意思的，將幾位看似無關的核心角色，慢慢地交錯在一起，若起頭和結尾能更圓潤就更棒了。
看完這本書後，讓我更不想走學界路線，我明白自己很難抗拒種種誘惑堅持自己。即使能堅持自己，也很難要求合作者照自己的要求進行，有太多灰色地帶，很難令合作者與自己達成共識。還是遠離利益得失，才能自在地以自己的步調前進。
]]></summary>
		<content type="html" xml:base="http://fcamel.twbbs.org/archives/2009/09/06/903/">&lt;p&gt;書籍基本資料：&lt;a href="http://www.books.com.tw/exep/prod/booksfile.php?item=0010021477" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.books.com.tw');"&gt;《康特的難題》&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;看到中後半時，由於相當在意某位角色出奇的應對方式，讓我不得不硬衝了兩小時看到結尾，導致我破例到淩晨兩點才睡，上回這樣挑燈夜戰讀小說，應該是國高中時看金庸小說吧？&lt;/p&gt;
&lt;p&gt;&lt;span id="more-903"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;若以一般小說來說，算是普普吧。但這本揭開科學界的生活，並用非科學界人士質疑科學界視為常識的文化，還有點出女性科學界的困境，都很有意思，可滿足我對科學界人性的好奇心。像是學界慣於使用的「我們」，究竟意指為何？作者順序的含意？提出想法和執行實驗何者較為重要？實驗室成員是合作者，還是手下？害怕被盜用想法而不敢發表，以及急於發表以追求第一發現者榮譽的衝突？實驗數據不如預期，做些「適當」的調整，是修正誤差還是照假？女性學者在追求終身職和小孩之間的抉擇？書中點出許多與科學誠實、無私、公正、理性、分享等特質矛盾的人性弱點，有許多令人深省的地方。角色的佈局也滿有意思的，將幾位看似無關的核心角色，慢慢地交錯在一起，若起頭和結尾能更圓潤就更棒了。&lt;/p&gt;
&lt;p&gt;看完這本書後，讓我更不想走學界路線，我明白自己很難抗拒種種誘惑堅持自己。即使能堅持自己，也很難要求合作者照自己的要求進行，有太多灰色地帶，很難令合作者與自己達成共識。還是遠離利益得失，才能自在地以自己的步調前進。&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/fcamel/~4/t81k40a-x_k" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://fcamel.twbbs.org/archives/2009/09/06/903/#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://fcamel.twbbs.org/archives/2009/09/06/903/feed/atom/" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://fcamel.twbbs.org/archives/2009/09/06/903/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>fcamel</name>
					</author>
		<title type="html"><![CDATA[驗證第一、想法第二]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/fcamel/~3/XSpnjRZb9ck/" />
		<id>http://fcamel.twbbs.org/?p=898</id>
		<updated>2009-09-06T03:03:47Z</updated>
		<published>2009-09-05T08:14:32Z</published>
		<category scheme="http://fcamel.twbbs.org" term="All" /><category scheme="http://fcamel.twbbs.org" term="Programming" /><category scheme="http://fcamel.twbbs.org" term="Research" /><category scheme="http://fcamel.twbbs.org" term="Testing" />		<summary type="html"><![CDATA[看到這篇《The Only Truly Failed Project》，其中有兩段話寫得很棒：
Failure is a wonderful teacher. But there&#8217;s no need to seek out failure. It will find you.
The only truly failed project is the one where you didn&#8217;t learn anything along the way.
最近觀察不少數據和實驗結果，推翻之前許多猜想，不過我沒有像碩士做研究時那般痛苦，反而有些興奮。大概是因為沒有發論文的壓力吧，加上先前讀過費曼的言論，覺得這是理所當然的情況，我們知道得本來就很少，想法通常也是錯的。然而，重點在於如何從錯誤的嘗試中學習？

昨天晚上不斷思索這堆錯誤的嘗試告訴我什麼，仍未有定論。忽然想到愛迪生的話，當他實驗千種材料失敗後，他說，至少我明白這千種材料不能作為燈炮的材料。
於是心裡又更踏實了。但這不表示可以隨意的嘗試，在沒有有效的驗證方式之前，無謂的嘗試無法提供任何訊息。
印象中費曼提過，他不和人討論無法驗證的想法，那是沒有意義的行為。提出猜想後，我會思考如何驗證。直到有辦法進行驗證前，我會先保留想法，改試別的作法。或是將原問題先拆成幾個小問題，讓小問題能夠被驗證。待各個擊破搜集到一些資訊後，再回頭看是否能驗證原本的想法。
能夠驗證的想法，才能從中學習。不然結果出來後，我們無從判斷結果有多接近目標，自然也無法從中學習，進而做修正。舉例來說，如果要做 AI 下棋的搜尋，要怎麼知道目前的策略有效？和人下棋是個辦法，可是沒有無法頻覆進行，也就不能確保方法的可靠程度。另一方面，光看評估盤面函式的輸出值也無用，沒法確認分數高確實是有利的盤面。
換個想法，提兩個策略，互相對戰。至少可以確定每次都贏的策略，是相對來說較好的策略。一個策略可以用 greedy algorithm，另一個用自己想的特別方式。雖然我們預期特別的方法會贏，但若結果相反，也能從中明白新東西：像是 greedy algorithm 比想像中的有效，可從中找到好點子；或是特別的方法不如預期地有效，也就不用再和人下棋，減少後續測試的成本。若擔心兩個方法自動對戰變化有限，可以引用不同棋譜的中盤局面，再引入兩個方法擔任不同角色，觀察好的方法是否在各種相同局面裡，無論擔任那一方，都能下得較好。
再舉解魔術方塊的例子。為了能夠驗證，可以先將解好的盤面一步步弄亂，記下正確的還原步驟和所需步數。準備好多組測試盤面（即最後弄亂的樣子），測試演算法解的效果，步數和預期步數相差多少？那一步發展變得不同？於是有確實的數據可以分析，明白問題出在那。有未知的大進步時（只花了預期的一半步數），也方便觀察出原因（如弄亂盤面時做了不當的重覆操作），不會不小心高估方法的成效。
看起來理所當然的事，沒想到我這麼遲才明白，驗證是如此的重要。而這個觀點卻是從 coding 那邊先萌芽，才接著在研究這邊確實實行。不論是研究還是coding，我認為重要性是: 需求 (動機) > 驗證 > 想法 (解法) > 實作。如《管理是什麼》書裡提到，管理即為客戶創造價值 －－ [...]]]></summary>
		<content type="html" xml:base="http://fcamel.twbbs.org/archives/2009/09/05/898/">&lt;p&gt;看到這篇&lt;a href="http://www.codinghorror.com/blog/archives/001297.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.codinghorror.com');"&gt;《The Only Truly Failed Project》&lt;/a&gt;，其中有兩段話寫得很棒：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Failure is a wonderful teacher. But there&amp;#8217;s no need to seek out failure. It will find you.&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;&lt;p&gt;The only truly failed project is the one where you didn&amp;#8217;t learn anything along the way.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;最近觀察不少數據和實驗結果，推翻之前許多猜想，不過我沒有像碩士做研究時那般痛苦，反而有些興奮。大概是因為沒有發論文的壓力吧，加上先前讀過費曼的言論，覺得這是理所當然的情況，我們知道得本來就很少，想法通常也是錯的。然而，重點在於如何從錯誤的嘗試中學習？&lt;/p&gt;
&lt;p&gt;&lt;span id="more-898"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;昨天晚上不斷思索這堆錯誤的嘗試告訴我什麼，仍未有定論。忽然想到愛迪生的話，當他實驗千種材料失敗後，他說，至少我明白這千種材料不能作為燈炮的材料。&lt;br /&gt;
於是心裡又更踏實了。但這不表示可以隨意的嘗試，在沒有有效的驗證方式之前，無謂的嘗試無法提供任何訊息。&lt;/p&gt;
&lt;p&gt;印象中費曼提過，他不和人討論無法驗證的想法，那是沒有意義的行為。提出猜想後，我會思考如何驗證。直到有辦法進行驗證前，我會先保留想法，改試別的作法。或是將原問題先拆成幾個小問題，讓小問題能夠被驗證。待各個擊破搜集到一些資訊後，再回頭看是否能驗證原本的想法。&lt;/p&gt;
&lt;p&gt;能夠驗證的想法，才能從中學習。不然結果出來後，我們無從判斷結果有多接近目標，自然也無法從中學習，進而做修正。舉例來說，如果要做 AI 下棋的搜尋，要怎麼知道目前的策略有效？和人下棋是個辦法，可是沒有無法頻覆進行，也就不能確保方法的可靠程度。另一方面，光看評估盤面函式的輸出值也無用，沒法確認分數高確實是有利的盤面。&lt;/p&gt;
&lt;p&gt;換個想法，提兩個策略，互相對戰。至少可以確定每次都贏的策略，是相對來說較好的策略。一個策略可以用 greedy algorithm，另一個用自己想的特別方式。雖然我們預期特別的方法會贏，但若結果相反，也能從中明白新東西：像是 greedy algorithm 比想像中的有效，可從中找到好點子；或是特別的方法不如預期地有效，也就不用再和人下棋，減少後續測試的成本。若擔心兩個方法自動對戰變化有限，可以引用不同棋譜的中盤局面，再引入兩個方法擔任不同角色，觀察好的方法是否在各種相同局面裡，無論擔任那一方，都能下得較好。&lt;/p&gt;
&lt;p&gt;再舉解魔術方塊的例子。為了能夠驗證，可以先將解好的盤面一步步弄亂，記下正確的還原步驟和所需步數。準備好多組測試盤面（即最後弄亂的樣子），測試演算法解的效果，步數和預期步數相差多少？那一步發展變得不同？於是有確實的數據可以分析，明白問題出在那。有未知的大進步時（只花了預期的一半步數），也方便觀察出原因（如弄亂盤面時做了不當的重覆操作），不會不小心高估方法的成效。&lt;/p&gt;
&lt;p&gt;看起來理所當然的事，沒想到我這麼遲才明白，驗證是如此的重要。而這個觀點卻是&lt;a href="/archives/2009/06/13/849/"&gt;從 coding 那邊先萌芽&lt;/a&gt;，才接著在研究這邊確實實行。不論是研究還是coding，我認為重要性是: 需求 (動機) &gt; 驗證 &gt; 想法 (解法) &gt; 實作。如《管理是什麼》書裡提到，管理即為客戶創造價值 －－ 相當含糊的定義，可是卻非常精闢。不論是研究還是寫程式，也要先確保能滿足某種需求，之後的發展才有意義。接著，在天馬行空地想解法前，先確保有方法驗證方法的好壞、達到目標的程度、有辦法分析結果，之後才能確實地落實想法。於是，即使失敗仍能有所收獲。&lt;/p&gt;
&lt;h4&gt;2009-09-06 Update&lt;/h4&gt;
&lt;p&gt;經 &lt;a href="http://www.plurk.com/LCamel" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.plurk.com');"&gt;LCamel&lt;/a&gt; 一提，發現英文的用詞很有趣，&lt;a href="http://en.wikipedia.org/wiki/Verification_and_Validation" onclick="javascript:pageTracker._trackPageview('/outbound/article/en.wikipedia.org');"&gt;Verification and Validation &lt;/a&gt; 裡這麼解釋：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;
It is sometimes said that validation can be expressed by the query &amp;#8220;Are you building the right thing?&amp;#8221; and verification by &amp;#8220;Are you building the thing right?&amp;#8221; &amp;#8220;Building the right thing&amp;#8221; refers back to the user&amp;#8217;s needs, while &amp;#8220;building it right&amp;#8221; checks that the specifications be correctly implemented by the system.
&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;意即：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;滿足需求 = validation = do the right thing.&lt;/li&gt;
&lt;li&gt;驗證作法 = verification = do the thing right.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;語言真是奇妙啊，用一句話來總結，就是「Are the do you right thing right?」&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/fcamel/~4/XSpnjRZb9ck" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://fcamel.twbbs.org/archives/2009/09/05/898/#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://fcamel.twbbs.org/archives/2009/09/05/898/feed/atom/" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://fcamel.twbbs.org/archives/2009/09/05/898/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>fcamel</name>
					</author>
		<title type="html"><![CDATA[《別鬧了，費曼先生》閱讀中的雜記]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/fcamel/~3/jmy35yxZ9jQ/" />
		<id>http://fcamel.twbbs.org/?p=889</id>
		<updated>2009-08-10T16:44:16Z</updated>
		<published>2009-08-10T15:37:56Z</published>
		<category scheme="http://fcamel.twbbs.org" term="All" /><category scheme="http://fcamel.twbbs.org" term="Blog" /><category scheme="http://fcamel.twbbs.org" term="Book" /><category scheme="http://fcamel.twbbs.org" term="Diary" /><category scheme="http://fcamel.twbbs.org" term="Research" /><category scheme="http://fcamel.twbbs.org" term="Web" /><category scheme="http://fcamel.twbbs.org" term="閒書" />		<summary type="html"><![CDATA[讀《別鬧了，費曼先生》的過程裡，偶而有寫片段感想。這篇是這些短記整理後的記錄。

通用的學習法則
《別鬧了，費曼先生》提到費曼常跨領域學些不同東西，不管是哲學、數學、生物學，費曼都用他學習科學的習慣判別對錯，掌握基本原理。最近做研究也有這種體會。即使沒有背景知識，有良好邏輯，掌握假設和觀察結果，通常能做出正確的判斷。前提是我們能明確判讀那些是客觀事實，那些是主觀判斷，數據不會騙人，可是人會，而且我們自己也可能會騙自己。
舉例來說，看到別人的實驗結果和實驗報告，一定要自己讀一遍數據，不然無法判斷別人說明中那些部份為主觀推測。像是兩個方法有效程度差了千分之一，是否可說有顯著差異？去除人有私心的因素外，我們也沒有想像中的聰明，容易將一些相似的資訊混在一起，不知不覺認定是事實。「誤把有相關性視為有因果關係」是常見的例子，有興趣的人可以看些寫給大眾看的統計書籍。反用「判讀個人觀點和事實」的原則在自己身上也很有效，可以找到自己思路的盲點，不會過於武斷主張自己的看法。
此外，舉例說明是最佳的討論方式。費曼提到他和數學家討論數學原理時，他的判斷方式是心中想像一些實例，對方描述問題時，他就想像心裡那些物體會怎麼變化，於是當對方說某某性質如何，他發覺在他想像世界裡有矛盾時，就能做出辯駁。另一方面，我相信只有當我們能舉例說明時，我們才算真的明白，藉由逼自己舉例，可以思考的更靈活，找出忽略的細節。
別死記名詞
另一方面，費曼也指出許多人記了一堆名詞，卻沒掌握基本精神，他在 MIT 的大學同學如此，愛因斯坦的研究助理也會犯這種錯。費曼一再提到很多學生只會背名詞，不會理解背後的含意，不明白他們在學什麼。這種精神從他小時候就存在，和父親在林中散步時，費曼的父親向他解釋生物行為而不背名字，費曼將自己的成就歸功於父親童年時的教導，不無道理。
費曼在問學生問題時，會舉例討論，而不問教科書式的問題。我在確認別人能力時也是這麼做，不問專有名詞解釋（像是請說明 X 演算法為何），盡量用應用題直接看對方怎麼運用知識，這樣能立即明白對方有沒有理解背後含意。反過來看，不知道某些名詞不代表什麼，就算對方不知道 Dijkstra&#8217;s Algorithm，但若能提出相似的解法，反而更高明。只要和對方說明這些知識，他們立即能掌握精神加以運用。反之，知道 Dijkstra&#8217;s Algorithm 卻無法活用，知道更多演算法、累積更多經驗，成長也有限。
名詞只是方便溝通的工具，若不能理解背後的含意，光記許多名詞毫無意義。在資訊爆炸的時代，每天產生一堆新的名詞，吸收這堆雜亂的詞彙時，得時時提醒自己，是否明白背後含意。以前我曾落入背誦知識為樂的陷阱，後來發現知道很多皮毛卻無法做進一步運用，才驚覺自己浪費不少時間。舉例來說，現在當紅的 Android，即使我知道 Android 是 Google 發佈的手機平台，也沒任何幫助，只是一堆名詞堆砌。到不如了解為何會有 Android？適合解什麼樣的問題？需要時可視需求對相關知識做進一步研究。 (備註：我並不了解這兩個問題，只是舉例而已。）
並不是說記名詞毫無意義，費曼童年時自己發明一套數學符號，他覺得讀起來比較好理解，很高興地用了一陣子。但後來發現他無法和人溝通，就把這些符號丟了，改用共通符號。與人溝通需要專有名詞，不然難以進入問題核心，講半天還在說「你是說如果有 n 個點，點可以是任意東西，像是城市，或想像成座標也行，這 n 個點之中部份兩點有互相連接，連接的距離長短不一，而你想從某個起點 A 走到終點 B，想問如何走才能花最少的步數嗎？」（即最短路徑問題）。
]]></summary>
		<content type="html" xml:base="http://fcamel.twbbs.org/archives/2009/08/10/889/">&lt;p&gt;讀《別鬧了，費曼先生》的過程裡，偶而有寫片段感想。這篇是這些短記整理後的記錄。&lt;/p&gt;
&lt;p&gt;&lt;span id="more-889"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4&gt;通用的學習法則&lt;/h4&gt;
&lt;p&gt;《別鬧了，費曼先生》提到費曼常跨領域學些不同東西，不管是哲學、數學、生物學，費曼都用他學習科學的習慣判別對錯，掌握基本原理。最近做研究也有這種體會。即使沒有背景知識，有良好邏輯，掌握假設和觀察結果，通常能做出正確的判斷。前提是我們能明確判讀那些是客觀事實，那些是主觀判斷，數據不會騙人，可是人會，而且我們自己也可能會騙自己。&lt;/p&gt;
&lt;p&gt;舉例來說，看到別人的實驗結果和實驗報告，一定要自己讀一遍數據，不然無法判斷別人說明中那些部份為主觀推測。像是兩個方法有效程度差了千分之一，是否可說有顯著差異？去除人有私心的因素外，我們也沒有想像中的聰明，容易將一些相似的資訊混在一起，不知不覺認定是事實。「誤把有相關性視為有因果關係」是常見的例子，有興趣的人可以看些寫給大眾看的統計書籍。反用「判讀個人觀點和事實」的原則在自己身上也很有效，可以找到自己思路的盲點，不會過於武斷主張自己的看法。&lt;/p&gt;
&lt;p&gt;此外，舉例說明是最佳的討論方式。費曼提到他和數學家討論數學原理時，他的判斷方式是心中想像一些實例，對方描述問題時，他就想像心裡那些物體會怎麼變化，於是當對方說某某性質如何，他發覺在他想像世界裡有矛盾時，就能做出辯駁。另一方面，我相信只有當我們能舉例說明時，我們才算真的明白，藉由逼自己舉例，可以思考的更靈活，找出忽略的細節。&lt;/p&gt;
&lt;h4&gt;別死記名詞&lt;/h4&gt;
&lt;p&gt;另一方面，費曼也指出許多人記了一堆名詞，卻沒掌握基本精神，他在 MIT 的大學同學如此，愛因斯坦的研究助理也會犯這種錯。費曼一再提到很多學生只會背名詞，不會理解背後的含意，不明白他們在學什麼。這種精神從他小時候就存在，和父親在林中散步時，費曼的父親向他解釋生物行為而不背名字，費曼將自己的成就歸功於父親童年時的教導，不無道理。&lt;/p&gt;
&lt;p&gt;費曼在問學生問題時，會舉例討論，而不問教科書式的問題。我在確認別人能力時也是這麼做，不問專有名詞解釋（像是請說明 X 演算法為何），盡量用應用題直接看對方怎麼運用知識，這樣能立即明白對方有沒有理解背後含意。反過來看，不知道某些名詞不代表什麼，就算對方不知道 Dijkstra&amp;#8217;s Algorithm，但若能提出相似的解法，反而更高明。只要和對方說明這些知識，他們立即能掌握精神加以運用。反之，知道 Dijkstra&amp;#8217;s Algorithm 卻無法活用，知道更多演算法、累積更多經驗，成長也有限。&lt;/p&gt;
&lt;p&gt;名詞只是方便溝通的工具，若不能理解背後的含意，光記許多名詞毫無意義。在資訊爆炸的時代，每天產生一堆新的名詞，吸收這堆雜亂的詞彙時，得時時提醒自己，是否明白背後含意。以前我曾落入背誦知識為樂的陷阱，後來發現知道很多皮毛卻無法做進一步運用，才驚覺自己浪費不少時間。舉例來說，現在當紅的 Android，即使我知道 Android 是 Google 發佈的手機平台，也沒任何幫助，只是一堆名詞堆砌。到不如了解為何會有 Android？適合解什麼樣的問題？需要時可視需求對相關知識做進一步研究。 (備註：我並不了解這兩個問題，只是舉例而已。）&lt;/p&gt;
&lt;p&gt;並不是說記名詞毫無意義，費曼童年時自己發明一套數學符號，他覺得讀起來比較好理解，很高興地用了一陣子。但後來發現他無法和人溝通，就把這些符號丟了，改用共通符號。與人溝通需要專有名詞，不然難以進入問題核心，講半天還在說「你是說如果有 n 個點，點可以是任意東西，像是城市，或想像成座標也行，這 n 個點之中部份兩點有互相連接，連接的距離長短不一，而你想從某個起點 A 走到終點 B，想問如何走才能花最少的步數嗎？」（即最短路徑問題）。&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/fcamel/~4/jmy35yxZ9jQ" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://fcamel.twbbs.org/archives/2009/08/10/889/#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://fcamel.twbbs.org/archives/2009/08/10/889/feed/atom/" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://fcamel.twbbs.org/archives/2009/08/10/889/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>fcamel</name>
					</author>
		<title type="html"><![CDATA[《別鬧了，費曼先生》讀後感 －－ 關於科學的品德]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/fcamel/~3/_Ej9jEUjB-Q/" />
		<id>http://fcamel.twbbs.org/archives/2009/08/05/882/</id>
		<updated>2009-10-30T14:57:54Z</updated>
		<published>2009-08-05T12:39:22Z</published>
		<category scheme="http://fcamel.twbbs.org" term="All" /><category scheme="http://fcamel.twbbs.org" term="Book" /><category scheme="http://fcamel.twbbs.org" term="Research" /><category scheme="http://fcamel.twbbs.org" term="閒書" />		<summary type="html"><![CDATA[小時候曾讀過一次，當時只覺得費曼這人真有趣。走過一遭研究的生活後，再回來讀這本書，幾乎每部份都令我深思許久。特別是最後一篇《草包族科學》讓我有更深的體會。

這篇是費曼於1974年在加州理工學院的畢業典禮演講，有別於其它故事，單刀直入說明科學研究最重要的課題－－科學的品德，也就是對自己誠實，對大眾誠實。費曼舉了個反例說明何謂不誠實：

有個朋友在上電台節目之前跟我聊起來，他是研究宇宙學及天文學的，而他很感困惑，不知該如何談論這些工作的應用。我說：「根本就沒有應用可言。」，他回答說：「沒錯，但如果這麼說，我們這類研究工作就更不受支持了。」我覺得很意外，我想那是一種不誠實。如果你以科學家的姿態出現，那麼你應該向所有非科學家的大眾說明你的工作－－如果他們不願意支持你的研究，那是他們的決定。

自己做研究也是一樣，該同時說明支持和不支持的數據和觀點，而非只報告支持的部份。要延伸別人的研究前，要先重製對方的實驗，如此才知道兩者在自己的實驗環境下差多少，而不能為了急著產生報告，省略前人的實驗，直接做自己的部份。
做研究必須客觀，早就同意某種觀點而開始做實驗，和從實驗中找出支持自己觀點的證據，是截然不同的行為。在利益衝突下，我們很容易欺騙自己，得非常非常細心且耐心地排除任何有利於自己發展的想法。很多時候我們難以把持，或是不自覺地騙了自己。舉例來說，看到違反預期 (不利) 的結果，會不斷思考那個環節有誤，嘗試修正「不當變因」；看到符合預期 (有利) 的結果卻會很興奮，忘了要進一步確保沒有「不當變因」影響結果。
藉由費曼生活中的插曲，看到一位真正科學家自然行事的風格，令我受益良多。在看到這麼多令人困惑的情況後，費曼的身教無疑是個強心劑。我想我不會再困惑了，若有那麼一天我打算讀博士，除了找到非作不可的研究外，還要確定我能把持住想法，能完全地誠實才會成行。不然，我還是遠離利害關係，至少在沒有利害關係的影響下，我能較誠實地進行研究。
費曼演講的最後一段如此說道：

因此我只有一個希望：你們能夠找到一個地方，在那裡自由自在的堅持我提到過的品德；而且不會由於要維持你在組織裡的地位，或是迫於經濟壓力，而喪失你的品德。
我誠心祝福，你們能獲得這樣的自由。
So I have just one wish for you—the good luck to be somewhere where you are free to maintain the kind of integrity I have described, and where you do not feel forced by a need to maintain your position in the organization, or financial support, or so on, to lose [...]]]></summary>
		<content type="html" xml:base="http://fcamel.twbbs.org/archives/2009/08/05/882/">&lt;p&gt;小時候曾讀過一次，當時只覺得費曼這人真有趣。走過一遭研究的生活後，再回來讀這本書，幾乎每部份都令我深思許久。特別是最後一篇《草包族科學》讓我有更深的體會。&lt;/p&gt;
&lt;p&gt;&lt;span id="more-882"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;這篇是費曼於1974年在加州理工學院的畢業典禮演講，有別於其它故事，單刀直入說明科學研究最重要的課題－－科學的品德，也就是對自己誠實，對大眾誠實。費曼舉了個反例說明何謂不誠實：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;
有個朋友在上電台節目之前跟我聊起來，他是研究宇宙學及天文學的，而他很感困惑，不知該如何談論這些工作的應用。我說：「根本就沒有應用可言。」，他回答說：「沒錯，但如果這麼說，我們這類研究工作就更不受支持了。」我覺得很意外，我想那是一種不誠實。如果你以科學家的姿態出現，那麼你應該向所有非科學家的大眾說明你的工作－－如果他們不願意支持你的研究，那是他們的決定。
&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;自己做研究也是一樣，該同時說明支持和不支持的數據和觀點，而非只報告支持的部份。要延伸別人的研究前，要先重製對方的實驗，如此才知道兩者在自己的實驗環境下差多少，而不能為了急著產生報告，省略前人的實驗，直接做自己的部份。&lt;/p&gt;
&lt;p&gt;做研究必須客觀，早就同意某種觀點而開始做實驗，和從實驗中找出支持自己觀點的證據，是截然不同的行為。在利益衝突下，我們很容易欺騙自己，得非常非常細心且耐心地排除任何有利於自己發展的想法。很多時候我們難以把持，或是不自覺地騙了自己。舉例來說，看到違反預期 (不利) 的結果，會不斷思考那個環節有誤，嘗試修正「不當變因」；看到符合預期 (有利) 的結果卻會很興奮，忘了要進一步確保沒有「不當變因」影響結果。&lt;/p&gt;
&lt;p&gt;藉由費曼生活中的插曲，看到一位真正科學家自然行事的風格，令我受益良多。在看到這麼多令人困惑的情況後，費曼的身教無疑是個強心劑。我想我不會再困惑了，若有那麼一天我打算讀博士，除了找到非作不可的研究外，還要確定我能把持住想法，能完全地誠實才會成行。不然，我還是遠離利害關係，至少在沒有利害關係的影響下，我能較誠實地進行研究。&lt;/p&gt;
&lt;p&gt;費曼演講的最後一段如此說道：&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;
因此我只有一個希望：你們能夠找到一個地方，在那裡自由自在的堅持我提到過的品德；而且不會由於要維持你在組織裡的地位，或是迫於經濟壓力，而喪失你的品德。&lt;/p&gt;
&lt;p&gt;我誠心祝福，你們能獲得這樣的自由。&lt;/p&gt;
&lt;p&gt;So I have just one wish for you—the good luck to be somewhere where you are free to maintain the kind of integrity I have described, and where you do not feel forced by a need to maintain your position in the organization, or financial support, or so on, to lose your integrity. May you have that freedom.
&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;看到這段話，我鼻頭都酸了，祝福自己，也祝福所有對科學有興趣的人。&lt;/p&gt;
&lt;p&gt;ps. 英文原文講稿&lt;a href="http://yost.com/misc/cargocult.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/yost.com');"&gt;在此&lt;/a&gt;。&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/fcamel/~4/_Ej9jEUjB-Q" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://fcamel.twbbs.org/archives/2009/08/05/882/#comments" thr:count="4" />
		<link rel="replies" type="application/atom+xml" href="http://fcamel.twbbs.org/archives/2009/08/05/882/feed/atom/" thr:count="4" />
		<thr:total>4</thr:total>
	<feedburner:origLink>http://fcamel.twbbs.org/archives/2009/08/05/882/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>fcamel</name>
					</author>
		<title type="html"><![CDATA[學而不思則罔，思而不學則殆]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/fcamel/~3/DE53ys3mBIg/" />
		<id>http://fcamel.twbbs.org/archives/2009/07/25/878/</id>
		<updated>2009-07-25T13:05:02Z</updated>
		<published>2009-07-25T12:59:15Z</published>
		<category scheme="http://fcamel.twbbs.org" term="All" /><category scheme="http://fcamel.twbbs.org" term="Life" /><category scheme="http://fcamel.twbbs.org" term="格言錦句" />		<summary type="html"><![CDATA[現在回顧兩年前思考未來出路的文章，覺得孔子說的「學而不思則罔，思而不學則殆。」真是太有道理了。再多規劃，聽再多情報，若沒有親身體驗，只會對紛亂的情報感到困惑。

現在回頭比對當時搜集的情報和現在知道的情報，發現有許多出入，甚至連對自己的認知都有誤。一開始我不知道自己喜歡做研究還是做產品。結果經過四個月全心投入研究後，覺得做研究滿有趣的，和正在業界的學長聊天，覺得自己似乎沒那麼適合當工程師。結果去一家公司實習四個月後，又覺得自己比較喜歡做產品。現在做了半年半研究半產品的工作，又覺得好像都很有趣。到頭來是看目標是否明確有意義、組織是否能給我彈性的空間發展，以及不需要為了衝積效而做無意義的事。那麼，不論是研究還是產品，都能從中找到樂趣。若用負面例子來看，寫不踏實的學術報告，和做難用的產品，都一樣乏味。
需求不明確，情報又不見得正確，怎麼能做出有效的決定？
所以，若碩士畢業生沒有先到業界實習過，不清楚自己的喜好，聽再多情報也難以判斷。另外，若不是和公司內的人直接一對一聊，情報價值也難以判斷。和一家公司內的一個人聊，也只能了解該組詳細情況和公司概況，容易以偏概全。就像好學校有壞實驗室，壞學校會有好實驗室一樣，和自身最相近的案例才有幫助。
類似的例子俯拾皆是，像是高中生選大學，若自身沒有針對有興趣的科系先嘗試一下，和他說明學校科系的特色，也難以定奪。若用系統來解釋，沒有寫過系統程式直接讀作業系統的書，只會覺得抽象得令人不知所云。寫一堆系統程式不看書消化整理知識，需求稍微變更，又不知該如何有效處理。
學技術時我明白孔子這兩句話的意思，但在人生方向的課題裡，我卻到現在才明白：原來我沒搞懂。話說回來，接觸新領域時，總會想省時間偷吃步，不做基礎練習，看來在技術方面，我也沒明白這兩句話的重要性。
]]></summary>
		<content type="html" xml:base="http://fcamel.twbbs.org/archives/2009/07/25/878/">&lt;p&gt;現在回顧兩年前思考未來出路的文章，覺得孔子說的「學而不思則罔，思而不學則殆。」真是太有道理了。再多規劃，聽再多情報，若沒有親身體驗，只會對紛亂的情報感到困惑。&lt;/p&gt;
&lt;p&gt;&lt;span id="more-878"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;現在回頭比對當時搜集的情報和現在知道的情報，發現有許多出入，甚至連對自己的認知都有誤。一開始我不知道自己喜歡做研究還是做產品。結果經過四個月全心投入研究後，覺得做研究滿有趣的，和正在業界的學長聊天，覺得自己似乎沒那麼適合當工程師。結果去一家公司實習四個月後，又覺得自己比較喜歡做產品。現在做了半年半研究半產品的工作，又覺得好像都很有趣。到頭來是看目標是否明確有意義、組織是否能給我彈性的空間發展，以及不需要為了衝積效而做無意義的事。那麼，不論是研究還是產品，都能從中找到樂趣。若用負面例子來看，寫不踏實的學術報告，和做難用的產品，都一樣乏味。&lt;/p&gt;
&lt;p&gt;需求不明確，情報又不見得正確，怎麼能做出有效的決定？&lt;/p&gt;
&lt;p&gt;所以，若碩士畢業生沒有先到業界實習過，不清楚自己的喜好，聽再多情報也難以判斷。另外，若不是和公司內的人直接一對一聊，情報價值也難以判斷。和一家公司內的一個人聊，也只能了解該組詳細情況和公司概況，容易以偏概全。就像好學校有壞實驗室，壞學校會有好實驗室一樣，和自身最相近的案例才有幫助。&lt;/p&gt;
&lt;p&gt;類似的例子俯拾皆是，像是高中生選大學，若自身沒有針對有興趣的科系先嘗試一下，和他說明學校科系的特色，也難以定奪。若用系統來解釋，沒有寫過系統程式直接讀作業系統的書，只會覺得抽象得令人不知所云。寫一堆系統程式不看書消化整理知識，需求稍微變更，又不知該如何有效處理。&lt;/p&gt;
&lt;p&gt;學技術時我明白孔子這兩句話的意思，但在人生方向的課題裡，我卻到現在才明白：原來我沒搞懂。話說回來，接觸新領域時，總會想省時間偷吃步，不做基礎練習，看來在技術方面，我也沒明白這兩句話的重要性。&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/fcamel/~4/DE53ys3mBIg" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://fcamel.twbbs.org/archives/2009/07/25/878/#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://fcamel.twbbs.org/archives/2009/07/25/878/feed/atom/" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://fcamel.twbbs.org/archives/2009/07/25/878/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>fcamel</name>
					</author>
		<title type="html"><![CDATA[學程式語言的樂趣]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/fcamel/~3/awxdbIYx4io/" />
		<id>http://fcamel.twbbs.org/archives/2009/07/22/859/</id>
		<updated>2009-07-23T11:41:24Z</updated>
		<published>2009-07-22T14:42:27Z</published>
		<category scheme="http://fcamel.twbbs.org" term="All" /><category scheme="http://fcamel.twbbs.org" term="Java" /><category scheme="http://fcamel.twbbs.org" term="Programming" /><category scheme="http://fcamel.twbbs.org" term="Python" /><category scheme="http://fcamel.twbbs.org" term="Ruby" />		<summary type="html"><![CDATA[國三時為了做北市數學科展，實習老師教我使用 Microsoft Word，這是我首次體會到電腦在遊戲之外的樂趣。為了學會怎麼灌 Windows，高一時參加了社團，結果社團學長 Scott 說:「灌 Windows 太簡單了，你來學 C 吧。不過我們這裡只有 Red Hat Linux，就邊學 C 邊學 Linux 吧。」傻傻的我，以為 Linux 裡只有 Vi，就四處翻 Linux 入門書，看完各本書裡 Vi 部份，還寫了篇 Vi 的教學。日漸熟悉 Vi、bash 指令後，覺得玩系統、寫程式真有趣。於是上課無聊就偷看電腦書，下課耍自閉繼續看書，中午放學都跑去社團混，就這樣渡過我的高一。不知不覺，我打下日後學習能力最重要的基礎。

高一一時想不開，同時學 C 和 Perl，用 Perl 寫東西頗有趣的，特別是費盡心思把程式擠到一行作完一件煩人的小工作時，有說不出來的成就感。可是我基礎太弱，無法明白兩者更深層的差異，只能當作兩個不同工具看。兩者同時學的下場，學一陣子仍不熟兩邊的語法。於是我先專心學 C，之後 Perl 也忘光了。那段日子最大的收獲是，不要一次同時學兩個語言。另外，多虧 Scott 心理不正常，用 K&#038;R 的《C 程式語言》當入門書，我直接學會標準語法，和 C 的典型寫法。這個習慣一直伴隨我到現在，每學一個新語言時，我傾向直接找能教我典型寫法的書，省去先花時間學一堆語法，再去蕪存菁地寫出典型風格。
寫了三年的 C，大一接觸到 Java 後，覺得 OOP 很有趣，這麼簡單又優雅地，讓我能同時使用兩個 Stack！雖然一開始寫著滿滿的 C-like Java，程式裡都是 static method，看了些 OOP 的書，開始轉型寫著自以為是 [...]]]></summary>
		<content type="html" xml:base="http://fcamel.twbbs.org/archives/2009/07/22/859/">&lt;p&gt;國三時為了做北市數學科展，實習老師教我使用 Microsoft Word，這是我首次體會到電腦在遊戲之外的樂趣。為了學會怎麼灌 Windows，高一時參加了社團，結果社團學長 Scott 說:「灌 Windows 太簡單了，你來學 C 吧。不過我們這裡只有 Red Hat Linux，就邊學 C 邊學 Linux 吧。」傻傻的我，以為 Linux 裡只有 Vi，就四處翻 Linux 入門書，看完各本書裡 Vi 部份，還寫了篇 Vi 的教學。日漸熟悉 Vi、bash 指令後，覺得玩系統、寫程式真有趣。於是上課無聊就偷看電腦書，下課耍自閉繼續看書，中午放學都跑去社團混，就這樣渡過我的高一。不知不覺，我打下日後學習能力最重要的基礎。&lt;/p&gt;
&lt;p&gt;&lt;span id="more-859"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;高一一時想不開，同時學 C 和 Perl，用 Perl 寫東西頗有趣的，特別是費盡心思把程式擠到一行作完一件煩人的小工作時，有說不出來的成就感。可是我基礎太弱，無法明白兩者更深層的差異，只能當作兩個不同工具看。兩者同時學的下場，學一陣子仍不熟兩邊的語法。於是我先專心學 C，之後 Perl 也忘光了。那段日子最大的收獲是，不要一次同時學兩個語言。另外，多虧 Scott 心理不正常，用 K&amp;#038;R 的《C 程式語言》當入門書，我直接學會標準語法，和 C 的典型寫法。這個習慣一直伴隨我到現在，每學一個新語言時，我傾向直接找能教我典型寫法的書，省去先花時間學一堆語法，再去蕪存菁地寫出典型風格。&lt;/p&gt;
&lt;p&gt;寫了三年的 C，大一接觸到 Java 後，覺得 OOP 很有趣，這麼簡單又優雅地，讓我能同時使用兩個 Stack！雖然一開始寫著滿滿的 C-like Java，程式裡都是 static method，看了些 OOP 的書，開始轉型寫著自以為是 OOP 的怪東西。時至今日，我仍然不明白要怎麼寫出真正的 OOP。至少我發現自己寫得不是 OOP，和大學時相比，算是進步不少。&lt;/p&gt;
&lt;p&gt;有些課要求用 C++，我就會用 Java 學到的 OOP 觀念和 C 的經驗來寫。每次要寫 C++ 就重翻一下 C++ 快速入門的書，寫完後又忘光一切。大三做專題時，我和朋友們打算參加一個國外的比賽，由於主要贊助商是 Microsoft，我們決定用 .NET Framework 開發。就這樣，我有個好機會寫 C#。亂翻一些 ASP.NET 的書把殼刻一刻後，我找了《C# Essentials》來看。這本書如其名，薄又都是重點，很快地明白 C# 的特色，讓我覺得 C# 挺漂亮的。不過寫完專題後沒繼續寫 C#，現在什麼也不記得了。而且，當時我的底不夠深，仍無法感受到各語言的特色。&lt;/p&gt;
&lt;p&gt;除 C++、C# 兩個插曲外，大學時主要用 Java 和 PHP。用途很簡單，接網站案子用 PHP，其它用 Java。我練習 PHP 的方式是不斷改寫自己的網站，還有接些小案子，可是我覺得 PHP 實在不怎麼美，沒動力學好它，能用就好。&lt;/p&gt;
&lt;p&gt;大學中途有試著寫了一點 Python、Scheme，可惜無法持續。一直到碩一一時興起，一方面是厭煩了用 PHP 寫重覆的東西，另一方面想試看看當紅的 Ruby on Rails，就邊查邊寫完成一個小案子。寫得過程裡，覺得 Ruby 很奇妙，於是在寒假花了一週讀完《Programming Ruby》第一部份，這才正式開始我學的第三個語言。&lt;/p&gt;
&lt;p&gt;自那之後，我只有寫 Ruby，Java、PHP和其它語言碰也沒碰，這樣直到碩士畢業。沒錯，我的碩士論文也是用 Ruby 寫的，這才深深體會到 Ruby 有多慢有多肥，幸好實驗室的機器很壯，不然我得改用 Java 完成碩論。這段期間，把一個論文裡用到的程式零零總總地加起來，大概有兩千多行，也驚覺 Ruby 幫我省了不少寫程式的時間，相信用 Java 的話，我無法在不到一個月的時間裡寫完自己的演算法、數個比較對象的演算法、前置處理、評估分數等程式。不過卻辛苦交接的學妹，這樣瘋狂用一個不熟語言趕出來的程式碼，原以為不會繼續用的說。&lt;/p&gt;
&lt;p&gt;用 Ruby 讓我有了第二次衝擊，就像當年從 C 到 Java 發現可以同時有兩個 Stack 那般驚奇，沒想到 iterator、code block 這麼好用，腦裡想什麼，手就可以直接敲出來，不用寫一寫還要把游標移來移去。而且，Ruby 可以寫出很短又好讀的程式，我從來沒想過程式可以寫到這麼精簡，而寫到這麼精簡後，又更容易理解。&lt;/p&gt;
&lt;p&gt;碩士畢業去一家公司實習時，該公司不用 Ruby，我藉機來試看看 Python。於是，對照先前一年多寫 Ruby 的經驗，我明白很多事。有時選擇某個語言，沒有什麼明確的理性依據，單純是個人偏好。高中時我一直想知道 Python 和 Perl 的差異，到底學那個比較划算，如今又多了一個 Ruby 列入抗爭。現在來看，即使我可以找到三者在語言設計、執行速度、社群、函式庫、上手度等各方面的比較，到頭來，選擇何者反而像是信仰。&lt;/p&gt;
&lt;p&gt;附帶一提，若要推廣一個程式語言，良好的互動直譯器、快速隨手查的文件、精簡易讀的入門書，三者缺一不可。 Ruby 大概就互動直譯器弱了一些，而 Python 三者都完美無缺，非常容易上手。至於 Java，即使到現在，我仍不知道要推薦別人看什麼書入門。最後附上我對各語言入門方式的看法，入門書書單是針對已學過一種語言的人：&lt;/p&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;tr&gt;
&lt;th&gt;語言&lt;/th&gt;
&lt;th&gt;互動式直譯器&lt;/th&gt;
&lt;th&gt;隨手查的文件&lt;/th&gt;
&lt;th&gt;入門書&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;C&lt;/th&gt;
&lt;td&gt;無&lt;/td&gt;
&lt;td&gt;man page&lt;/td&gt;
&lt;td&gt;《C 程式語言》&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;Ruby&lt;/th&gt;
&lt;td&gt;設定後的 irb&lt;/td&gt;
&lt;td&gt;ri&lt;/td&gt;
&lt;td&gt;《Programming Ruby》&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;Python&lt;/th&gt;
&lt;td&gt;ipython&lt;/td&gt;
&lt;td&gt;ipython&lt;/td&gt;
&lt;td&gt;《Python Essential Reference》&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;th&gt;Java&lt;/th&gt;
&lt;td&gt;無&lt;/td&gt;
&lt;td&gt;CHM格式的 Java doc &lt;/td&gt;
&lt;td&gt;無&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;( 待續 )&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/fcamel/~4/awxdbIYx4io" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://fcamel.twbbs.org/archives/2009/07/22/859/#comments" thr:count="9" />
		<link rel="replies" type="application/atom+xml" href="http://fcamel.twbbs.org/archives/2009/07/22/859/feed/atom/" thr:count="9" />
		<thr:total>9</thr:total>
	<feedburner:origLink>http://fcamel.twbbs.org/archives/2009/07/22/859/</feedburner:origLink></entry>
	</feed>
