<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/rss2full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><rss 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:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>{|ihower.idv.tw| blog }</title>
	
	<link>http://ihower.idv.tw/blog</link>
	<description>experiences in Ruby, Rails and Merb</description>
	<pubDate>Thu, 16 Oct 2008 04:12:44 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.2</generator>
	<language>en</language>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/ihower" type="application/rss+xml" /><item>
		<title>售 MacBook Pro 筆電一台</title>
		<link>http://feeds.feedburner.com/~r/ihower/~3/421698881/1926</link>
		<comments>http://ihower.idv.tw/blog/archives/1926#comments</comments>
		<pubDate>Wed, 15 Oct 2008 15:52:54 +0000</pubDate>
		<dc:creator>ihower</dc:creator>
		
		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://ihower.idv.tw/blog/?p=1926</guid>
		<description><![CDATA[代售好友的 MBP 筆記型電腦一台，有試用了一個禮拜多(上週我的 MBP 拿去送修，所以就借了這台當工作機 :p)，功能一切正常：

中文鍵盤，15 吋螢幕
序號: W8630241VWW
處理器: Intel Core Duo 2.0GHz
L2 快取記憶體: 2 MB
記憶體: 2 GB
匯流排速度: 667 MHz
硬碟: 80GB
這台只有 Firewire 400, 沒有 Firewire 800
外觀方面不算太理想，由於經常使用，鍵盤表面上有許多磨損的痕跡。
保固: 已經超過一年保固期限，也沒有再加買 Apple Care。
電池在保固期快要結束之前換過全新的一顆，因此現在還可以連續使用兩個小時左右。
附件: 變壓器、原廠附的 Tiger 光碟片、原廠附的 Apple Remote、DVI-to-RGB 轉接頭
附贈: 一盒正版的 Leopard 光碟片、 Moshi 銀灰色手提袋。

欲售 TWD $25000，有意願購買者，可以直接來信議價，或從Y!拍賣下定。




]]></description>
			<content:encoded><![CDATA[<p>代售好友的 MBP 筆記型電腦一台，有試用了一個禮拜多(上週我的 MBP 拿去送修，所以就借了這台當工作機 :p)，功能一切正常：</p>
<ul>
<li>中文鍵盤，15 吋螢幕</li>
<li>序號: W8630241VWW</li>
<li>處理器: Intel Core Duo 2.0GHz</li>
<li>L2 快取記憶體: 2 MB</li>
<li>記憶體: 2 GB</li>
<li>匯流排速度: 667 MHz</li>
<li>硬碟: 80GB</li>
<li>這台只有 Firewire 400, 沒有 Firewire 800</li>
<li>外觀方面不算太理想，由於經常使用，鍵盤表面上有許多磨損的痕跡。</li>
<li>保固: 已經超過一年保固期限，也沒有再加買 Apple Care。</li>
<li>電池在保固期快要結束之前換過全新的一顆，因此現在還可以連續使用兩個小時左右。</li>
<li>附件: 變壓器、原廠附的 Tiger 光碟片、原廠附的 Apple Remote、DVI-to-RGB 轉接頭</li>
<li>附贈: 一盒正版的 Leopard 光碟片、 Moshi 銀灰色手提袋。</li>
</ul>
<p>欲售 TWD $25000，有意願購買者，可以直接來信議價，或從<a href="http://tw.f2.page.bid.yahoo.com/tw/auction/b43313092">Y!拍賣</a>下定。</p>
<p>
<a href="http://www.flickr.com/photos/ihower/2943988019/" title="Gugod's MBP by ihower, on Flickr"><img src="http://farm4.static.flickr.com/3177/2943988019_ea464ded44_m.jpg" width="240" height="180" alt="Gugod's MBP" /></a></p>
<p><a href="http://www.flickr.com/photos/ihower/2944851036/" title="Gugod's MBP by ihower, on Flickr"><img src="http://farm4.static.flickr.com/3148/2944851036_9b57cefbd7_m.jpg" width="240" height="180" alt="Gugod's MBP" /></a></p>
<p><a href="http://www.flickr.com/photos/ihower/2943989023/" title="Gugod's MBP by ihower, on Flickr"><img src="http://farm4.static.flickr.com/3221/2943989023_d35cd46579_m.jpg" width="240" height="180" alt="Gugod's MBP" /></a></p>
<img src="http://feeds.feedburner.com/~r/ihower/~4/421698881" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ihower.idv.tw/blog/archives/1926/feed</wfw:commentRss>
		<feedburner:origLink>http://ihower.idv.tw/blog/archives/1926</feedburner:origLink></item>
		<item>
		<title>MerbCamp 2008</title>
		<link>http://feeds.feedburner.com/~r/ihower/~3/418970444/1998</link>
		<comments>http://ihower.idv.tw/blog/archives/1998#comments</comments>
		<pubDate>Sun, 12 Oct 2008 23:31:04 +0000</pubDate>
		<dc:creator>ihower</dc:creator>
		
		<category><![CDATA[Merb]]></category>

		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://ihower.idv.tw/blog/?p=1998</guid>
		<description><![CDATA[
身歷其境的看了兩天的 MerbCamp，主辦單位提供的 Webcast 非常流暢，幾乎沒有 delay。(怎麼會這麼厲害呢?! 我連 youtube 或 Y! Live 沒有不 delay 的啊&#8230;orz)，讓我在家就可以參加地球另一端的研討會，真是棒極了。(雖然英文聽的哩哩落落，不過還是很爽。It&#8217;s free!)
主辦單位也在 IRC 上開了 #merbcamp 頻道，講者們似乎也都在上面，隨時都有一些 link 丟出來可以看看，有什麼問題也可在上面提出(例如: webcast 沒聲音或沒影像等轉撥問題反應)、講者QA時間也可以從 IRC 上面問，主辦單位會幫你問講者，非常有參與性。
以下整理自我在twitter的簡短 Merb 心得:

Merb router&#8217;s defer_to method is awesome!! # keep routing logic in the route, even authentication.
merb slice use 100% public API of merb core, not like rails engine broke with each [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.merbcamp.com"><img src="http://www.merbcamp.com/images/logo.gif"></a></p>
<p>身歷其境的看了兩天的 <a href="http://www.merbcamp.com">MerbCamp</a>，主辦單位提供的 Webcast 非常流暢，幾乎沒有 delay。(怎麼會這麼厲害呢?! 我連 youtube 或 Y! Live 沒有不 delay 的啊&#8230;orz)，讓我在家就可以參加地球另一端的研討會，真是棒極了。(雖然英文聽的哩哩落落，不過還是很爽。It&#8217;s free!)</p>
<p>主辦單位也在 IRC 上開了 #merbcamp 頻道，講者們似乎也都在上面，隨時都有一些 link 丟出來可以看看，有什麼問題也可在上面提出(例如: webcast 沒聲音或沒影像等轉撥問題反應)、講者QA時間也可以從 IRC 上面問，主辦單位會幫你問講者，非常有參與性。</p>
<p>以下整理自我在<a href="http://twitter.com/ihower">twitter</a>的簡短 Merb 心得:</p>
<ul>
<li>Merb router&#8217;s defer_to method is awesome!! # keep routing logic in the route, even authentication.</li>
<li>merb slice use 100% public API of merb core, not like rails engine broke with each rails upgrade. :) </li>
<li>MerbAuth&#8217;s &#8220;strategy&#8221; looks good to support multiple login methods(password, open id&#8230;etc) in the same app. </li>
<li>Although merb is ORM-agnostic and JavaScript library agnostic, but everybody loves DataMapper and JQuery ;) </li>
<li>Merb team will not implement RJS. RJS sucks!</li>
<li>It seems that Merb::Plugins is very different from rails plugins: Merb has hooks and public/stable API ;) </li>
<li>Merb really hates monkeypatching and alias_method_chain.</li>
<li>Rails has no public/private/plugin API, every method is API. That&#8217;s why rails developer must use monkeypatching and alias_method_chain.</li>
<li>Ruby is not slow! merb is faster than PHP (frameworks). see <a href="http://skitch.com/leinweber/2qju/merbcamp">benchmark</a>.</li>
</ul>
<p>也有人做了詳細的筆記：<a href="http://rubypond.com/articles/2008/10/11/merbcamp---notes-from-the-edge/">MerbCamp Day1</a>, <a href="http://rubypond.com/articles/2008/10/12/merbcamp---day-2/">MerbCamp Day2</a>，最後一場 Keynote 的 Merb Performance Benchmarks 特別有意思：Merb without template 與 pure PHP 平分秋色，Merb with template 就大勝 CodeIgniter 和 CakePHP 這兩套 PHP web framework 了&#8230;.. XD 找了一下這幾套的 <a href="http://www.avnetlabs.com/php/php-framework-comparison-benchmarks">benchmarks</a> 比較，發現連 Rails 還不算太慢麻，比 Zend Framework 跟 CakePHP 都還快上不少，所以比較起來應該是 Merb >> CodeIgniter > Rails >> Zend Framework >> CakePHP。</p>
<p>投影片大部分在 <a href="http://www.slideshare.net/tag/merbcamp">slideshare</a> 上可以下載的到。同時間 Merb 也將發佈 1.0 RC (即 0.9.9) 版本，所有 API 都將定下來(Merb team 非常強調保證他們的 public API will be stable and backwards compatibility for 1.x，我想大家都被 Rails 一升級就有 plugin 會爛掉非常感冒)，相信在過不久就會有越來越多的文件可以看(目前還很缺啊!)，是個不錯的進場時機。</p>
<img src="http://feeds.feedburner.com/~r/ihower/~4/418970444" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ihower.idv.tw/blog/archives/1998/feed</wfw:commentRss>
		<feedburner:origLink>http://ihower.idv.tw/blog/archives/1998</feedburner:origLink></item>
		<item>
		<title>物件導向程式的九個體操練習</title>
		<link>http://feeds.feedburner.com/~r/ihower/~3/418634148/1960</link>
		<comments>http://ihower.idv.tw/blog/archives/1960#comments</comments>
		<pubDate>Sun, 12 Oct 2008 15:01:39 +0000</pubDate>
		<dc:creator>ihower</dc:creator>
		
		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://ihower.idv.tw/blog/?p=1960</guid>
		<description><![CDATA[最近在翻 The ThoughtWorks Anthology(知名軟體顧問公司 Thoughtworks 出的文集)，裡面有篇 Object Calisthenics 蠻有意思的。
好的物件導向設計很難，我們都很同意何謂好的設計原則：高內聚力(cohesion)、低耦合(loose coupling)、不重複程式(Don&#8217;t Repeat Yourselp)、封裝(encapsulation)、可測試性、易閱讀性等等，但是實際寫的時候卻不容易化身為一行行的程式碼。這篇作者列了九條規則，並建議你練習寫個千行程式嚴格遵守看看，用以改善你的OO實作能力。
初次看到這九條絕得有點誇張，但其實濃縮了不少OO想法在裡面，如果有閱讀過重構或物件導向設計原則等概念，應該能夠聯想到很多東西，挺有趣的。
1. 每個函式裡面只能有一層縮排，如果需要多一層，請多寫一個 method 去呼叫。
這個規則其實就是要求嚴格遵守 Compose Method：將邏輯操作轉換為細目等級相同的步驟，避免過深的邏輯而無法迅速了解，相信大家應該都有看(寫)過M型程式吧 :p
2. 不要使用到 else 這個關鍵字。
避免寫出複雜的 nested conditional 程式。不論是&#8221;重構&#8220;或是&#8221;重構－向範式前進&#8220;這兩本書，都有很多篇幅花在討論如何簡化條件邏輯，作法包括 
a. 重構一書提到的 Replace Nested Conditional with Guard Clauses 方式，直接使用 return 返回，不要再 else 了。
b. 請愛用 Ternary Operator：也就是 boolean-expression ? expr1 : expr2。很多簡單的 if else 都可以用 Ternary Operator 簡化到一行一目了然。舉個 Ruby code 例子：

  [...]]]></description>
			<content:encoded><![CDATA[<p>最近在翻 <a href="http://www.pragprog.com/titles/twa/thoughtworks-anthology">The ThoughtWorks Anthology</a>(知名軟體顧問公司 <a href="http://www.thoughtworks.com/">Thoughtworks</a> 出的文集)，裡面有篇 Object Calisthenics 蠻有意思的。</p>
<p>好的物件導向設計很難，我們都很同意何謂好的設計原則：高內聚力(cohesion)、低耦合(loose coupling)、不重複程式(Don&#8217;t Repeat Yourselp)、封裝(encapsulation)、可測試性、易閱讀性等等，但是實際寫的時候卻不容易化身為一行行的程式碼。這篇作者列了九條規則，並建議你練習寫個千行程式嚴格遵守看看，用以改善你的OO實作能力。</p>
<p>初次看到這九條絕得有點誇張，但其實濃縮了不少OO想法在裡面，如果有閱讀過重構或物件導向設計原則等概念，應該能夠聯想到很多東西，挺有趣的。</p>
<blockquote><p>1. 每個函式裡面只能有一層縮排，如果需要多一層，請多寫一個 method 去呼叫。</p></blockquote>
<p>這個規則其實就是要求嚴格遵守 <a href="http://www.industriallogic.com/xp/refactoring/composeMethod.html">Compose Method</a>：將邏輯操作轉換為細目等級相同的步驟，避免過深的邏輯而無法迅速了解，相信大家應該都有看(寫)過<a href="http://forth.wordpress.com/2007/11/08/m型程式/">M型程式</a>吧 :p</p>
<blockquote><p>2. 不要使用到 else 這個關鍵字。</p></blockquote>
<p>避免寫出複雜的 nested conditional 程式。不論是&#8221;<a href="http://tlsj.tenlong.com.tw/WebModule/BookSearch/bookSearchViewAction.do?isbn=9789861547534&#038;sid=46024">重構</a>&#8220;或是&#8221;<a href="http://tlsj.tenlong.com.tw/WebModule/BookSearch/bookSearchViewAction.do?isbn=9789861814025&#038;sid=43993">重構－向範式前進</a>&#8220;這兩本書，都有很多篇幅花在討論如何簡化條件邏輯，作法包括 </p>
<p>a. 重構一書提到的 <a href="http://www.refactoring.com/catalog/replaceNestedConditionalWithGuardClauses.html">Replace Nested Conditional with Guard Clauses</a> 方式，直接使用 return 返回，不要再 else 了。</p>
<p>b. 請愛用 Ternary Operator：也就是 boolean-expression ? expr1 : expr2。很多簡單的 if else 都可以用 Ternary Operator 簡化到一行一目了然。舉個 Ruby code 例子：</p>
<p><code><br />
  if ( is_something )<br />
    "foo"<br />
  else<br />
     "bar"<br />
  end<br />
</code><br />
如果改成三重操作子就俐落多了：<br />
<code><br />
 ( is_something )? "foo" : "bar"<br />
</code></p>
<p>另外初心者也常寫出根本不需要 if else 的情況：<br />
<code><br />
def is_foobar<br />
  if ( a > 0 )<br />
    return true<br />
  else<br />
    return false<br />
  end<br />
end<br />
</code><br />
其實只需要這樣就可以了：<br />
<code><br />
def is_foobar<br />
  ( a > 0 )<br />
end<br />
</code></p>
<p>c. 第三招要先念點書，請善用物件導向的多型(polymorphism)能力，請參考設計模式的 <a href="http://en.wikipedia.org/wiki/Strategy_pattern">Strategy pattern</a> 或重構的 <a href="http://www.refactoring.com/catalog/replaceConditionalWithPolymorphism.html">Replace Conditional with Polymorphism</a></p>
<p><span id="more-1960"></span></p>
<blockquote><p>3. 所有基本型別都包裝成物件 </p></blockquote>
<p>如果你要用到 integer 或 string 等基本型別，請多用一層帶有意義 Class 包裝起來。例如在傳遞 &#8220;年&#8221; 跟 &#8220;月&#8221; 的參數時，不要只用 integer 傳遞哪一年哪一個月，而是用個 Date 物件包裝起來。</p>
<p>為什麼呢? 透過這種小型物件，我們可以寫出較容易維護的程式，一看就懂那個 integer 代表的意義是什麼。而且只用基本型別，編譯器也無法幫助(偵測)你寫出你真正想要的正確&#8221;語意&#8221;。另外一個小型物件好處是提供了很好的放 method 的地方，例如在這方面 Ruby 就做的很好，因為所有東西都是物件，所以甚至是 integer 或 string 都可以直接有自己的基本操作，例如：<br />
<code><br />
-123456.abs # 123456<br />
"FOObar".downcase # "foobar"。<br />
Time.now.year # 2008<br />
</code></p>
<blockquote><p>4. 每一行只能出現 dot 一次(即每行只能呼叫一次 method)</p></blockquote>
<p>這規則對 Ruby 可能太嚴格了&#8230;XD 規則的目的是要減少耦合，避免破壞封裝原則：你只能玩你的玩具，而不是玩具的玩具。細節請找 The Law of Demeter (&#8221;只對你的朋友說話&#8221;)，引用 Qing 長輩的<a href="http://www.javaworld.com.tw/roller/qing/entry/漫談程式碼的相依性_4">漫談程式碼的相依性</a>：&#8221;在遵守所謂的Law of Demeter時，在某一物件的某一函式中所能呼叫函式的對象是受限制的，它只能是：該物件本身、傳入該函式的引數、在該函式中所產生的物件、以及該物件的資料成員。很明顯的，你不能在此函式中呼叫其他函式所回傳物件的函式，因為其他函式所回傳的物件，並不在上述的對象之中。</p>
<blockquote><p>5. 不要縮寫名稱 </p></blockquote>
<p>我超愛這個規則，每次看到有人用縮寫亂取 method name 或 variable name，就覺得很抓狂。即使用 full name 會長了點，但是我寧願一看就懂而不是玩猜謎(例 what&#8217;s sm? short_message? smart_phone? single_machine?)。即使用暫時變數我也覺得應該好好命名，而不是只用一個 &#8220;t&#8221;。我自己在 Textmate 的經驗是只要按 Esc 就可以自動比對出你要的 full name，從來都不覺得打完整名稱會很辛苦。</p>
<p>如果你真的覺得太長，就應該好好重新思考：是不是這個 method 放錯 class 了? (放到別的 class 之下也許不需要這麼長就可以知道作用)。另一個取名常犯的錯誤是不需要重複 context (語境)：例如一個叫 Order Class，它的 method name 就不需要命名為 ship_order (即@order.ship_order)，只需要取名 ship (即@order.ship)就好了。</p>
<blockquote><p>6. 保持東西輕薄</p></blockquote>
<p>class 不超過50行，每個 package 不超過10個檔案。50行的程式不會超過一個螢幕，這樣螢幕不用捲就可以一掃而過。這個挑戰在於你要努力去 grouping 有共通 logical sense 的東西。</p>
<blockquote><p>7. 不要用任何一個含超過兩個 instance 變數的 class </p></blockquote>
<p>這大概是最難的練習了，作者認為當一個 Class 處理超過一個 state variable 時，就應該另建一個新的 class 分解及包裝起來。實際的作法我想可以參考重構的 <a href="http://www.refactoring.com/catalog/extractClass.html">Extract Class</a> 方法。</p>
<blockquote><p>8. 使用第一級 collections</p></blockquote>
<p>任何包含 collection 的類別就不應該再含有別的變數，也就是你應該把 collection 當做一個很基本的類別來使用。</p>
<blockquote><p>9. 不要使用任何 getters/setters/properties</p></blockquote>
<p>目標是要練習 &#8220;Tell, don&#8217;t ask&#8221; 原則，你應該盡量告訴物件你想要什麼(tell)，而不是去問(ask)物件的狀態，然後做決定，再告訴物件做什麼。更詳細可以看看 The Pragmatic Bookshelf 的 <a href="http://www.pragprog.com/articles/tell-dont-ask">Tell, Don&#8217;t Ask</a> 一文 (這篇也有提到Law of Demeter)。</p>
<img src="http://feeds.feedburner.com/~r/ihower/~4/418634148" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ihower.idv.tw/blog/archives/1960/feed</wfw:commentRss>
		<feedburner:origLink>http://ihower.idv.tw/blog/archives/1960</feedburner:origLink></item>
		<item>
		<title>如何使用 memcached 做快取</title>
		<link>http://feeds.feedburner.com/~r/ihower/~3/416739583/1768</link>
		<comments>http://ihower.idv.tw/blog/archives/1768#comments</comments>
		<pubDate>Fri, 10 Oct 2008 12:12:33 +0000</pubDate>
		<dc:creator>ihower</dc:creator>
		
		<category><![CDATA[Cache]]></category>

		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://ihower.idv.tw/blog/?p=1768</guid>
		<description><![CDATA[
關於 memcached，雖然可以找到一些基本
介紹，DK大神也有點到一些進階議題，不過最近看了 Using memcached PDF 之後才真正學到了不少實戰技巧跟如何設計快取的概念。以下是一些零散的筆記：
裝好之後，基本的啟動方式是

* `memcached -l 127.0.0.1 -P 11211 -m 128 -d` for deamon
* `memcached -l 127.0.0.1 -P 11211 -m 128 -vv` for development debug

memcached 是一套 Name-Value Pair(NVP) 分散式記憶體快取系統，Key 的長度被限制在 250 characters，儲存的資料不能超過 1 megabyte。如果資料會超過 1mb，可以考慮使用壓縮工具，例如在 Rails 2.1 裡就內建了 ActiveSupport::Cache::CompressedMemCacheStore。
除了 memcached server，不同程式語言都有自己的 memcache client library 工具提供更方便的介面。一個基本的任務就是使用 Hashing algorithm 根據 Key 來決定該去存取一台 memcached server (如果有超過一台的 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.pragprog.com/titles/memcd/using-memcached"><img src="http://ihower.idv.tw/blog/wp-content/uploads/2008/10/memcd.jpg" alt="" title="memcd" width="190" height="228" class="alignnone size-full wp-image-1946" /></a></p>
<p>關於 <a href="http://www.danga.com/memcached/">memcached</a>，雖然可以找到一些基本<br />
<a href="http://tw.myblog.yahoo.com/weijenlu/article?mid=87&#038;prev=89&#038;next=82">介</a><a href="http://lightyror.thegiive.net/2006/12/rails-memcached_21.html">紹</a>，DK大神也有點到一些進階<a href="http://blog.gslin.org/archives/2008/05/31/1510/">議題</a>，不過最近看了 <a href="http://www.pragprog.com/titles/memcd/using-memcached">Using memcached</a> PDF 之後才真正學到了不少實戰技巧跟如何設計快取的概念。以下是一些零散的筆記：</p>
<p>裝好之後，基本的啟動方式是<br />
<code><br />
* `memcached -l 127.0.0.1 -P 11211 -m 128 -d` for deamon<br />
* `memcached -l 127.0.0.1 -P 11211 -m 128 -vv` for development debug<br />
</code></p>
<p>memcached 是一套 Name-Value Pair(NVP) 分散式記憶體快取系統，Key 的長度被限制在 250 characters，儲存的資料不能超過 1 megabyte。如果資料會超過 1mb，可以考慮使用壓縮工具，例如在 Rails 2.1 裡就內建了 ActiveSupport::Cache::CompressedMemCacheStore。</p>
<p>除了 memcached server，不同程式語言都有自己的 memcache client library 工具提供更方便的介面。一個基本的任務就是使用 Hashing algorithm 根據 Key 來決定該去存取一台 memcached server (如果有超過一台的 memcached server 的話)。Ruby 的 client 目前檯面上有幾套 1. <a href="http://rubyforge.org/projects/seattlerb">memcache-client</a> 2. fiveruns fork 版 <a href="http://github.com/fiveruns/memcache-client/tree/master">memcache-client</a>，針對 Hasing 的部份用C改寫了 3. 使用 <a href="http://tangent.org/552/libmemcached.html">libmemcached</a> 的超快 <a href="http://github.com/fauna/memcached/tree/master">memcached</a></p>
<p>有趣的是，不需要 client library，memcached 是可以直接 telnet 127.0.0.1 11211 的。telnet 之後打 stats 可以得到一些統計資料，除了目前共有多少筆資料跟共用多少空間之外，重要的有 cmd_get 跟 cmd_hits，就可以得出 cache hit ratio，這個數字應該努力到九成以上。另外還有你的 cmd_set 應該超過 cmd_get，</p>
<p>其他的 memcached 標準操作有 SET (新增或是更新一個值)、ADD(只有在該key不存在時，才會新增快取資料成功)、REPLACE(只有在該key已經存在時，才會更新資料成功)、GET(拿快取資料)。</p>
<p>在考慮使用 memcached 前，要知道它不是你系統中唯一的 cache，HTML 的整頁快取應該用 Web server、純 SQL query result 可以用 MySQL 內建 <a href="http://dev.mysql.com/doc/refman/5.0/en/query-cache.html">Query Cache</a>，設定很簡單，效果很不錯 (<a href="http://www.mysqlperformanceblog.com/2006/08/09/cache-performance-comparison/">Cache Performance Comparison</a>。我自己的心得是很多時候你想要快取的物件其實並不是一個 SQL query 就可以搞定的，而是多個 SQL query 才計算出來，這時候去做純快取 SQL query result 我個人覺得也許不是很有意義，Rails 這部份就有人實做了<a href="http://github.com/ferblape/query_memcached/tree/master">query_memcached</a>。。</p>
<p>另外要注意的是 memcached 並不是 persistent data store，只要一關掉 memcached server，裡面的資料就會通通不見，如果要拿來儲存 session authentication 資料要特別小心。</p>
<p>寫 memcached 程式的第一個問題是找出什麼資料需要快取? 一個常見的問題是我該快取 HTML fragment 還是純資料結構? 如果你操作介面只有一處用到，我們可以只快取 HTML fragment 即可，不然其實規模稍大的網站其實兩者都可以快取起來。</p>
<p>撰寫使用 memcached 程式的基本模式就是，先查看有沒有 key-value，有就把快取資料讀出來，沒有就運算結果後存到 memcached sever。這部份算是簡單的。真正困難的事情有兩件：<strong>一是清除過期的快取資料(expire)，二是Key的命名。</strong><br />
<span id="more-1768"></span><br />
命名的一個慣用的格式是 ObjectName:ObjectType:Key 或是該 SQL statement，但為了 Security 避免被人猜到 Key 和避免超過 255 bytes 的 key 長度限制，建議你將 Key hash 過。當然 Security 的最好解決方式是要有防火牆，因為只要連的上 Port 11211，有 Key 就可以讀的到快取資料，memcached server 本身是沒有任何認證機制的。</p>
<p>有兩種方式清除快取資料：一是在新增/刪除資料時，順便刪掉這個快取 key-value，這樣下次 request 來時便會重新 快取。二是在有更新的時候直接重設快取資料(Reset)。要注意的是如果您有不同的程式會直接更新資料庫(也就是不只是透過主應用程式，還有別的背景程式)，就會有可能 memcachd 裡面的資料沒有被更新到，解法有 1. 清空所有資料 2. 有一隻程式可以重建 memcached 裡面的資料 3. 統一用一套知道 memcached 機制的介面操作</p>
<p>如果站很大，race condition 就會是個效能問題了，同時有多個 request 同時去更新同一份快取資料。雖然改用上述的方法二在有更新的時候直接重設(Reset)快取資料可以改善這個問題，不過如果資料根本還不在快取裡的話問題還是存在。也因此我們需要一個 lock 機制，概念是先檢查有沒有 lock entry，有的話先等一下，然後再抓。沒有的話就更新，然後刪除 lock entry。</p>
<p>實做招數有二，如果你的 client library 支援 ADD 操作(也就是如果該 key 已經存在的話，操作會失敗)，就可以先用 ADD key:lock 決定是不是有別的 process 在用，沒有的話就 SET key，最後 DELETE delete key:lock。</p>
<p>如果 client library 只支援 GET 操作，只好先 GET key:lock，沒有值就 SET key:lock (有的話表示已經被鎖住，就先稍等)，然後再設定真正的快取資料 SET key，最後 DELETE key:lock。這樣會比方法一多一個操作就是了。這的方法的範例程式碼可以去PDF的 <a href="http://www.pragprog.com/titles/memcd/source_code">Source Code</a>下載，在 /LinuxBasics/memcachedUpdateCalendarOfEvents-3.pl。(well, it&#8217;s perl code)</p>
<p>如果不採用主動更新快取資料的方式，也可以直接設定過期時間(expire time)，這取決於你有多常讀取/更新。越常更新 expire time 就越短。這種方式特別適合例如首頁每隔幾分鐘才換，而且沒有要求快取資料一定要跟資料庫裡面完全一致，例如在五分鐘內雖有很多更新資料，但前台只需要每隔五分鐘重組頁面即可。</p>
<p>為了徹底解決使用 expire time 方式仍會有的 race condition 問題，有一招是 proactive cache refill：我們另外紀錄一個比 expire 週期還短的 refresh time，如果 refresh time 到了，我們就先更新快取資料，這樣無論何時都不會有 client 要不到資料的情形，自然也就不會發生 rece condition。這招大絕的範例在 /LinuxBasics/memcachedRollingCalendarOfEvents.pl。</p>
<p>在更新跟查詢都很極端頻繁的情況下，也可以考慮用另外的程式專門去撈資料庫執行更新快取，這樣主應用程式只需要處理拿快取資料即可(唯一會去資料庫撈可能只有第一次資料不存在時)。</p>
<p>另一個議題是：如果群集跟個別資料都快取會有的重複現象，例如我們如果同時快取了 People.find(:all) 跟 Person.find(1)，這時就重複存了 Person.find(1)。作者是建議群集的部份只當作指標(pointer)來使用，也就是群集只快取了所有 Person 的 ID 而不是完整資料。畢竟單項比較好重複使用(reuse)，而且在處理更新快取資料時也比較方便，不會發生個別資料更新了，但是群集忘了沒有處理。</p>
<p>話說雖然 memcached 有提供 ADD/REPLACE 操作(根據Key存在或不存在，會導致儲存快取不一定成功的操作)，但是這樣你就必須處理 error code 的情況，作者認為<strong>&#8220;快取&#8221;的基本原理是不回應(noreply)</strong>：你不應該關心為什麼你的資料不在快取裡 (事實上就算你的 memcached server 都關掉，你的程式應該也要可以正常執行，只是比較慢而已)，也許可能是 expire time 到了? 記憶體用完了? 被刪除了? 或是根本不存在? 這些都不重要。雖然有些例外，但基本上應該 SET 操作就可以應付絕大多數的情況。</p>
<img src="http://feeds.feedburner.com/~r/ihower/~4/416739583" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ihower.idv.tw/blog/archives/1768/feed</wfw:commentRss>
		<feedburner:origLink>http://ihower.idv.tw/blog/archives/1768</feedburner:origLink></item>
		<item>
		<title>實戰敏捷開發 Practices of an Agile Developer (3) 測試篇</title>
		<link>http://feeds.feedburner.com/~r/ihower/~3/416128294/1758</link>
		<comments>http://ihower.idv.tw/blog/archives/1758#comments</comments>
		<pubDate>Thu, 09 Oct 2008 20:56:45 +0000</pubDate>
		<dc:creator>ihower</dc:creator>
		
		<category><![CDATA[Agile]]></category>

		<category><![CDATA[Books]]></category>

		<guid isPermaLink="false">http://ihower.idv.tw/blog/?p=1758</guid>
		<description><![CDATA[上一章談了來自客戶的 Feedback，這一章作者談另一種回饋機制：透過程式測試得知目前開發的情形(Coding Feedback!)。
Put Angels on Your Shoulders (讓測試當你的天使)
Code 一直在變，我們需要一種持續又快速的 feedback 告訴我們這些程式碼建不健康：是我想要的程式嗎? 最後的 commit 有沒有弄壞任何東西? 這時你需要的一種機制可以一直幫你確保這些，也就是自動化的單元測試(unit tests)。
因為測試的流程總是 1.Setup(設定初始資料) 2.Exercise（執行某些操作) 3. Verify(驗證輸出結果與預期相同) 4.Teardown(清空資料)，所以目前每套程式語言一定都會有一套 xUnit framework 的測試框架可供使用。
另外還可以加裝一套 continuous build 工具(例如 CruiseControl)，它可以自動 checkout 最新的程式碼並測試，一旦有人送交了有錯的程式碼，馬上就可以通知並修正(這時候fix bug最簡單且成本最低)。
當你的 unit tests 達到 Regression tests 程度時，這時候做重構(refactoring)時就有更大的自由(自信)，因為不需要擔心改爛了什麼你不知道的東西。
另外搭配 test coverage 工具可以幫助你有個大概的鳥瞰。寫 test 像是一個聰明的投資，因此報酬效率也很重要，trivial method 不需要寫，把火力放在你最擔心出錯的地方。
Use It Before You Build It (用之前先測試怎麼用)
這節進一步談測試驅動開發(TDD)，在寫程式前先寫好測試程式。透過先寫測試程式，可以從使用API的觀點來思考怎麼寫程式、怎麼設計API，因而寫出更好用、一致及簡潔的程式介面。
Different Makes a Difference (差一點差很多)
在我這台沒問題啊，為什麼換一台電腦就不對了? 只要換一個平台(即使是不同版本的作業系統)，不同就是不同，而太晚發現這樣的問題要修理是非常麻煩的，尤其是正要 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://ihower.idv.tw/blog/archives/1756">上一章</a>談了來自客戶的 Feedback，這一章作者談另一種回饋機制：透過程式測試得知目前開發的情形(Coding Feedback!)。</p>
<h3>Put Angels on Your Shoulders (讓測試當你的天使)</h3>
<p>Code 一直在變，我們需要一種持續又快速的 feedback 告訴我們這些程式碼建不健康：是我想要的程式嗎? 最後的 commit 有沒有弄壞任何東西? 這時你需要的一種機制可以一直幫你確保這些，也就是自動化的單元測試(unit tests)。</p>
<p>因為測試的流程總是 1.Setup(設定初始資料) 2.Exercise（執行某些操作) 3. Verify(驗證輸出結果與預期相同) 4.Teardown(清空資料)，所以目前每套程式語言一定都會有一套 xUnit framework 的測試框架可供使用。</p>
<p>另外還可以加裝一套 continuous build 工具(例如 <a href="http://cruisecontrol.sourceforge.net/">CruiseControl</a>)，它可以自動 checkout 最新的程式碼並測試，一旦有人送交了有錯的程式碼，馬上就可以通知並修正(這時候fix bug最簡單且成本最低)。</p>
<p>當你的 unit tests 達到 <a href="http://en.wikipedia.org/wiki/Regression_testing">Regression tests</a> 程度時，這時候做重構(<a href="http://www.refactoring.com/">refactoring</a>)時就有更大的自由(自信)，因為不需要擔心改爛了什麼你不知道的東西。</p>
<p>另外搭配 test coverage 工具可以幫助你有個大概的鳥瞰。寫 test 像是一個聰明的投資，因此報酬效率也很重要，trivial method 不需要寫，把火力放在你最擔心出錯的地方。</p>
<h3>Use It Before You Build It (用之前先測試怎麼用)</h3>
<p>這節進一步談測試驅動開發(TDD)，在寫程式前先寫好測試程式。透過先寫測試程式，可以從使用API的觀點來思考怎麼寫程式、怎麼設計API，因而寫出更好用、一致及簡潔的程式介面。</p>
<h3>Different Makes a Difference (差一點差很多)</h3>
<p>在我這台沒問題啊，為什麼換一台電腦就不對了? 只要換一個平台(即使是不同版本的作業系統)，不同就是不同，而太晚發現這樣的問題要修理是非常麻煩的，尤其是正要 release 的時候才發現它沒辦法在某某你想要的平台上執行。</p>
<p>我們當然可以要求 QA team 要在不同平台上測試，但是如果他們只是手動測試，就不如自動測試來的及早發現。我們已經會在 commit 程式前在自己電腦上執行一次 unit testing，現在要做的事情是要在你所要支援的不同平台、不同版本上再測試一次。不過好累啊，這時候就必須靠 <a href="http://www.martinfowler.com/articles/continuousIntegration.html">continuous integration</a> 工具來幫忙，每當有人 commit 時，這個工具就會自動 checkout 出來執行測試，我們分別在不同平台(例如可以使用 VMware 或 Virtual PC)上設定好這個工具來做自動化測試。</p>
<h3>Automate Acceptance Testing (自動化驗收測試)</h3>
<p>重要的商業邏輯除了 unit testing，還需要驗收測試獨立於所有程式之外，而且客戶必須親自驗證這個結果。也因為因此，我們需要一個工具讓客戶也可以新增編輯跟修改驗收測試(without coding)，</p>
<p>這本書介紹的工具是 http://fit.c2.com/，它使用 HTML table 當作定義的介面，客戶可以直接編輯加入新的功能，接著加入可能的輸入與正確的預期值。然後 developer 再根據這個 table 產生 fixtures 資料，並比對測試結果是否成功。</p>
<p>感覺像是協力式的 unit testing，你還是必須自己寫測試，只是必須有別人提供你什麼是正確答案。</p>
<h3>Measure Real Progress (測量真正的進度)</h3>
<p>紀錄花了多久做事提供了很好的 feedback，可以幫助專案計畫、估計跟效率測量。但是一般常用的 timesheet 多半用於薪水用途而非真正花費的時間，這點要特別注意。另外常用的紀錄完成百分比，作者也認為很沒用。一個比較好的方式是紀錄 1.估計多少時間 2.已經花了多少時間 3.估計還需要多少時間來完成。根據真正花了多少時間的經驗，加以比對一開始的估計值，可以獲得很好的經驗用於估計下一個類似的任務。</p>
<p>紀錄真正的時數對於使用 backlog(要完成的任務清單)和 Iteration 也非常重要，如果剩餘的時間超過這次 Iteration 了，就知道必須移動某些任務到下一個 Iteration，反之則有時間多加工作。</p>
<p>最後是注意紀錄的時間單位，以分鐘太細了，以週就太粗囉。我們的經驗是超過一天的 Ticket(Issue) 應該都可以想辦法拆小，1hr、2hr、4hr、8hr 應該是不錯的範圍。</p>
<h3>Listen to Users (聆聽使用者)</h3>
<p>作者在這章最後特別提了使用者的回饋。即使有寫測試程式，我們還是很容易忽略來自真正使用者的聲音。每一個使用者的抱怨都有其道理，盡量試著找出真正的問題，而不是怪罪使用者不懂、不了解系統如何操作。<br />
程式Bug、文件Bug、使用者會認知錯誤也要算是Bug。而不是讓客服人員回答說：喔，那不是Bug, 你犯了一個大家都會犯的錯誤。即使聽起來很笨，也應該去試著聆聽。</p>
<img src="http://feeds.feedburner.com/~r/ihower/~4/416128294" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ihower.idv.tw/blog/archives/1758/feed</wfw:commentRss>
		<feedburner:origLink>http://ihower.idv.tw/blog/archives/1758</feedburner:origLink></item>
		<item>
		<title>Rails country_select 事件懶人包</title>
		<link>http://feeds.feedburner.com/~r/ihower/~3/413333668/1770</link>
		<comments>http://ihower.idv.tw/blog/archives/1770#comments</comments>
		<pubDate>Tue, 07 Oct 2008 01:41:39 +0000</pubDate>
		<dc:creator>ihower</dc:creator>
		
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://ihower.idv.tw/blog/?p=1770</guid>
		<description><![CDATA[因為這件事我從頭跟到尾，我想我來報告一下最新的處理結果吧(是的！還有笨蛋在追蹤這個問題，而不只是又一個&#8221;某某機構把 Taiwan 改成 Taiwan, Province of China&#8221;的新聞而已)。
從 Rails 2.2 起，將不會內建 country_helper，也不會建議/提供預設的 plugin。edge Rails 即日起的 deprecation 訊息會警告您 &#8220;country_select will be removed from 2.2.0.  http://www.rubyonrails.org/deprecation/list-of-countries has more information.&#8221; (見此commit)。在這個說明頁上面也沒有名字叫做 country_helper 的官方 plugin，而是會列出幾種相容的方案：原來 Rails 的 country_helper 被改名為更明顯的 iso_3166_country_select，另外還有我根據 IBM Globalization guideline 修改成的 country_and_region_select plugin (請支持)。

其實這件事( Country Select Helper 改使用 ISO 3166 )去年(2007/10/15)就 commit 進去了，當時的 Ticket 為了避免之後再更動列表，決定根據 ISO [...]]]></description>
			<content:encoded><![CDATA[<p>因為這件事我從頭跟到尾，我想我來報告一下最新的處理結果吧(是的！還有笨蛋在追蹤這個問題，而不只是又一個&#8221;某某機構把 Taiwan 改成 Taiwan, Province of China&#8221;的新聞而已)。</p>
<p>從 Rails 2.2 起，將不會內建 country_helper，也不會建議/提供預設的 plugin。edge Rails 即日起的 deprecation 訊息會警告您 &#8220;country_select will be removed from 2.2.0.  http://www.rubyonrails.org/deprecation/list-of-countries has more information.&#8221; (<a href="http://github.com/rails/rails/commit/03a6f74bdd8d0164525fa9bf89087be1160d6d6f">見此commit</a>)。在這個<a href="http://www.rubyonrails.org/deprecation/list-of-countries">說明頁</a>上面也沒有名字叫做 country_helper 的官方 plugin，而是會列出幾種相容的方案：原來 Rails 的 country_helper 被改名為更明顯的 <a href="http://github.com/rails/iso-3166-country-select/tree/master">iso_3166_country_select</a>，另外還有我根據 <a href="http://www-01.ibm.com/software/globalization/topics/writing/references.jsp">IBM Globalization guideline</a> 修改成的 <a href="http://github.com/ihower/country_and_region_select/tree/master">country_and_region_select</a> plugin (請支持)。<br />
<span id="more-1770"></span><br />
其實這件事( Country Select Helper 改使用 <a href="http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm">ISO 3166</a> )去年(2007/10/15)就 commit 進去了，當時的 <a href="http://dev.rubyonrails.org/ticket/6872">Ticket</a> 為了避免之後再更動列表，決定根據 ISO 3166 不再接受更動(雖然有意識到 Taiwan 這個問題，但是當時並沒有人抗議)。後來陸陸續續也有人零星丟出<a href="http://rails.lighthouseapp.com/projects/8994/tickets/715-actionview-helpers-formoptionshelper-countries-constant-controversally-labels-taiwan-a-province-of-china">這個</a><a href="http://groups.google.com/group/rubyonrails-core/browse_thread/thread/c868ad88a5cf6f39/c5e0957e3cd14e89?lnk=gst&#038;q=Taiwan#c5e0957e3cd14e89">問題</a>，不過都被 NZKoz 拒絕接受變更，直到最近：</p>
<p>因為我有訂閱 GitHub 的 Rails feed，所以我在 2008/9/18 看到第一篇 <a href="http://github.com/rails/rails/commit/3353b85b0eae76bf36ae7c2f7b6adc1863278a8e#comments">jamis 留言 </a>之後，我就想說是個好機會再度提起此事，於是在 IRC 上找人幫忙聲援，再加上 twitter 上的朋友，一時間抗議聲熱鬧非凡。因為 NZKoz 早有將 country_select helper 移出成為 plugin 的想法，於是很快的就有了回應動作，不過即使如此，拆出來的官方 Rails &#8220;country_select&#8221; plugin 還是直接採用 ISO 3166 列表，並且在 deprecation 訊息也直接建議升級 Rails 2.2 之後改裝那個 plugin，這等於只是把問題從 core 移到 plugin 罷了。期間我也 fork 了這個官方的 plugin (參考了 <a href="http:////pkg-isocodes.alioth.debian.org/">isocodes package</a>，debian 的作法是針對 Taiwan 多加上 common_name attribute )，並發出 request 給 NZKoz，但是還是一樣碰釘子，NZKoz 非常堅持不要更動列表，Rails core team 不會 maintain 一份自己特有的國家列表，以免開了一個Taiwan特例，之後還會有別的國家也會要求修改，會沒完沒了。</p>
<p>到這裡已經卡關了，github 上面也已經不准許任何人<a href="http://github.com/rails/rails/commit/3353b85b0eae76bf36ae7c2f7b6adc1863278a8e#comments">留言</a>討論(大概也很難有結論)。文筆佳的 <a href="http://yllan.org/blog/archives/296">yllan</a> 跟 <a href="http://hlb.yichi.org/blog/2008/09/22/258">hlb</a> 先後寫了一篇英文 Blog 來表達我們的抗議，我也根據 lukhnos 的意見重新建了 <a href="http://github.com/ihower/country_and_region_select/tree/master">country_and_region_select plugin</a>，還把這個 plugin 跟 hlb 的文章(無恥地?絕望地?)貼到 <a href="http://www.rubyflow.com/items/935">RubyFlow</a> 去看能不能有點效果。</p>
<p>Anyway，正當萬念俱灰(?)，準備改行去寫 <a href="http://merbivore.com/">Merb</a> 時(?)，NZKoz 看到了 hlb&#8217;s blog，並在他自己的 blog 上貼了一篇<a href="http://www.koziarski.net/archives/2008/9/24/countries-and-controversies">善意的文章</a>，提供了幾個選項，於是我和 hlb、gugod 討論之後，提出了照 <a href="http://www-01.ibm.com/software/globalization/topics/writing/references.jsp">IBM Globalization guideline</a> 是最簡單的作法，不過以 framework 來說，沒有任何預設列表也許也是不錯的解套方式。NZKoz 比較喜歡我們後者的建議，後來也直接寫 E-mail 通知我們他最後的作法，Rails core team 是真的非常希望他們在這件事情上保持中立立場。</p>
<p>這件事一路 follow 到尾，心理壓力倒是不小，而且我也沒有很想管這件麻煩事啊(我很早就沒用 country_select helper 了，都自己建 country Model 處理 :p)，只是有以上這幾位關心這件事的朋友幫忙發聲/出主意，加上 NZKoz 的主動來信，才有了更進一步的改善，希望這樣的結果還算是讓大家(Taiwan Rails community?)可以接受。</p>
<img src="http://feeds.feedburner.com/~r/ihower/~4/413333668" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ihower.idv.tw/blog/archives/1770/feed</wfw:commentRss>
		<feedburner:origLink>http://ihower.idv.tw/blog/archives/1770</feedburner:origLink></item>
		<item>
		<title>主動攔截 Rails exception 錯誤</title>
		<link>http://feeds.feedburner.com/~r/ihower/~3/405355506/1773</link>
		<comments>http://ihower.idv.tw/blog/archives/1773#comments</comments>
		<pubDate>Sun, 28 Sep 2008 10:43:24 +0000</pubDate>
		<dc:creator>ihower</dc:creator>
		
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://ihower.idv.tw/blog/?p=1773</guid>
		<description><![CDATA[
喔，炸了。
相信以上畫面大家都不陌生，這是一個標準的 Rails app 錯誤頁面。雖然我們努力避免，但總是有出錯的時候，一個上 production mode 的專業 Rails app 絕不會痴痴地等待使用者告訴你網站炸了，而是要能夠主動通知及紀錄下這個錯誤例外(exception)，好讓我可以 trace error、fixed bug 甚至在發生錯誤沒多久就可以 E-mail 告訴這位使用者苦主發生了什麼事情。
解法有幾種：
1. 安裝 exceiption_notifition，這是個官方的基本 Plugin ，它會在發生例外時寄 email 通知你(們)。
2. 安裝 ExceptionLogger (作者 defunkt 也是 facebox 的作者 :p )，這個  Plugin 會紀錄到 database，並提供一個後台可以瀏覽。不過這個後台裝起來比較麻煩，例如你還得處理瀏覽權限等等。
3. 使用 Hoptoad 第三方服務，這是個由知名Rails團隊 thoughtbot 所提供的 Web service。申請帳號之後可以拿到 API key 及 Plugin，於是你的網站發生 exception 的時候就會自動將錯誤訊息送到 Hoptoad 收集起來。Hoptoad 提供了還蠻不錯的後台可以瀏覽。這個解法安裝最簡單，功能又很夠用，還可以統計及追蹤例外處理的情況，我個人十分推薦使用。
github 上應該還有其他的 Plugins 可以幫助你處理這個問題。anyway&#8230; 最糟的就是什麼都不做，讓使用者告訴你有東西炸了，然後你再去爬去找 [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://ihower.idv.tw/blog/wp-content/uploads/2008/09/rails-500.png" alt="" title="rails-500" width="440" class="aligncenter size-full wp-image-1774" /></p>
<p>喔，炸了。</p>
<p>相信以上畫面大家都不陌生，這是一個標準的 Rails app 錯誤頁面。雖然我們努力避免，但總是有出錯的時候，一個上 production mode 的專業 Rails app 絕不會痴痴地等待使用者告訴你網站炸了，而是要能夠主動通知及紀錄下這個錯誤例外(exception)，好讓我可以 trace error、fixed bug 甚至在發生錯誤沒多久就可以 E-mail 告訴這位使用者苦主發生了什麼事情。</p>
<p>解法有幾種：</p>
<p>1. 安裝 <a href="http://github.com/rails/exception_notification/tree">exceiption_notifition</a>，這是個官方的基本 Plugin ，它會在發生例外時寄 email 通知你(們)。</p>
<p>2. 安裝 <a href="http://github.com/defunkt/exception_logger/tree/master">ExceptionLogger</a> (作者 defunkt 也是 <a href="http://famspam.com/facebox">facebox</a> 的作者 :p )，這個  Plugin 會紀錄到 database，並提供一個後台可以瀏覽。不過這個後台裝起來比較麻煩，例如你還得處理瀏覽權限等等。</p>
<p>3. 使用 <a href="http://www.hoptoadapp.com/welcome">Hoptoad</a> 第三方服務，這是個由知名Rails團隊 <a href="http://www.thoughtbot.com/">thoughtbot</a> 所提供的 Web service。申請帳號之後可以拿到 API key 及 Plugin，於是你的網站發生 exception 的時候就會自動將錯誤訊息送到 Hoptoad 收集起來。Hoptoad 提供了還蠻不錯的後台可以瀏覽。這個解法安裝最簡單，功能又很夠用，還可以統計及追蹤例外處理的情況，我個人十分推薦使用。</p>
<p>github 上應該還有其他的 Plugins 可以幫助你處理這個問題。anyway&#8230; 最糟的就是什麼都不做，讓使用者告訴你有東西炸了，然後你再去爬去找 log 檔 :)</p>
<img src="http://feeds.feedburner.com/~r/ihower/~4/405355506" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ihower.idv.tw/blog/archives/1773/feed</wfw:commentRss>
		<feedburner:origLink>http://ihower.idv.tw/blog/archives/1773</feedburner:origLink></item>
		<item>
		<title>和多繽紛樂@Yahoo! Open Hack Day</title>
		<link>http://feeds.feedburner.com/~r/ihower/~3/399645967/1771</link>
		<comments>http://ihower.idv.tw/blog/archives/1771#comments</comments>
		<pubDate>Mon, 22 Sep 2008 09:35:00 +0000</pubDate>
		<dc:creator>ihower</dc:creator>
		
		<category><![CDATA[Rails]]></category>

		<category><![CDATA[和多]]></category>

		<guid isPermaLink="false">http://ihower.idv.tw/blog/?p=1771</guid>
		<description><![CDATA[我們得獎了！和多繽紛樂是敝社參加 Y! Open Hack Day 2008 的作品，它是個賓果機產生器，你可以將各式資料扔進去，拉下拉霸之後就會亂數回答一個結果。除了直接提供選項之外，也可以選擇 Yahoo! 生活+、Yahoo! 知識+、Yahoo! 電影、Yahoo! 拍賣、Flickr 相簿、無名熱門相簿、Diggirl 熱門相簿等等資料。


和多獲佳作十萬元

和多與Y!共同創辦人David Flio的合照

會場音樂很吵(剛好我們的位置被安排在音響前方)、正妹很漂亮、食物飲料不缺、網路雖不快但也算順暢、贈品還不錯豐富，Y! 辦了一場想要大家認真 Coding，但又請了樂團炒熱氣氛的 Party&#8230; XD 對我來說，最 high 的不是台上怎麼玩，而是這充分 teamwork 的黑客松過程，在這兩天內和多瘋狂地 commit，一想到想要做什麼，分工一下不用多久就做出來了，我們也在會場內提早公開這個網站讓大家玩(Agile feedback!!)。
雖然超級疲累，不過得獎真的很爽 :D
]]></description>
			<content:encoded><![CDATA[<p>我們得獎了！<a href="http://bingo.handlino.com">和多繽紛樂</a>是<a href="http://handlino.com">敝社</a>參加 <a href="http://hackday.ithome.com.tw/yahoo/">Y! Open Hack Day 2008</a> 的作品，它是個賓果機產生器，你可以將各式資料扔進去，拉下拉霸之後就會亂數回答一個結果。除了直接提供選項之外，也可以選擇 Yahoo! 生活+、Yahoo! 知識+、Yahoo! 電影、Yahoo! 拍賣、Flickr 相簿、無名熱門相簿、Diggirl 熱門相簿等等資料。</p>
<div>
<a href="http://www.flickr.com/photos/tempofeng/2876359548"><img src="http://farm4.static.flickr.com/3259/2876359548_678a9f464e.jpg" width="480"></a></p>
<p style="font-style: italic;">和多獲佳作十萬元</p>
<p><a href="http://www.flickr.com/photos/gugod/2878172174/" title="Handlino and David Filo by gugod, on Flickr"><img src="http://farm4.static.flickr.com/3005/2878172174_3f315c87be.jpg" width="480" alt="Handlino and David Filo" /></a></p>
<p style="font-style: italic;">和多與Y!共同創辦人David Flio的合照</p>
</div>
<p>會場音樂很吵(剛好我們的位置被安排在音響前方)、正妹很漂亮、食物飲料不缺、網路雖不快但也算順暢、贈品還不錯豐富，Y! 辦了一場想要大家認真 Coding，但又請了樂團炒熱氣氛的 Party&#8230; XD 對我來說，最 high 的不是台上怎麼玩，而是這充分 teamwork 的黑客松過程，在這兩天內和多瘋狂地 commit，一想到想要做什麼，分工一下不用多久就做出來了，我們也在會場內提早公開這個網站讓大家玩(Agile feedback!!)。</p>
<p>雖然超級疲累，不過得獎真的很爽 :D</p>
<img src="http://feeds.feedburner.com/~r/ihower/~4/399645967" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ihower.idv.tw/blog/archives/1771/feed</wfw:commentRss>
		<feedburner:origLink>http://ihower.idv.tw/blog/archives/1771</feedburner:origLink></item>
		<item>
		<title>最佳化 ActiveRecord SQL 查詢</title>
		<link>http://feeds.feedburner.com/~r/ihower/~3/383248983/1766</link>
		<comments>http://ihower.idv.tw/blog/archives/1766#comments</comments>
		<pubDate>Thu, 04 Sep 2008 13:29:28 +0000</pubDate>
		<dc:creator>ihower</dc:creator>
		
		<category><![CDATA[Performance]]></category>

		<category><![CDATA[Programming]]></category>

		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://ihower.idv.tw/blog/?p=1766</guid>
		<description><![CDATA[Update(2008/9/5) 補充 named_scope 也可以用在 :select，感謝 tsechingho++
要看 AciveRecord 產生的 SQL 是什麼，除了可以直接 tail -f log/development.log 之外，也可以在 script/console 的情況下透過以下指令直接把 log 直接顯示出來：

ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Base.clear_active_connections!

如此便可以好好在 console 的環境下實驗 ActiveRecord 囉。
我看到關於 ActiveRecord SQL 查詢最佳化方式有這幾種：
1. 使用 :select 
只撈需要用到的欄位，特別是如果不需要用到的 text 或  binary 欄位請排除。

Event.find(:all, :select => "id, title, description")

搭配 named_scope 我們可以把常用的 :select 預先設定好，例如：

class User < ActiveRecord::Base
  named_scope :short, :select => &#8220;id, name, email&#8221;
end
User.short.find(:all)

2. [...]]]></description>
			<content:encoded><![CDATA[<p>Update(2008/9/5) 補充 named_scope 也可以用在 :select，感謝 tsechingho++</p>
<p>要看 AciveRecord 產生的 SQL 是什麼，除了可以直接 tail -f log/development.log 之外，也可以在 script/console 的情況下透過以下指令直接把 log 直接顯示出來：<br />
<code><br />
ActiveRecord::Base.logger = Logger.new(STDOUT)<br />
ActiveRecord::Base.clear_active_connections!<br />
</code><br />
如此便可以好好在 console 的環境下實驗 ActiveRecord 囉。</p>
<p>我看到關於 ActiveRecord SQL 查詢最佳化方式有這幾種：</p>
<h3>1. 使用 :select </h3>
<p>只撈需要用到的欄位，特別是如果不需要用到的 text 或  binary 欄位請排除。<br />
<code><br />
Event.find(:all, :select => "id, title, description")<br />
</code></p>
<p>搭配 named_scope 我們可以把常用的 :select 預先設定好，例如：<br />
<code><br />
class User < ActiveRecord::Base<br />
  named_scope :short, :select => &#8220;id, name, email&#8221;<br />
end</p>
<p>User.short.find(:all)<br />
</code></p>
<h3>2. 使用 :include </h3>
<p>使用 :include 避免 N+1 次 queries 的問題。</p>
<p><code><br />
  @events = Event.find(:all, :include => [:group] )<br />
</code></p>
<p><code><br />
  @events.each do |e|<br />
      e.group.title<br />
   end<br />
</code></p>
<p>如果沒有加 :include 把相關的 groups 一起載入，在迴圈中就會產生 @event.size 次對 group 的個別 SQL 查詢，會非常傷。加了 :include 之後總共只需查詢兩次。</p>
<p>另外一個比較少人知道的是，在設定 Model associations 時，如果有很明顯的情境一定會順道載入二階 association model，可以設定 :include 在 has_many, belongs_to, has_one 上面，例如：</p>
<p><code><br />
class User < ActiveRecord::Base<br />
 has_one :foo, :include => [:bar]<br />
end<br />
</code></p>
<p>如此便會在載入 @user.foo 的同時，也會提早載入 @user.foo.bar。</p>
<h3>3. 資料庫索引</h3>
<p>針對 foreign key 要加上資料庫索引 index。在 migration 上透過 add_index 就可以加上去了。</p>
<h3>4. 特定情況下可用 :joins 取代 :include</h3>
<p>在只需要用到 :conditions 而不需要載入該 model 的情況下，可以用 :joins 取代 :include。<br />
<code><br />
  Group.find(:all, :include => [ :group_memberships ], :conditions => [ "group_memberships.created_at > ?", Time.now - 30.days ] )<br />
</code><br />
因為其中會載入 group_memberships model 只是為了加條件式，而沒有要撈出裡面的資料，所以可以改用 :joins，這其中的差異你看產生出的SQL就知道了 :)</p>
<p><code><br />
  Group.find(:all, :joins => [ :group_memberships ], :conditions => [ "group_memberships.created_at > ?", Time.now - 30.days ] )<br />
</code></p>
<h3>5. 自己寫 SQL </h3>
<p>ActiveRecord 可以直接寫 find_by_sql。</p>
<h3>6. denormalization 逆正規化</h3>
<p>當資料非常多，又要常常查詢其中計算的結果，這時可以考慮使用逆正規化的手法，將計算的結果也當做資料存起來。</p>
<p>一個最常見最基本的用法就是計算總數了，例如以下的例子可以解決需要常常查詢 @topic.posts.size 該篇主題有多少文章的情境：</p>
<p><code><br />
class Topic < ActiveRecord::Base<br />
 has_many :posts<br />
end</p>
<p>class Posts < ActiveRecord::Base<br />
   belongs_to :topic, :counter_cache => true<br />
end<br />
</code></p>
<p>我們會在 Topic model 新增一個欄位 posts_count，然後 :counter_cache 就會幫我們在新增刪除 Post 時，自動更新所屬 Topic 的 posts_count 欄位資料。這時只要打 @topic.posts.size 就會直接回傳 posts_count，而無需每次都再發一個 SQL query 去 count 有多少筆 posts。</p>
<p>其他逆正規化的方式也包括了統計結算報表等，我們把需要複雜計算的的結果(可以透過非同步的機制如 cron 定期去觸發) 存到 Report model，這樣使用者直接撈 Report 的結果即可。</p>
<img src="http://feeds.feedburner.com/~r/ihower/~4/383248983" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ihower.idv.tw/blog/archives/1766/feed</wfw:commentRss>
		<feedburner:origLink>http://ihower.idv.tw/blog/archives/1766</feedburner:origLink></item>
		<item>
		<title>Rails plugins 投影片</title>
		<link>http://feeds.feedburner.com/~r/ihower/~3/372762887/1762</link>
		<comments>http://ihower.idv.tw/blog/archives/1762#comments</comments>
		<pubDate>Sat, 23 Aug 2008 15:10:11 +0000</pubDate>
		<dc:creator>ihower</dc:creator>
		
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://ihower.idv.tw/blog/?p=1762</guid>
		<description><![CDATA[釋出今天在 COSCUP 2008 的投影片，PDF請按這裡下載
Rails Plugins
View SlideShare presentation or Upload your own. (tags: plugin rails)

雖然還蠻走馬看花的，不過20分鐘的 talk 也夠把(我所知道的)常用的 Rails Plugins 都介紹過了一遍，其中也包含了幾個和多自產自用的 open source plugin :)
誠如我投影片所說，熟悉常用的 Rails Plugins 跟熟悉 core 一樣重要。不過投影片沒說的是：Plugin 的地雷可比 core 來的多，因此除了會安裝使用之外，最好也要具備基本 Ruby meta-programming 的能力來大概看懂這些 Plugins 是怎麼做的。
BTW，如果投影片對你有幫助的話，希望可以聽到您的留言鼓勵，或是推薦一下還有什麼好用 Rails plugin :p
]]></description>
			<content:encoded><![CDATA[<p>釋出今天在 <a href="http://coscup.org/2008/">COSCUP 2008</a> 的投影片，<a href="/presentation/rails-plugins-coscup-823.pdf">PDF請按這裡下載</a></p>
<div style="width:425px;text-align:left" id="__ss_566360"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/ihower/rails-plugins-presentation?src=embed" title="Rails Plugins">Rails Plugins</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slideshare.net/swf/ssplayer2.swf?doc=railspluginscoscup823-1219503333843775-8&#038;stripped_title=rails-plugins-presentation" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slideshare.net/swf/ssplayer2.swf?doc=railspluginscoscup823-1219503333843775-8&#038;stripped_title=rails-plugins-presentation" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object>
<div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View SlideShare <a style="text-decoration:underline;" href="http://www.slideshare.net/ihower/rails-plugins-presentation?src=embed" title="View Rails Plugins on SlideShare">presentation</a> or <a style="text-decoration:underline;" href="http://www.slideshare.net/upload?src=embed">Upload</a> your own. (tags: <a style="text-decoration:underline;" href="http://slideshare.net/tag/plugin">plugin</a> <a style="text-decoration:underline;" href="http://slideshare.net/tag/rails">rails</a>)</div>
</div>
<p>雖然還蠻走馬看花的，不過20分鐘的 talk 也夠把(我所知道的)常用的 Rails Plugins 都介紹過了一遍，其中也包含了幾個<a href="http://handlino.com">和多</a>自產自用的 open source plugin :)</p>
<p>誠如我投影片所說，熟悉常用的 Rails Plugins 跟熟悉 core 一樣重要。<strong>不過投影片沒說的是：Plugin 的地雷可比 core 來的多</strong>，因此除了會安裝使用之外，最好也要具備基本 Ruby meta-programming 的能力來大概看懂這些 Plugins 是怎麼做的。</p>
<p>BTW，如果投影片對你有幫助的話，希望可以聽到您的留言鼓勵，或是推薦一下還有什麼好用 Rails plugin :p</p>
<img src="http://feeds.feedburner.com/~r/ihower/~4/372762887" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ihower.idv.tw/blog/archives/1762/feed</wfw:commentRss>
		<feedburner:origLink>http://ihower.idv.tw/blog/archives/1762</feedburner:origLink></item>
		<item>
		<title>誰說人是理性的</title>
		<link>http://feeds.feedburner.com/~r/ihower/~3/363231453/1760</link>
		<comments>http://ihower.idv.tw/blog/archives/1760#comments</comments>
		<pubDate>Tue, 12 Aug 2008 20:11:35 +0000</pubDate>
		<dc:creator>ihower</dc:creator>
		
		<category><![CDATA[Books]]></category>

		<category><![CDATA[社會經濟]]></category>

		<guid isPermaLink="false">http://ihower.idv.tw/blog/?p=1760</guid>
		<description><![CDATA[
好久沒看經濟類的書，這本書從人的非理性層面切入，並用有趣的實驗導出令人驚奇的結果，還蠻有趣的。

比較才能做決定。提供 A,-A, B 三種選項，其中 A,B 無法比較，A 比 -A 好。實驗出人們會 75% 去選A，即使 A,B 無法比較。這個 -A 的效果稱作誘餌效應。
定錨點的影響，隨機的定錨點先入為主影響你的決策。
只要有&#8221;免費&#8221;這個字眼，就難以抗拒。2塊降價變1塊跟1塊變免費的效果是天差地遠。
社會規範與市場規範，只要一提到錢，就變成市場規範。(錢不是萬能)
不同的情緒狀態所做的決定會不同，高張的情緒容易失去理智。
預先承諾機制可以幫助解決拖延問題
如果擁有某樣東西，就會對這樣東西估價較高。所有權會讓你的損失趨避心理變得強烈，只想到失去時的損失而忘記會獲得的利益。(由簡入奢易，由奢入簡難)
人會盡量保留多一點選擇，即使這樣得付出極高的代價。就像父母匆忙帶著小孩到處學才藝，四處奔走不僅讓人緊張，也不符合經濟效益。很多時候在兩個相似的選項中做選擇，猶豫的時間代價比兩者細微的差異損失更多。
預期心理影響感官認知。但若事後知道內情也不會影響一開始的經驗。
安慰劑的暗示效果，因為人們相信它有效，所以也出現治療效果。價格因素也會影響效用，貴的比較有效。關於醫療與安慰劑的道德問題是個很大的議題。
一旦有機會，許多誠實的人都會欺騙，一旦決定作弊，卻不會受被逮到的風險高低所影響，對小的欺騙來說不會思考成本效益分析。有趣的是如果有任何誠實概念進到腦子(例如回憶十戒或簽署榮譽制度)，就會容易保持誠實。
當人們騙的不是現金的時候，欺騙行為較容易發生。甚至即使改成用代幣(多一層轉換手續而已，還是可以換現金)，欺騙的比例也會大增。當交易媒介與貨幣無關時，我們就更容易合理化自己的行為。
行為經濟學了解人容易受到情境、不相關的情緒等不理性因素影響，所以希望利用工具、方法與制度來幫助我們提高決策品質。

我想這本書真正精采的地方在作者設計的這些有趣實驗，作為一本通俗讀物還蠻值得推薦的。不過我在想如果是科普觀點：認知心理學家、生物學家等科學家應該會有更好的解釋為什麼人類會這麼做吧，我自己是認為&#8221;人&#8221; 的這些非理性決策不是為了找到最佳解，而只是極小化選到最差解的可能 (也許就代表死亡)罷了。
]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.books.com.tw/exep/assp.php/ihower/exep/prod/booksfile.php?item=0010405763"><img src="http://www.books.com.tw/exep/lib/image.php?image=http://addons.books.com.tw/G/001/3/0010405763.jpg&#038;width=200&#038;height=280&#038;quality=80"></a><br />
好久沒看經濟類的書，這本書從人的非理性層面切入，並用有趣的實驗導出令人驚奇的結果，還蠻有趣的。</p>
<ol>
<li>比較才能做決定。提供 A,-A, B 三種選項，其中 A,B 無法比較，A 比 -A 好。實驗出人們會 75% 去選A，即使 A,B 無法比較。這個 -A 的效果稱作誘餌效應。</li>
<li>定錨點的影響，隨機的定錨點先入為主影響你的決策。</li>
<li>只要有&#8221;免費&#8221;這個字眼，就難以抗拒。2塊降價變1塊跟1塊變免費的效果是天差地遠。</li>
<li>社會規範與市場規範，只要一提到錢，就變成市場規範。(錢不是萬能)</li>
<li>不同的情緒狀態所做的決定會不同，高張的情緒容易失去理智。</li>
<li>預先承諾機制可以幫助解決拖延問題</li>
<li>如果擁有某樣東西，就會對這樣東西估價較高。所有權會讓你的損失趨避心理變得強烈，只想到失去時的損失而忘記會獲得的利益。(由簡入奢易，由奢入簡難)</li>
<li>人會盡量保留多一點選擇，即使這樣得付出極高的代價。就像父母匆忙帶著小孩到處學才藝，四處奔走不僅讓人緊張，也不符合經濟效益。很多時候在兩個相似的選項中做選擇，猶豫的時間代價比兩者細微的差異損失更多。</li>
<li>預期心理影響感官認知。但若事後知道內情也不會影響一開始的經驗。</li>
<li>安慰劑的暗示效果，因為人們相信它有效，所以也出現治療效果。價格因素也會影響效用，貴的比較有效。關於醫療與安慰劑的道德問題是個很大的議題。</li>
<li>一旦有機會，許多誠實的人都會欺騙，一旦決定作弊，卻不會受被逮到的風險高低所影響，對小的欺騙來說不會思考成本效益分析。有趣的是如果有任何誠實概念進到腦子(例如回憶十戒或簽署榮譽制度)，就會容易保持誠實。</li>
<li>當人們騙的不是現金的時候，欺騙行為較容易發生。甚至即使改成用代幣(多一層轉換手續而已，還是可以換現金)，欺騙的比例也會大增。當交易媒介與貨幣無關時，我們就更容易合理化自己的行為。</li>
<li>行為經濟學了解人容易受到情境、不相關的情緒等不理性因素影響，所以希望利用工具、方法與制度來幫助我們提高決策品質。</li>
</ol>
<p>我想這本書真正精采的地方在作者設計的這些有趣實驗，作為一本通俗讀物還蠻值得推薦的。不過我在想如果是科普觀點：認知心理學家、生物學家等科學家應該會有更好的解釋為什麼人類會這麼做吧，我自己是認為&#8221;人&#8221; 的這些非理性決策不是為了找到最佳解，而只是極小化選到最差解的可能 (也許就代表死亡)罷了。</p>
<img src="http://feeds.feedburner.com/~r/ihower/~4/363231453" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ihower.idv.tw/blog/archives/1760/feed</wfw:commentRss>
		<feedburner:origLink>http://ihower.idv.tw/blog/archives/1760</feedburner:origLink></item>
		<item>
		<title>Rails plugins@COSCUP 2008</title>
		<link>http://feeds.feedburner.com/~r/ihower/~3/352752504/1759</link>
		<comments>http://ihower.idv.tw/blog/archives/1759#comments</comments>
		<pubDate>Fri, 01 Aug 2008 16:10:35 +0000</pubDate>
		<dc:creator>ihower</dc:creator>
		
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://ihower.idv.tw/blog/?p=1759</guid>
		<description><![CDATA[Update(2008/8/23): 今天的投影片請點此下載。

一年一度的 COSCUP 聚會又來了，這次我也投了一場 Rails plugins used/created in Registrano 約二十分鐘的演講。題目顧名思義就是介紹 Registrano 所用到的 Rails open source plugins，就是因為有這麼多好用的開放原始碼插件，才得已讓 Registrano 這個網路服務能夠敏捷地構建出來。
敝社和多這次同時也贊助了活動網站設計，當然還有報名網頁(Registrano)。除了我的 talk，還有 xdite 也會分享 Rails 2.1 的新功能介紹。希望大家多多捧場。
如果您對 Registrano 這項服務有任何想法，屆時也歡迎給予指教，並致贈您 Registrano 折價卷。
]]></description>
			<content:encoded><![CDATA[<p>Update(2008/8/23): 今天的投影片<a href="http://ihower.idv.tw/blog/archives/1762">請點此下載</a>。</p>
<p><a href="http://coscup.org/2008/"><img src="http://coscup.org/2008/wp-content/themes/coscup/images/h1.gif" alt="COSCUP" /></a></p>
<p>一年一度的 <a href="http://coscup.org/2008/">COSCUP</a> 聚會又來了，這次我也投了一場 <strong>Rails plugins used/created in Registrano</strong> 約二十分鐘的演講。題目顧名思義就是介紹 <a href="http://registrano.com">Registrano</a> 所用到的 Rails open source plugins，就是因為有這麼多好用的開放原始碼插件，才得已讓 Registrano 這個網路服務能夠敏捷地構建出來。</p>
<p>敝社<a href="http://zh.handlino.com">和多</a>這次同時也贊助了活動網站設計，當然還有報名網頁(Registrano)。除了我的 talk，還有 <a href="http://blog.xdite.net/">xdite</a> 也會分享 Rails 2.1 的新功能介紹。希望大家多多捧場。</p>
<p>如果您對 Registrano 這項服務有任何想法，屆時也歡迎給予指教，並致贈您 Registrano 折價卷。</p>
<img src="http://feeds.feedburner.com/~r/ihower/~4/352752504" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://ihower.idv.tw/blog/archives/1759/feed</wfw:commentRss>
		<feedburner:origLink>http://ihower.idv.tw/blog/archives/1759</feedburner:origLink></item>
	</channel>
</rss>
