和多繽紛樂@Yahoo! Open Hack Day

我們得獎了!和多繽紛樂敝社參加 Y! Open Hack Day 2008 的作品,它是個賓果機產生器,你可以將各式資料扔進去,拉下拉霸之後就會亂數回答一個結果。除了直接提供選項之外,也可以選擇 Yahoo! 生活+、Yahoo! 知識+、Yahoo! 電影、Yahoo! 拍賣、Flickr 相簿、無名熱門相簿、Diggirl 熱門相簿等等資料。

和多獲佳作十萬元

Handlino and David Filo

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

會場音樂很吵(剛好我們的位置被安排在音響前方)、正妹很漂亮、食物飲料不缺、網路雖不快但也算順暢、贈品還不錯豐富,Y! 辦了一場想要大家認真 Coding,但又請了樂團炒熱氣氛的 Party… XD 對我來說,最 high 的不是台上怎麼玩,而是這充分 teamwork 的黑客松過程,在這兩天內和多瘋狂地 commit,一想到想要做什麼,分工一下不用多久就做出來了,我們也在會場內提早公開這個網站讓大家玩(Agile feedback!!)。

雖然超級疲累,不過得獎真的很爽 :D

最佳化 ActiveRecord SQL 查詢

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 => "id, name, email"
end

User.short.find(:all)

2. 使用 :include

使用 :include 避免 N+1 次 queries 的問題。


@events = Event.find(:all, :include => [:group] )


@events.each do |e|
e.group.title
end

如果沒有加 :include 把相關的 groups 一起載入,在迴圈中就會產生 @event.size 次對 group 的個別 SQL 查詢,會非常傷。加了 :include 之後總共只需查詢兩次。

另外一個比較少人知道的是,在設定 Model associations 時,如果有很明顯的情境一定會順道載入二階 association model,可以設定 :include 在 has_many, belongs_to, has_one 上面,例如:


class User < ActiveRecord::Base has_one :foo, :include => [:bar]
end

如此便會在載入 @user.foo 的同時,也會提早載入 @user.foo.bar。

3. 資料庫索引

針對 foreign key 要加上資料庫索引 index。在 migration 上透過 add_index 就可以加上去了。

4. 特定情況下可用 :joins 取代 :include

在只需要用到 :conditions 而不需要載入該 model 的情況下,可以用 :joins 取代 :include。

Group.find(:all, :include => [ :group_memberships ], :conditions => [ "group_memberships.created_at > ?", Time.now - 30.days ] )

因為其中會載入 group_memberships model 只是為了加條件式,而沒有要撈出裡面的資料,所以可以改用 :joins,這其中的差異你看產生出的SQL就知道了 :)


Group.find(:all, :joins => [ :group_memberships ], :conditions => [ "group_memberships.created_at > ?", Time.now - 30.days ] )

5. 自己寫 SQL

ActiveRecord 可以直接寫 find_by_sql。

6. denormalization 逆正規化

當資料非常多,又要常常查詢其中計算的結果,這時可以考慮使用逆正規化的手法,將計算的結果也當做資料存起來。

一個最常見最基本的用法就是計算總數了,例如以下的例子可以解決需要常常查詢 @topic.posts.size 該篇主題有多少文章的情境:


class Topic < ActiveRecord::Base has_many :posts end class Posts < ActiveRecord::Base belongs_to :topic, :counter_cache => true
end

我們會在 Topic model 新增一個欄位 posts_count,然後 :counter_cache 就會幫我們在新增刪除 Post 時,自動更新所屬 Topic 的 posts_count 欄位資料。這時只要打 @topic.posts.size 就會直接回傳 posts_count,而無需每次都再發一個 SQL query 去 count 有多少筆 posts。

其他逆正規化的方式也包括了統計結算報表等,我們把需要複雜計算的的結果(可以透過非同步的機制如 cron 定期去觸發) 存到 Report model,這樣使用者直接撈 Report 的結果即可。

Rails plugins 投影片

釋出今天在 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

誰說人是理性的


好久沒看經濟類的書,這本書從人的非理性層面切入,並用有趣的實驗導出令人驚奇的結果,還蠻有趣的。

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

我想這本書真正精采的地方在作者設計的這些有趣實驗,作為一本通俗讀物還蠻值得推薦的。不過我在想如果是科普觀點:認知心理學家、生物學家等科學家應該會有更好的解釋為什麼人類會這麼做吧,我自己是認為”人” 的這些非理性決策不是為了找到最佳解,而只是極小化選到最差解的可能 (也許就代表死亡)罷了。

Rails plugins@COSCUP 2008

Update(2008/8/23): 今天的投影片請點此下載

COSCUP

一年一度的 COSCUP 聚會又來了,這次我也投了一場 Rails plugins used/created in Registrano 約二十分鐘的演講。題目顧名思義就是介紹 Registrano 所用到的 Rails open source plugins,就是因為有這麼多好用的開放原始碼插件,才得已讓 Registrano 這個網路服務能夠敏捷地構建出來。

敝社和多這次同時也贊助了活動網站設計,當然還有報名網頁(Registrano)。除了我的 talk,還有 xdite 也會分享 Rails 2.1 的新功能介紹。希望大家多多捧場。

如果您對 Registrano 這項服務有任何想法,屆時也歡迎給予指教,並致贈您 Registrano 折價卷。

實戰敏捷開發 Practices of an Agile Developer (2) 需求篇

這一章是 Delivering What Users Want。我們總是幻想客戶一開始就確切告訴我們需要什麼,然後做完收工拿錢即可。不過事實總是中途加入一開始沒有提到的功能跟規格變更。敏捷開發不去試圖”擊敗”這些變更,而是把重點放在如何快速辨認及適應這些改變,並在時程及預算內做出真正符合用戶需求的軟體。
閱讀全文〈實戰敏捷開發 Practices of an Agile Developer (2) 需求篇〉