Saturday, January 13, 2007

Introduction video to ActiveResources RESTful Rails controller actions

The world is talking about REST. Just when you are reading voraciously about Ruby and Rails, what would be nicer than having DHH to tell you what the next version of Rails' vision is regarding the whole REST idea?

Consider how you would write 4 named routes for the following ActiveController actions today:

POST /people/create
GET /people/show/1
POST /people/update/1
POST /people/destroy/1

ActionController::Routing::Routes.draw do |map|
map.with_options(:controller => 'people') do |people|
people.connect 'people/create', :action => 'create'
people.connect 'people/show/:id', :action => 'show'
people.connect 'people/update/:id', :action => 'update'
people.connect 'people/destroy/:id', :action => 'destroy'

How many times have you done CRUD on a model? With ActiveResources, all your need is 1 line of route setting:

  POST /people
GET /people/1
PUT /people/1
DELETE /people/1

ActionController::Routing::Routes.draw do |map|
map.resources :person

Convention over configuration can buy you a lot of coding. Rails does just that here (and more). Enjoy.

Presentation (pdf)
There is also a ActiveResources cheatsheet

Friday, January 05, 2007

Migrate Thunderbird mailboxes from Windows to Mac

When I moved from my Windows machine to a Mac I had a bunch of mail in my Thunderbird that I wanted to migrate over. These are emails going back to the days of the war in online email services. As it turns out it isn't as easy as copying the mailboxes over from Windows to my shiny Mac. MozBackup didn't work for me because it is only for Windows-to-Windows. I found a solution after some soul searching from Google... Turns out it's almost as easy as copying over your mailboxes...

1) Install the T-Bird extension MBoxInput
This is the beauty in open standard. Mailboxes in T-Bird are stored in MBox standard, therefore they are portable to whichever email client you wish to use. Install this onto your Mac T-Bird.

2) Copy your mailboxes from your Windows T-Bird profile folder to your Mac
They are in your %APPDATA%\Thunderbird\Profiles folder. I used my good-ole USB drive...

3) On your Mac, right click on your Folders menu, there will be a "Import/Export" item. Select it, and then choose the mailbox in your Profile folder/sub-folder you want to import (eg. Inbox)
If you have multiple email accounts set up, you can right click on the account before selecting Import/Export. The mail will then be imported into the appropriate account as a subfolder.

Wednesday, January 03, 2007

Monday, January 01, 2007

Use your test classes to identify smelly code

How can you tell if you have smelly code? Your test classes actually can tell you a lot about it. Here are a few unit test anti-patterns:

Big test class
Hopefully you have one unit test class per class/module/whatever-that-contains-behaviors you write code for. When your test class starts becoming unwieldily difficult to read and understand, your Class Under Test* is doing too much (i.e. God Object). So what is difficult to read? It is different for everyone. For me, when your unit test class stretches more than 4-5 page scrolls, it is starting to become too big. Think small, think manageable.

*By Class Under Test, I mean the class (e.g. class Laptop) that is to be tested by the test class (e.g. class LaptopTest < Test::Unit::TestCase).

Prefix test method names for categorization purposes
When you have to categorize your test methods in your test class by prefixing some text for grouping to improve readability, it is an indication your Class Under Test is doing too much:

class EBayChristmasShopperTest < Test::Unit::TestCase
  def test_browse_fetch_pricing_details_for_item...
  def test_browse_froogle_compare_item_prices...
  def test_browse_amazon_compare_item_prices...
  def test_auction_overbid_item...
  def test_auction_underbid_item...
  def test_payment_paypal_purchase_item...
  def test_payment_paypal_buy_it_now...
  def test_payment_credit_card_purchase_item...
  def test_payment_credit_card_one_click_checkout...

Instead of one EBayChristmasShopper object doing all of these, how about have Shopper to delegate some of these functionalities (browsing, auction, etc.) to other smaller objects (like ItemBrowser, Auctioneer)? This way you can write more well-intended unit tests for ItemBrowser and Auctioneer, and significantly simplify our EBayChristmasShopper class.

To me, one good way to categorize your unit test methods is to group them by the names of your public methods:

class IPodTest < Test::Unit::TestCase
  def test_prev_skips_to_previous_song...
  def test_prev_and_hold_rewinds_during_playback...
  def test_menu_displays_song_list_during_playback...
  def test_play_starts_playback...
  def test_play_pauses_playback_when_playing...
  def test_play_resumes_playback_when_paused...
  def test_next_skips_to_next_song...
  def test_next_and_hold_fast_forwards_during_playback...

class IPod
  def prev...
  def menu...
  def play...
  def next...

This way, each of your public methods can have a group of unit tests responsible for its behavior. In addition, it's easy to find out which method is missing tests (psssst....). But most importantly, you can easily see and logically group functionalities together, and refactor them into new classes should your Class Under Test becomes hideous to look at.

Mocks/Stubs frenzy
All too often, developers try to write code to make things work the way they want, at the expense of the complicating the fundamentals of object-oriented programming: object-to-object communication. Sure, the code works, but the tests tell you a different picture about how you get it to work. Take a look at the following example:

class DriverTest < Test::Unit::TestCase
  def test_drive_vehicle_forward_moves_appropriate_car_parts
    car =

    driver =
    driver.driving_directions = 'FORWARD'

Did I lose you at the mock call for my car radio? Driving forward, in my mind, only needs half of those moving parts (ignition, clutch, steering wheel, acceleration). Others? I don't care (at least not when I only want to move the car forward as a driver). Sure the code works, but an overdosage of Mocks and Stubs is a good indicator that you are breaking encapsulation and/or coupling your class with too many other objects.

Long test methods
This indicates your Class Under Test requires a lot of set up in order to be useful, or your object is very coupled with the rest of the world (remember someone once said decoupling is good?), or your Class Under Test is very long and procedural. Remember the test_drive_vehicle_forward above?

Reduce the size of your test methods by re-thinking your object-object communication path. Maybe introducing an additional object to do all the dirty set up work would help decoupling the Class Under Test from the rest of the world immensely. Maybe this is a common object-coupling design problem that someone already has a design pattern to solve it succinctly, and all you need is google for it. There are always ways around it.