實戰敏捷開發 Practices of an Agile Developer (4) 程式篇

趁著新年連續假期,終於把這一章念完了:隨著開發的進展,程式逐漸變得怪獸。這章談幾個重點幫助你讓程式容易了解、擴充及維護。

Program Intently and Expressively (寫清楚了解的程式)

厲害的程式是沒有人可以看懂的程式?程式的可閱讀性比寫得方便還重要,寫只會寫一遍,看卻會看很多次。很多時候會有機會要修 Bugs 或是新增功能,這時搞懂本來的程式常常是一開始最困難的地方,如果一開始寫的人就以可讀性為重要目標,那你就會輕鬆的多。

舉個我自己常見的例子就是 Magic Number,很多人喜歡是一個數字來代表 Type code。例如 1 代表 foo、2 代表 bar、3代表…etc,然後程式裡面就直接寫 1, 2, 3。方便是方便,但是沒多久就會忘記這個 1,2,3 各代表什麼意義。最簡單的解決手法就是請改用字串 constant 處理,或者是用 class 來表示 type。

透過程式語言本身的特色可以寫出更有表達力的程式,函數名稱應該傳達出意圖、參數名稱應該表達出他們的用途,寫出好閱讀的程式我們可以避免很多不必要的註解跟說明文件。一些你覺得明顯簡單的地方,不一定對別人也是如此明顯,甚至是幾個月後的你自己。請想想看幾個月後自己來看還會看得懂嗎?

Communicate in Code (寫出可以閱讀的程式)

我們都討厭寫文件的一大理由是:所謂的文件跟程式碼常是分開的兩碼子事,因此很難讓文件跟的上程式的更新,最終變得難以維護。因此最好的寫文件方式,就是透過程式本身和程式中的註解。

註解是用來寫目的、限制條件跟預期結果等,而不是寫出以下這些程式一行行會做些什麼(請不要拿註解再寫一次程式碼在寫的事情)。一個簡單的判斷方式是:寫在函式 “裡面” 的註解多半是不需要的 (尤其是註解寫 what? 而不是註解 why?)。在重構一書更直言回答哪裡需要重構?那就是有註解的地方:如果程式碼前方有一行註釋,就是在提醒你,可以將這段程式碼替換成一個函式,而且可以在註釋的基礎上給這個函式命名。

你要做的事情應該是讓 source code 本身容易了解,而不是透過註解。透過正確的變數命名、好的空白間隔、邏輯分離清楚的執行路徑等手法,我們很少需要在函式裡面註明這些程式在做什麼,我自己的經驗除非是有參考外部的程式碼或複雜演算法,我會多註明參考來源(網址)。否則沒有必要的註解對我來說就像噪音一樣,妨礙閱讀。

變數跟函式的命名是件非常重要的事情,有意義的命名可以傳達出程式怎麼進行,我舉個 Rails 例子:

p = Post.find(param[:id])
if p
   p.destroy
else
   p = Post.new( param[:post] )
   p.save
end


可以改寫成以下這樣具有清楚意含:

existed_post = Post.find(param[:id])
if existed_post
  existed_post.destroy
else
  new_post = Post.new( param[:post] )
  new_post.save
end

有一種 Job security 的方式就是把程式中所有的變數名稱都代換成亂碼,保證拿到的人超級難看得懂。這就是為什麼手工打造的程式碼有其不可取代的重要性,只要拿到整合型 IDE 像是 Dreamweaver 產生出來的 HTML/CSS code 都很想殺人,因為裡面的變數都是編號產生出來的,根本沒辦法閱讀及擴充。

另外就是大家很喜歡用縮寫,這在我之前寫的文章 物件導向程式的九個體操練習 也有提到,這些只有一個字母的暫時變數並沒有辦法傳達出任何可以幫助了解的資訊。

Class, module, method 前面是個寫註解的好地方,而且每個語言都有工具(例如 RDoc, Javadoc… 等)可以幫忙從程式碼中整理出好看的純文件,這些說明通常有:

  • Purpose 目的
  • Requirements(pre-conditions) 預期的輸入是什麼
  • Promises(post-conditions) 什麼樣的輸入,會有什麼樣的預期輸出
  • Exceptions: 有哪些例外(exceptions)情況

這些說明可以幫助我們由大局觀了解程式是怎麼運作的,而不需要仔細看其中每個 method。
閱讀全文〈實戰敏捷開發 Practices of an Agile Developer (4) 程式篇〉

Ruby Advent 2008 摘要 (下)

Ruby Advent 2008連載完畢,來繼續整理完下集。

  1. GUIfy your Ruby apps with Shoes
    介紹 Shoes 這套有趣的跨平台 GUI 小型開發工具。
  2. Ansuz: Rails based CMS for the Masses
    介紹 Ansuz 這套 Rails-based CMS。裝起來玩了一下,看起來功能蠻多的。不過我個人還是推薦 Radiant 這套比較精簡些。
  3. A Collection of Rack middlewares
    Rack 幾乎要變成 Ruby 社群要做 web framework/apps 標準規格了,Edge Rails 最近在做的 Metal 就是在 Rails 裡也可以撰寫低階的 Rack 操作(效能++)。這篇文章則介紹幾套基於 Rack 的 middleware 函式庫,任何基於 Rack 的 Web framework/apps 都可以使用。也就是對將採用 Rack 的 Rails 來說,這些 Rack middleware 都無需經過 Rails router 和 Action Controller path 就可以把事情做完,真是太厲害了。
  4. Rails 2.2 Internationalization
    介紹及經驗分享 Rails 2.2 的 i18n 功能。有興趣可以看看我之前在 Ruby Tuesday 分享的投影片
  5. Prawn and the future of Ruby PDF generation
    傳統上 Ruby 要產生 PDF 文件,會考慮使用 PDF Writer 等等工具,不過現在有執行速度更快、API設計更好的選擇了(而且 PDF Writer 也不會再出新版了),那就是 Prawn,這是一套 pure Ruby 的 PDF Generator,內建支援 UTF-8,預計2009年中就會推出穩定的正式版。
  6. Full-Cycle Feature Development in Merb
    作者分享他使用 BDD 開發功能的流程:1. 點子 2. 用 Cucumber 寫出規格 3. 用 RSpec 寫 model specs
  7. Ruby Graphs and Java Monitoring with JRuby
    介紹如何使用 RMagick4J,一個 ImageMagick/RMagick 在 JRuby 上的實做品,以及搭配 Gruff 工具。下段介紹 Java Management Extensions (JMX)

  8. Easy Dependency Management for Git with Braid
    如何管理外部程式碼一直是個頭痛的問題,最常見的處理方式就是 copy 一份回來,但是萬一碰到自己有修改,加上這個套件升級了,就會很麻煩。在 Git 流行之前大家推薦用 Piston 來管理,不過現在又多了不少選擇:

    這篇文章介紹 braid 這套管理 vendor dependencies 版本的工具,支援 git 跟 svn。

    其他選擇可以參考這篇 Easy Git External Dependency Management with Giternal 所介紹的有 Tim Dysinger 的 rake tasks、37signal 的 cached_externals、Pat Maddox 的 giternal 等等,也許更適合你。

  9. Jump Start Credit Card Processing
    製作精美 PDF 介紹信用卡金流及 Active Merchant。看起來很棒可是台灣的金流公司都沒有… XD
  10. Dance in the Clouds with PoolParty
    PoolParty 是一套以雲端運算平台為目標的佈署工具,目前支援 Amazon EC2。
  11. HTML Scraping with scRUBYt! for Fun and Profit
    介紹 scRUBYt! 是一套基於 HpricotMechanize 的多功能 web scraping 工具。
  12. Life Beyond Code
    耶誕夜的這最後一篇連載跟技術不太有關係… XD

Ruby Advent 2008 摘要 (上)

Ruby Advent 2008 到耶誕節有一系列的 Ruby 連載:

  1. Simple Blog Engine in Ruby
    介紹 Scanty 這套由 Sinatra 做的 Blog 系統
  2. Deploying Ruby Apps with Passenger
  3. Passenger 其實不只支援 Rails,任何支援 Rack 的 web framework 都可以使用。

  4. Hoptoad for better Exception Notification

    Hoptoad之前有介紹過,是 ThoughtBot 出的網路服務,用來追蹤 Rails 的 exception notifications,最近也剛推出收費版支援 SSL。

  5. Cool as a Cucumber

    Cucumber 是一套基於 Rspec 的 Acceptance Testing Framework。這種驗收測試的作法是用純文字的方式把規格文件(feature documentation)寫出來,然後用這套工具來寫一個可以執行它(parse)它的測試程式。

  6. Machinist for your Test Data Factory

    因為 fixtures 實在不惹人喜愛,所以有些人改用工廠機制,例如 Factory Girl 這套 plugin 可以預先定義好資料形式,方便隨時建立出測試假資料。我的經驗是程式會漂亮不少,但代價是如果假資料量大的話,執行會花不少時間。

    而這裡介紹的 Machinist 也是概念類似的一套實作品(算是 Factory girl 的重新發明)。

  7. SOA with Merb?

    要做 REST calls 目前有幾種 library 可以用 Net::HTTP、RestClient、HTTParty 和 ActiveResource。其中 Net::HTTP 太基本了,而 ActiveReource 太肥不適合搭配 Merb,所以這裡推薦的是 RestClient

  8. Generating (Real) Fake Content

    開發網站的時候,常有要塞滿一些假資料來 Demo 的需求,這裡介紹了 Faker gem 可以產生假文字。

  9. A Simple Distributed Queue in Ruby

    使用 DRb 用九行 Ruby code 就實作出一個 Shared Queue。

  10. Git it done, Rubyists

    介紹 Git 跟一些 Ruby 工具,對 Git 還不太知道的朋友可以看看 Why Git is Better than X (有中文翻譯)

  11. Listening to Your Specs

    這篇長文蠻深入的講解 RSpec 的 BDD(Behavior-Driven Development) coding style。

  12. Thinking out of the Box with Enumerable#inject

    火力展示 Ruby Enumerable#inject 的進階用法,雖然我覺得還挺難懂的。

  13. Meet the Splat

    介紹 Ruby splat operator (也就是asterisk *) 的用法,可以將陣列展開成參數列。

Ruby Tuesday 2008 歲末場 開始報名

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

這次的題目非常難得,godfat 介紹的 Rubinius 和 contagious 介紹的 Merb 都是 Ruby 社群中非常看好其發展的兩套 Open Source Projects,相信可以帶給大家不一樣的視野跟想法。

RESTful Rails 入門開課 (自由軟體技術教學工作坊)

Update(2008/12/12): 上課的網頁在這裡 ihower.tw/course/rails.html,投影片在這裡

感謝 OSSF 自由軟體技術教學工作坊 的邀請,下週四我會在台北開一堂 Ruby on Rails 稍微進階一點的上機實做課程(主辦人不忘提醒我這是推廣教學課程,盡量簡單一點),詳細內容請參考課程介紹

  • 如果從未寫過 Ruby,建議可以看看Ruby Programming Language 網站的 Get Started 部份,或是 Learn to Program,大概了解一下語法。
  • 如果從未接觸過 Ruby on Rails,建議可以一起報名參加另一堂 Ruby on Rails 導覽 (講師不是我,不過內容應該比較簡單)。
  • 如果您有看過、簡單用過 Rails,但是對於 Rails 2 開始採用的 RESTful 設計不明瞭(例如為什麼Rails一代的 scaffold 用的好好的,但是升級二代之後的 scaffold 就看不懂了?為什麼照市面上的Rails書打範例都是地雷沒辦法執行?因為市面上的中文書都太舊了沒講 Rails2 啊。),建議可以來聽聽看。
  • 如果這份投影片的內容您已經會了,就不用來佔人位子囉。

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 頻道,歡迎多多指教。