Ruby Tuesday Returns 開始報名

各位喜愛 Ruby 的朋友們,Ruby Tuesday 復出首場開始報名囉,詳細資料請前往報名網頁,時間地點是 2008/11/25(二) PM7~9 台北市果子咖啡。

嚷嚷說要重辦 Ruby Tuesday 好久了,因為覺得辦活動挺麻煩的,所以一直都只是嘴上說說…. XD
直到兩個禮拜前布丁大人去買了 ruby.tw 這個響當當的網址,在 hlb 跟 gugod 聯手凹(鼓勵?)的情況下,就決定衝了。

首先是要找講者,沒想到還蠻順利的 :p 賣一下人情就把三位講者拖下水了(?) 其實大家都非常樂見能有一個社群活動可以分享技術、聯絡感情,所以都二話不說就答應了,甚至還說可以贊助活動費用(怎麼好意思呢,都已經沒有講者車馬費了XD),真是超級感謝。

lukhnos 將會分享他們公司如何使用 Ruby script 來取代一些 shell script 的工作。tsechingho 會介紹及比較 substructspree 這兩套 Rails E-Commerce 平台。contagious 則是講解 DataMapper 這套比 ActiveRecord 厲害的 ORM 工具,同時他也預約了下一場 Ruby Tuesday 會繼續介紹 DataMapper 的好夥伴 Merb web framework。

Ruby Taiwan 第一次辦社群活動,請各位舊雨新知多多捧場囉,我們會出沒在 IRC freenode #ruby.tw 頻道,歡迎多多指教。

MerbCamp 2008

身歷其境的看了兩天的 MerbCamp,主辦單位提供的 Webcast 非常流暢,幾乎沒有 delay。(怎麼會這麼厲害呢?! 我連 youtube 或 Y! Live 沒有不 delay 的啊…orz),讓我在家就可以參加地球另一端的研討會,真是棒極了。(雖然英文聽的哩哩落落,不過還是很爽。It’s free!)

主辦單位也在 IRC 上開了 #merbcamp 頻道,講者們似乎也都在上面,隨時都有一些 link 丟出來可以看看,有什麼問題也可在上面提出(例如: webcast 沒聲音或沒影像等轉撥問題反應)、講者QA時間也可以從 IRC 上面問,主辦單位會幫你問講者,非常有參與性。

以下整理自我在twitter的簡短 Merb 心得:

  • Merb router’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 rails upgrade. :)
  • MerbAuth’s “strategy” looks good to support multiple login methods(password, open id…etc) in the same app.
  • Although merb is ORM-agnostic and JavaScript library agnostic, but everybody loves DataMapper and JQuery ;)
  • Merb team will not implement RJS. RJS sucks!
  • It seems that Merb::Plugins is very different from rails plugins: Merb has hooks and public/stable API ;)
  • Merb really hates monkeypatching and alias_method_chain.
  • Rails has no public/private/plugin API, every method is API. That’s why rails developer must use monkeypatching and alias_method_chain.
  • Ruby is not slow! merb is faster than PHP (frameworks). see benchmark.

也有人做了詳細的筆記:MerbCamp Day1, MerbCamp Day2,最後一場 Keynote 的 Merb Performance Benchmarks 特別有意思:Merb without template 與 pure PHP 平分秋色,Merb with template 就大勝 CodeIgniter 和 CakePHP 這兩套 PHP web framework 了….. XD 找了一下這幾套的 benchmarks 比較,發現連 Rails 還不算太慢麻,比 Zend Framework 跟 CakePHP 都還快上不少,所以比較起來應該是 Static >> PHP > Merb >> CodeIgniter > Rails >> Zend Framework >> CakePHP。

投影片大部分在 slideshare 上可以下載的到。同時間 Merb 也將發佈 1.0 RC (即 0.9.9) 版本,所有 API 都將定下來(Merb team 非常強調保證他們的 public API will be stable and backwards compatibility for 1.x,我想大家都被 Rails 一升級就有 plugin 會爛掉非常感冒),相信在過不久就會有越來越多的文件可以看(目前還很缺啊!),是個不錯的進場時機。

物件導向程式的九個體操練習

最近在翻 The ThoughtWorks Anthology(知名軟體顧問公司 Thoughtworks 出的文集),裡面有篇 Object Calisthenics 蠻有意思的。

好的物件導向設計很難,我們都很同意何謂好的設計原則:高內聚力(cohesion)、低耦合(loose coupling)、不重複程式(Don’t Repeat Yourselp)、封裝(encapsulation)、可測試性、易閱讀性等等,但是實際寫的時候卻不容易化身為一行行的程式碼。這篇作者列了九條規則,並建議你練習寫個千行程式嚴格遵守看看,用以改善你的OO實作能力。

初次看到這九條時覺得有點誇張,但其實濃縮了不少OO想法在裡面,如果有閱讀過重構或物件導向設計原則等概念,應該能夠聯想到很多東西,挺有趣的。

1. 每個函式裡面只能有一層縮排,如果需要多一層,請多寫一個 method 去呼叫。

這個規則其實就是要求嚴格遵守 Compose Method:將邏輯操作轉換為細目等級相同的步驟,避免過深的邏輯而無法迅速了解,相信大家應該都有看(寫)過M型程式吧 :p

2. 不要使用到 else 這個關鍵字。

避免寫出複雜的 nested conditional 程式。不論是”重構“或是”重構-向範式前進“這兩本書,都有很多篇幅花在討論如何簡化條件邏輯,作法包括

a. 重構一書提到的 Replace Nested Conditional with Guard Clauses 方式,直接使用 return 返回,不要再 else 了。

b. 請愛用 Ternary Operator:也就是 boolean-expression ? expr1 : expr2。很多簡單的 if else 都可以用 Ternary Operator 簡化到一行一目了然。舉個 Ruby code 例子:


if ( is_something )
"foo"
else
"bar"
end

如果改成三重操作子就俐落多了:

( is_something )? "foo" : "bar"

另外初心者也常寫出根本不需要 if else 的情況:

def is_foobar
if ( a > 0 )
return true
else
return false
end
end

其實只需要這樣就可以了:

def is_foobar
( a > 0 )
end

c. 第三招要先念點書,請善用物件導向的多型(polymorphism)能力,請參考設計模式的 Strategy pattern 或重構的 Replace Conditional with Polymorphism

閱讀全文〈物件導向程式的九個體操練習〉

如何使用 memcached 做快取

關於 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 (如果有超過一台的 memcached server 的話)。Ruby 的 client 目前檯面上有幾套 1. memcache-client 2. fiveruns fork 版 memcache-client,針對 Hasing 的部份用C改寫了 3. 使用 libmemcached 的超快 memcached

有趣的是,不需要 client library,memcached 是可以直接 telnet 127.0.0.1 11211 的。telnet 之後打 stats 可以得到一些統計資料,除了目前共有多少筆資料跟共用多少空間之外,重要的有 cmd_get 跟 cmd_hits,就可以得出 cache hit ratio,這個數字應該努力到九成以上。另外還有你的 cmd_set 應該超過 cmd_get,

其他的 memcached 標準操作有 SET (新增或是更新一個值)、ADD(只有在該key不存在時,才會新增快取資料成功)、REPLACE(只有在該key已經存在時,才會更新資料成功)、GET(拿快取資料)。

在考慮使用 memcached 前,要知道它不是你系統中唯一的 cache,HTML 的整頁快取應該用 Web server、純 SQL query result 可以用 MySQL 內建 Query Cache,設定很簡單,效果很不錯 (Cache Performance Comparison。我自己的心得是很多時候你想要快取的物件其實並不是一個 SQL query 就可以搞定的,而是多個 SQL query 才計算出來,這時候去做純快取 SQL query result 我個人覺得也許不是很有意義,Rails 這部份就有人實做了query_memcached。。

另外要注意的是 memcached 並不是 persistent data store,只要一關掉 memcached server,裡面的資料就會通通不見,如果要拿來儲存 session authentication 資料要特別小心。

寫 memcached 程式的第一個問題是找出什麼資料需要快取? 一個常見的問題是我該快取 HTML fragment 還是純資料結構? 如果你操作介面只有一處用到,我們可以只快取 HTML fragment 即可,不然其實規模稍大的網站其實兩者都可以快取起來。

撰寫使用 memcached 程式的基本模式就是,先查看有沒有 key-value,有就把快取資料讀出來,沒有就運算結果後存到 memcached sever。這部份算是簡單的。真正困難的事情有兩件:一是清除過期的快取資料(expire),二是Key的命名。
閱讀全文〈如何使用 memcached 做快取〉

實戰敏捷開發 Practices of an Agile Developer (3) 測試篇

上一章談了來自客戶的 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 (差一點差很多)

在我這台沒問題啊,為什麼換一台電腦就不對了? 只要換一個平台(即使是不同版本的作業系統),不同就是不同,而太晚發現這樣的問題要修理是非常麻煩的,尤其是正要 release 的時候才發現它沒辦法在某某你想要的平台上執行。

我們當然可以要求 QA team 要在不同平台上測試,但是如果他們只是手動測試,就不如自動測試來的及早發現。我們已經會在 commit 程式前在自己電腦上執行一次 unit testing,現在要做的事情是要在你所要支援的不同平台、不同版本上再測試一次。不過好累啊,這時候就必須靠 continuous integration 工具來幫忙,每當有人 commit 時,這個工具就會自動 checkout 出來執行測試,我們分別在不同平台(例如可以使用 VMware 或 Virtual PC)上設定好這個工具來做自動化測試。

Automate Acceptance Testing (自動化驗收測試)

重要的商業邏輯除了 unit testing,還需要驗收測試獨立於所有程式之外,而且客戶必須親自驗證這個結果。也因為因此,我們需要一個工具讓客戶也可以新增編輯跟修改驗收測試(without coding),

這本書介紹的工具是 fit.c2.com/,它使用 HTML table 當作定義的介面,客戶可以直接編輯加入新的功能,接著加入可能的輸入與正確的預期值。然後 developer 再根據這個 table 產生 fixtures 資料,並比對測試結果是否成功。

感覺像是協力式的 unit testing,你還是必須自己寫測試,只是必須有別人提供你什麼是正確答案。

Measure Real Progress (測量真正的進度)

紀錄花了多久做事提供了很好的 feedback,可以幫助專案計畫、估計跟效率測量。但是一般常用的 timesheet 多半用於薪水用途而非真正花費的時間,這點要特別注意。另外常用的紀錄完成百分比,作者也認為很沒用。一個比較好的方式是紀錄 1.估計多少時間 2.已經花了多少時間 3.估計還需要多少時間來完成。根據真正花了多少時間的經驗,加以比對一開始的估計值,可以獲得很好的經驗用於估計下一個類似的任務。

紀錄真正的時數對於使用 backlog(要完成的任務清單)和 Iteration 也非常重要,如果剩餘的時間超過這次 Iteration 了,就知道必須移動某些任務到下一個 Iteration,反之則有時間多加工作。

最後是注意紀錄的時間單位,以分鐘太細了,以週就太粗囉。我們的經驗是超過一天的 Ticket(Issue) 應該都可以想辦法拆小,1hr、2hr、4hr、8hr 應該是不錯的範圍。

Listen to Users (聆聽使用者)

作者在這章最後特別提了使用者的回饋。即使有寫測試程式,我們還是很容易忽略來自真正使用者的聲音。每一個使用者的抱怨都有其道理,盡量試著找出真正的問題,而不是怪罪使用者不懂、不了解系統如何操作。
程式Bug、文件Bug、使用者會認知錯誤也要算是Bug。而不是讓客服人員回答說:喔,那不是Bug, 你犯了一個大家都會犯的錯誤。即使聽起來很笨,也應該去試著聆聽。