Wednesday, December 26, 2007

Go to mysql command shell using rake

Tired of typing mysql -u foo -pbar -h db01.firewalled.com baz_development yet? Add to that when you have database environments galore like test, QA, selenium, staging, etc.

Here's a rake task for you. Just point it to a Rails environment and execute and you are in the corresponding mysql command prompt.

e.g.

$ rake mysql RAILS_ENV=qa

Loading mysql in RAILS_ENV=qa...
Executing: mysql -u foo -pbar -h localhost baz_qa_test

Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.0.51 Source distribution

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql>


Code:
desc "Loads mysql command prompt"
task :mysql do
puts "\n\nLoading mysql in RAILS_ENV=#{RAILS_ENV}...\n"

database_yml_path = "#{RAILS_ROOT}/config/database.yml"
database_yml = YAML.load(ERB.new(File.read(database_yml_path)).result)

raise "Could not find environment #{RAILS_ENV} in database.yml" unless database_yml[RAILS_ENV]

config = database_yml[RAILS_ENV]
username = config['username']
password = config['password']
database_name = config['database']
host = config['host'] || 'localhost'
port = config['port'] || 3306
socket = config['socket'] || '/tmp/mysql.sock'

raise "Failed. Setup requires a user and database for environment #{environment} in '#{database_yml_path}'.\n\n#{database_yml.to_yaml}" unless username and database_name

args = "-u #{username}"
args << " -p#{password}" unless password.to_s.strip.empty?
args << " -h #{host}" unless host.to_s.strip.empty?
args << " #{database_name}"

command = []
command << "mysql #{args}"

puts <<-EOS
Executing: #{command.join(' ')}\n

EOS

system command.join(' ')
end

Monday, December 17, 2007

Rid of those TextMate "ctags timed out!" error

If you use TextMate for your Ruby on Rails development, you must use the ctags bundle CTags.tmbundle. It gives you a keyboard shortcut CTRL-] to jump to files that defines the class/method your cursor is on. Similar to "go to file and line" in some IDE. Super handy.

Trouble is when your project gets large, it gets longer and longer to update the tmtags index file to a point where it exceeds the default 15 seconds timout and gives a "ctags timed out!" error.

What you can do is edit the file ~/Library/Application\ Support/TextMate/Pristine\ Copy/Bundles/CTags.tmbundle/Support/bin/tmctags and increase the timeout $CtagsTimeout value to something more reasonable. Problem solved.

p.s. CTags suffers from another shortcoming, and that is it cannot index ruby methods named ending with a ? or !. Anyone knows of a fix/workaround? Please comment if you do!

Friday, December 14, 2007

Why create database migrations, when you don't need to?

Rails out of the box supports database migration. It allows Rails programmers to be more Agile, do less database BDUF and instead change the database schema as the requirements change and the business wants it. Writing a migration is also as easy as running a command line script/generate migration and then executing it with rake db:migrate.

Database migration is useful for two reasons. Number one is to allow developers to change the database schema. This can be as simple as a single ALTER TABLE statement to add a new column. Number two, more importantly, is to migrate the all-important data exist in the database. But if your application is still under development for initial release, then migration may not be buying you too much good, because chances are no one cares how your table structure got to where it is now, and you may not have a whole lot of data.

We all use migrations feverishly probably because most of the Rails books/references/tutorials begins with: "Let's start by creating a database migration, in it we insert some data into the newly created tables, and learn how to do XYZ." Thus, your db/migrate folder is stuffed with migrations that does everything: create new tables; alter existing tables; create data for those tables; update data created from previous migrations; and perhaps all of the above, while without justifiable reasons on what those migrations are trying to migrate. In practice, it is quite time-consuming for a developer to run 200+ migrations every time he blows away a database, which is not uncommon. Not only that, sometimes you have multiple migrations that basically cancel out each other's changes as our customers change their minds back and forth. As a result, you could be creating migrations left and right when there may not be any real beneficiaries: a database loaded with data.

Sometimes your QA team may have their own data set that tests your app, and thus their loaded database is a beneficiary. While that is true, I prefer their data to be scripted and be freshly generated by ActiveRecord models (using create!) every time instead of keep migrating them, because as my application domain model expands, I want not just QA data but all datasets to be cleansed and validated by my model validations. There is no guarentee that after running a drop_column migration the QA dataset does not violate any business logic. Keeping all these data valid while database migrations are being rapidly created is very hard.

To take advantage of the fact that your development environment has nothing to lose until you have an initial release, while maximizing the benefits of keeping all your data valid (for all enviroments) the whole time while your app is under development, it's a simple steps 1-2-3:


Step 1:

Have one migration file, 001_release_one_schema.rb, that captures all database object creations. For example, all your create_table, create_index, views, triggers (*yikes*), etc. After this migration, your database should contain all database objects for your Rails app but in a "blank", data-less state.

$ cat db/migrate/001_release_one_schema.rb

class ReleaseOneSchema < ActiveRecord::Migration
def self.up
create_table "foos" do |t|
end

(... and many others ...)
end

def self.down
(... ... ...)
end
end


Step 2:

Create a rake task to populate all reference data that your application requires to run with. Reference data meaning all data that your application cannot change through its screens, but are essential for your app to run. For example, all currencies that are used to populate a drop-down on your app. A lot of drop-down lists data are reference data.
$ cat lib/tasks/data.rake

namespace :data do
desc "Loads a default dataset of both reference and user data into database."
task :load => [ :environment,
:configuration,
:reference_data,
:user_data ]

private

task :configuration do
ENV['DATASET'] ||= 'slim'
end

task :reference_data do
require "#{RAILS_ROOT}/db/data/reference_data/#{ENV['DATASET']}"
end
end

$ cat db/data/reference_data/slim.rb

@us_dollar = Currency.create! :name => "US Dollar"
@yen = Currency.create! :name => "Yen"
@euro = Currency.create! :name => "EURO"
... ... ...


Step 3:

Create a rake task to populate all user data that your app requires to run with. User data are data that a user can create/update within your application. They are also required for the Rails app to function properly the first day when it launches. For example, for your flashy Paypal application, the fees structure on how it charges its users. An application administrator is allowed to raise or drop fees in your app.


namespace :data do

private

task :user_data do
require "#{RAILS_ROOT}/db/data/user_data/#{ENV['DATASET']}"
end
end

$ cat db/data/user_data/slim.rb

Fee.create! :amount => 1_000, :currency => @us_dollar
Fee.create! :amount => 1_500, :currency => @yen
Fee.create! :amount => 2_500, :currency => @euro
... ... ...


There are several benefits of managing your database schema and data this way:
  • It is easier and faster to re-populate your entire database to the latest schema from scratch with data, since there are no extraneous migrations.

  • Faster to locate and update data needed for application. They are always in your dataset generation scripts.

  • No need to worry about outdated/removed ActiveRecord classes and declare them inside the migration file itself. They is no "legacy" ActiveRecord models.

  • All data are valid all the time because they are created through Model.create! sanitized by your model validations.

  • Easy to specify datasets to load by preference for DEV (slim, loaded), BA (story sign-off), QA (scenario-based), or demo (full) environments. e.g. rake data:load DATASET=slim RAILS_ENV=qa

  • No worries about broken/incomplete migrations. Fewer code, fewer trouble.

Now, after your Rails app goes to a 1.0 production release, you should switch this back to the normal Rails database migration style. I suspect your application users won't be too happy if you blow away their data every time you roll out a minor update or a major release... (or not?)

Tuesday, December 04, 2007

The last "D" in TDD means more than just "Development"

When asked "Do you write tests?", a lot of developers these days will say "of course" as their answers. However, not everyone can admit to doing TDD (Test Driven Development) correctly. Test Driven Development says, a developer will write a test that fails first, then write code to make the test pass, and refactor when possible, and repeat. This is what most people's TDD rhythm is. For the most part this is fairly easy to do. But to reach the next level, one has to understand TDD as a tool: TDD means more than just test your own code. Here is a couple tips on what the last "D" means:

Discipline

It takes a great deal of discipline to even write a failing test before writing the actual code. Sometimes, we write a little seudo-code here, or move a method definition there, or changing code else where trying to see if more new code needs to be written after it, and sooner than you think you are writing the actual implementation of the methods you wanted to test (Test Afterwards Development anyone?). Other times you write the test, but you are too anxious to even run it and see it fails. And other times you want to jump into the actual code immediately when you see your new test fails, but failing for the unexpected reasons.

Don't fall into these traps. If anything is true, testing is hard, but it is at the same time rewarding and fun. What's also true is, it will pay off. Write the failing test, draw up your list of tests you will need to write, and satisfy them one by one. Having discipline is the cornerstone of becoming a better programmer.

Design

It takes too long to write a test? Tests are running too slowly? Are your tests difficult to read? Are they too brittle and fail all the time? Hang in there! You ever had the feeling you saw code in the codebase that irks the living hell out of your mind written by someone else on your team? Well, it is time for you to get some of these feedback about your own code. Yay, your code sucks! Your tests are telling you that! Let's address each of these one by one.

Slow running tests? You shouldn't be hitting a database or web service in your unit tests, because you can mock/stub them out. Difficult to mock/stub it out? There probably is a better way to design your classes your tests are hitting. Ever heard of Inversion of Control (or Dependency Injection)? Master them. True TDD masters use them extensively.

Unreadable tests? Is it because of too many mocks/stubs? Or is it the code is 500 lines long and doing high octane 720-double-backflip logic? Either way, you have to learn to like small objects. Check this blog post of mine out.

Hard to test something? Tests too brittle? Perhaps you have encapsulation issues in your class design. If your classes are referencing 15 other neighbors, of course they are hard to mock/stub. Chances are, you have to spend time to debug your tests to find out what's wrong! Heard of Law of Demeter? Even if you have, take a look at this highly entertaining yet informative post. It might change your perspective a little.

The bottom line is, TDD is a way to guide you to writing good code, but only if you know how to use it as a tool. Now that you know, hopefully you will have a new perspective next time you write a test.

Sunday, December 02, 2007

Passing multiple parameters in observe_field

Sometimes you just want to pass multiple parameters on your ajax observe_field web request for processing. If you Google around, you will find out there are multiple ways of doing it.

And here is yet another way:

    observe_field :target_dom_id,
:url => some_named_route_url,
:method => :get,
:with => "Form.serializeElements($('text_field_one', 'text_field_two', ...))"


where 'text_field_one' and 'text_field_two' are html form element ids.

I like this because if my text fields are rendered through form_for or fields_for (e.g. form_for :product), and my action does not want to explicitly specify what the posted parameters are upon processing (e.g. Product.create params[:product]), then by using Form.serializeElements I can hide all the params inside the key params[:product] still.

Tuesday, November 27, 2007

Parsing time in custom format in Ruby

I am sure you have used Time#strftime (or Date, DateTime) to format your date/time into your own custom format for pretty time display. This is fine and great. But how do you parse a date or time in your own specific format in Ruby?

There is a little method called DateTime#strptime. Its second parameter takes a string, containing basically all the options available to you in Time#strftime (eg. %m-%d-%Y) and return you a DateTime object. This method is strangely not available in Time class. Fortunately from there you can use the Rails methods #to_time to convert to the Time object you want.

Usage:

  DateTime.strptime("12/25/2007 01:00 AM EST", "%m/%d/%Y %I:%M %p %Z")

Wednesday, November 21, 2007

Stop tangling those iPod earbuds!

You have an iPod? If you ever use their white trademarked earbuds, chances are every time you pull them out of your pockets you spend 40 seconds of your life untangling those stupid wire. It adds up.

Ever notice there is a little sliding thing at the Y-split of your earbuds on the wire? I assume it is used to reduce the split between the two ear pieces when you are wearing them. If they are for that purpose I have never used them. But I did find a better use of it...

Next time when you are done using them, slide that thing all the way to the ear pieces. This will make your Y-splitted earbuds into essentially one straight wire, and thus reduce a lot of unnecessary tangling. Hopefully this saves you some annoying faces in untangling the thing (maybe that's why those Apple billboards have no face on them...)

Sunday, November 18, 2007

Numbers don't lie, but your test coverage numbers might

We have learned all though our education that our decisions should base off of numbers. Can you support your family given however much you are making? What is the velocity of gravity? How many roses do you give your girlfriend on Valentine's Day (no satisfying answers ever...)

The same happens in software. On all software projects, various flavors of metrics are gathered and read by various types of people on the team. Code coverage being one of them that is most commonly mentioned.

But there is a misconception about code coverage: When the percentage is high, it is good; otherwise, it is not good.

Then people try to find definition of "high", some say 80% is a good number, others say 90%. Some even strive for 100%.

But let's decode this message a little more thoroughly. If your number is low, this means your code is not very well tested. Clearly this is not desirable in a code base that you have to go in every day and make changes here and there - good luck in not breaking stuff. So, a low coverage number is bad.

Now, a high coverage number means your code is well tested. But this number does not tell you a few things:

1) The quality of your code. It does not tell you whether your objects are coupled like spaghetti; it does not tell you whether your code is doing crazily unreadable nested iterations mixing with multiple levels of recursions; it does not tell you whether you are violating encapsulation and separate of concerns; it does not tell you whether you are copy & pasting code everywhere. If your code exhibits all of these symptoms, a 99.9% code coverage still means future changes to the code base is going to be a nightmare.

2) The quality of your tests. Tests are also code that needs to be maintained. If it takes someone 30 seconds to make a single line of code change, but it breaks hundreds of tests and takes that person an additional hour to duplicate that fix in all failed tests, then the burden of maintaining those tests outweights the feedback of whether the system still works or not. Further, if tests are hard to read as they are long and mocks/stubs everywhere, and the test method names do not reflect what the test method body is doing, then having your tests unmaintained just adds test maintenance time.

So how should you read the coverage number? You should read this number in combination with other metrics to gauge the health of the code base. For example, do defects constantly come from a feature area of the code when changes are being made? Are story estimates higher in certain areas of the code base but not others? Are stories in certain functional areas always being under-estimated during Planning Meeting?

Code coverage is just a number. It does not tell you whether your code's flexibility to reflect the pace of your business requirements change. True productivity comes in with good code solving a particular problem well. Well tested code can still be bad.

Thursday, November 15, 2007

Seeing Rails Resources Clearly

REST-fulness is probably one of the hot topics you will face when you walk into the Rails world today. One of the terms you will notice when you dig deeper into Rails REST-ful routes is "resources". In Rails, after running the scaffold resource generator, you will get a database table migration, a domain model class, a controller, and 4 CRUD views. This is the skeleton that Rails provides for you to build upon.

However, a lot of Rails developers don't know how to bend this structure when it comes to non-CRUD operations (eg. search for something, reset password, login, various ajax actions etc.)

I have a solution for you: Routes Driven Development - Let your named routes guide you. Here's how.

As an example, suppose you have a Rails app that an admin can create/remove users that access your application. You have a database table named Users, which has a password column.

In your routes.rb, with a single line of:

map.resources :users

You automatically get these academically REST-ful urls:

  GET    /users          # => users_url
POST /users
GET /users/new # => new_user_url
GET /users/:id/edit # => edit_user_url
GET /users/:id # => user_url
PUT /users/:id
DELETE /users/:id


Then, there comes a requirement that says "From the login page, a user who forgot his password can go to a page to see directions on how to retrieve his forgotten password." We are all familiar with this concept, right?

The next thing you know, the developer jumps into the code:

  class UsersController < ActionController::Base
def index...
def show...
def new...
def edit...
def create...
def update...
def destroy...

def forgot_password
# new code here
end


And in your routes.rb:

  map.resouces :users
map.forgot_password_url '/users/forgot_password', :controller => 'users', :action => 'forgot_password', :method => :get


Oops. And you just made a wrong move in building upon the Rails skeleton. You put the action in the wrong controller.

Most developers make the assumption that a Rails "resource" is synonymous to a database table. This observation is made because this is how most people would start their Rails application, as in our case our Users concept. With this in mind, since password is a column rather than a table in the database, it should not have its own controller, and thus no model, nor view, etc. Still, we got to jam the code somewhere, and therefore the Users controller, the table on which it belongs. But this observation of one-table, one-controller is not always true.

Instead, I would keep my users controller free from password related operations and do this:

  class PasswordsController < ActionController::Base
def forgot
# new code here
end

map.resource :password, :member => { :forgot => :get }


This gives me an url of:

  GET: /passwords/forgot    # => Which gives you forgot_password_url


My named route of forgot_password_url is telling me that I am doing the right thing, because it is extremely readable. Had I not been creating a new passwords controller and put the action in my users controller, using the same technique I used to define my named route, I would end up with a not only incorrect but also nasty forgot_password_user_url(:id) by the naming convention (<action>_<controller>_url). Definitely not what I want to pass to any link_to() or button_to().

If you realize, you just created a controller (and its view) with no database table backing it what-so-ever. It doesn't even have a model class. But then again, how much more complicated can it be when the customer is asking for a page that shows directions?

By putting actions in the wrong controller, your controller actions will lack cohesiveness (i.e. actions don't operate on the right thing) which inhibits sharing, you will also run into problems in sharing views (pages, partials, rjs, helpers) like "why am I rendering a partial that is in an obscure folder?", etc. In short, a lot of bad code.

Using this routes driven technique to drive your actions and controllers, can you identify which action/controller combination is correct for a 'Login' button?

1) create_session_url  # => :controller => 'sessions', :action => 'create', :method => :post
2) login_user_url # => :controller => 'users', :action => 'login', :method => :post
3) login_url # => map.login '/login', :controller => 'whatever', :action => 'anything', :method => :post


The true answer is, it doesn't really matter, as long as your controller is responsible for the correct "resource", and the named route is screamingly readable to anyone using it.. No matter which controller you put your actions in, you can always fall back to creating a named route for it using map.connect like option (3) above. The bottom line is, Rails "resources" might not be what you and others think it is.

As homework, go read more about Rails resources. Not only can you specify :member, but learn how to use other options like :new, :collection, and nested routes. Also, there is also a singular "resource" method and a plural "resources" method. Get familiar with them. This rdoc page is IMHO pretty poorly documented, but hopefully this article gives you a reason to explore them.

Tuesday, March 20, 2007

Extreme Rails programming

What is considered as extreme Rails programming? How do you know you are coding in a zone where no man has gone before you?

That's the feeling of you standing on top of Mount Everest, with the world underneath your feet. That's the feeling when history is in the making before your eyes.

So how do you get there?

Got dumped by your girlfriend because you love Rails more than her? Uh-uh.

Solving a problem no one has thought of before in Ruby on Rails? Negative.

Writing Rails code on the moon? Nah.

Today I looked over a programming pair's shoulders, and I immediately realized that they were in a programming zone where no one ever has gone before them. So I took a picture as proof.

And it is...

Writing a Rails app in vim, with a Dvorak keyboard.



This is real, and it's priceless.

So do you know what key you press to yank a line?

(Thanks to Muness Alrubaie and David Vollbracht for this shot)

Tuesday, March 06, 2007

Rails migration pitfalls

When we create a migration, we are essentially creating a "delta" SQL script, whose intent is to change the state of the database at a given time, including its schema and its data, from point A to point B. Rails migration scripts even allow you to rollback from B to A. A lot of developers got the delta of the schema part right, because it is the most intriguing part, but they fail to recognize the data part in their migrations.

Take a look at the following migration:

class MoveColumnFooFromTableAToTableB < ActiveRecord::Migration
  def self.up
    remove_column :table_a, :foo
    add_column :table_b, :foo, :string
  end

  def self.down
    add_column :table_a, :foo, :string
    remove_column :table_b, :foo
  end
end


This migration drops column "foo" from Table A, and adds column "foo" to Table B. From the schema point of view, the migration achieves what it's supposed to do - moving a column. But this delta script is flawed from the data point of view.

Imaging your application is at 1.0, users start inserting 20MM rows into your Table A. This migration script is part of your release 1.5 upgrade. You run this script against your table A. Poof! The column is moved, but you just lost *all* of your data in the column "foo" forever. Table B now has a "foo" column with no data in it. Things went wrong, so you rollback, right? Try it. Still, your Table A now contains a "foo" column with all NULL values in it. The data are gone.

Worse yet, your boss is standing behind you, giving you 15 minutes to fix the whole mess. "Database migration sucks...", you mumbled.

This migration fails to migrate the data from point A to point B. So, what should developers have done differently? Well, here's one way to do it:

  def self.up
    add_column :table_b, :foo, :string
    execute("UPDATE table_b INNER JOIN table_a ON table_b.id = table_a.id SET table_b.foo = table_a.foo")
    remove_column :table_a, :foo
    
  end

  def self.down
    add_column :table_a, :foo, :string
    execute("UPDATE table_a INNER JOIN table_b ON table_a.id = table_b.id SET table_a.foo = table_b.foo")
    remove_column :table_b, :foo
  end


Now with this delta script, which accounts for data migration as well, will do what it is intended to migrate: schema and data.

Here is another gotcha situation:

  def self.up
    add_column :table_a, :foo, :null => true
  end


When you have a table that contains rows in it, like our 20MM row table, after this migration, the 20MM rows will contain NULL in column "foo". Your database will complain null column constraint violated after this migration.

So be careful when you are performing these migrations. My advice is, do a sanity check on all your migrations by running them against a database with tables populated with data. It actually may not be a bad idea to run a CI build on any migration check-ins, to tick off all migrations, against a database full of data, if your migrations are meant to migrate data.

Enhance Array#collect to become magical

Do you do this often?

customers.collect { |customer| customer.name }
customers.collect { |customer| [customer.name, customer.id] }


Array#collect is indeed very powerful. But I still find myself to repeatedly declare a variable to keep a reference of the elements I am iterating. I could care less if I call it |customer| or |c|.

What if I enhance the Array class to do the following:

customers.collect_name
customers.collect_name_and_id


DRY-ness... Inspiration came from ActiveRecord's magic #find method.

class Array

  def method_missing(method_sym, *args)
    if collect_by_method?(method_sym)
      attributes = fetch_collect_attributes(method_sym)
      if attributes.size == 1
        block = lambda { |element| element.send attributes.first }
      else
        block = lambda { |element| attributes.collect { |attribute| element.send :"#{attribute}" } }
      end
      self.collect(&block)
    else
      super
    end
  end

  private

  def collect_by_method?(method_sym)
    method_sym.to_s =~ /^collect_/
  end

  def fetch_collect_attributes(method_sym)
    attributes = method_sym.to_s.gsub(/collect_/, '').split(/_and_/)
    raise ArgumentError, "Array#collect_* requires at least one method name after it. eg. #collect_id" if attributes.empty?
    attributes
  end

end


And of course, code is no good without tests:

class ArrayTest < Test::Unit::TestCase

  def test_collect_raises_exception_with_no_parameter
    assert_raise ArgumentError do
      [].collect_
    end
  end

  def test_collect_with_one_parameter
    array = []
    array << TestStruct.new(:id => 1, :foo => 'Foo 1')
    array << TestStruct.new(:id => 2, :foo => 'Foo 2')
    assert_equal ['Foo 1', 'Foo 2'], array.collect_foo
  end

  def test_collect_with_multiple_parameter
    array = []
    array << TestStruct.new(:id => 1, :foo => 'Foo 1', :bar => 'Bar 1')
    array << TestStruct.new(:id => 2, :foo => 'Foo 2', :bar => 'Bar 2')
    assert_equal [ ['Foo 1', 'Bar 1'], ['Foo 2', 'Bar 2'] ], array.collect_foo_and_bar
  end

  def test_collect_does_not_interfere_default_method_missing
    assert_raise NoMethodError do
    [].foo
    end
  end

end

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'
end
end


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
end


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...
end

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 = Car.new
    car.radio.expects(:off)
    car.clutch.expects(:shift_to_drive)
    car.acceleration_paddle.expects(:push)
    car.steering_wheel.expects(:turn).with(:straight)
    car.ignition.expects(:engine_on)
    car.timing_belt.expects(:run)
    car.muffler.expects(:stinks)
    car.battery.expects(:charging)


    driver = Driver.new(car)
    driver.driving_directions = 'FORWARD'
    driver.drive
  end
end

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.