Refactoring at ORUG 2

Posted by caike on January 19, 2010

Here is the slides for the Refactoring talk I did last Thursday at the Orlando Ruby User Group meeting. In case you want to hear me speaking along with the slides, I’ve put it up on vcasmo also.

Using Authlogic for general email validation 1

Posted by caike on November 05, 2009

In case you are using Authlogic for authentication in your Rails apps, then you are probably using its email format validation in the user registration step. You get this validation for free just by specifying your model to acts_as_authentic:

class User < ActiveRecord::Base

  acts_as_authentic

end

That’s it for the user model and its registration field validations (login, email and password).

But what if you have some other model in your application with an email field that you also want to validate ? You could just get your favorite email format regexp and use it with the validates_format_of method:

class Band < ActiveRecord::Base

  validates_presence_of :manager, :description
  validates_format_of :email, :with => /SomeRegexpYouGotFromGoogle/

end

But that would be decentralizing the email validation concern - totally anti-DRY and error-prone.

A better solution would be to use the email regexp that’s in Authlogic, which is the same that’s already validating your user model email field.

class Band < ActiveRecord::Base

  validates_presence_of :manager, :description
  validates_format_of :email, :with => Authlogic::Regex.email

end

That’s it. Hope it helps someone keep their code clean.

Writing expressive code 7

Posted by caike on October 07, 2009

Software developers read a lot more code than they actually write. An application source code is nothing but a story written using a specific language. It has state and describes behaviour.

Code written once, will be read millions of times. For the most part, it will be read by a compiler who doesn’t really look for anything but correct syntax. Compilers are not into reading stories. They are too busy for that. Just like assembly-line workers, they follow a plan and do exactly what they were told. As soon as they pass things over to the runtime, they are done. On the other hand, we developers are not like that, are we ? No, we are not!

We are software craftsmen. We like to read stories and even get paid to write some every once in a while.

man_reading_book

http://www.flickr.com/photos/dhammza/91435718/

Think about it the next time you hack that magic one-liner in an application. Do you think you will be able to read that code-golf champion piece of code the next time you look at it ? What if it is not you, but someone else reading it ?

“Always code as if the person who ends up maintaining your code is a violent psychopath who knows where you live (…) Alternatively, always code and comment in such a way that if someone a few notches junior picks up the code, they will take pleasure in reading and learning from it.” - Ward Cunningham, CodeForTheMaintainer

An example I like to use for expressive code is method parameters in Ruby. Let’s say you want to stay fit and write a method to calculate a body fat percentage. You write the following:

def body_fat_percentage(name, age, height, weight, metric_system)
end

Apparently it looks nice. Let’s see how it could be invoked:

# fred's height in meters and weight in kilograms
body_fat_percentage("fred", 30, 1.82, 90, 1)

# barney's height in feet and weight in pounds
body_fat_percentage("barney", 32, 5, 300, 2)

In order to write those two calls you would probably have to check the right order for the parameters in the method’s signature. Even worse, every time you read that line you would have to check back its signature just to make sure that the last argument determines the metric system or that the third argument is actually the height and not the weight.

That sounds like a pretty boring story to read!

Let’s make this piece of code more expressive:

# fred's height in meters and weight in kilograms
body_fat_percentage("fred", :age => 30, :height => 1.82,
  :weight => 90, :metric_system => MetricSystem::METERS_KG)

# barney's height in feet and weight in pounds
body_fat_percentage("barney", :age => 32, :height => 5,
:weight => 300, :metric_system => MetricSystem::FEET_LB)

All we need to do to the method signature is to replace the standalone arguments for a hash.

def body_fat_percentage(name, params={})
end

From the method body, the values can be accessed using the keys, like params[:age], params[:height], etc.

In a real life situation, this expressiveness would be achieved from writing our expectations as unit tests. We would first write our failing tests as how we wanted our code to look and act like. From that, we would head towards making the tests pass. When all is green, the tests would turn out to be the reference for how to call the method (running and never-obsolete documentation) so there’s no need to go back to the implementation of the method itself to learn how to to use it.

Writing expressive code often means writing more code, but it also means writing better code. It’s not about making things work, it’s about making things right.

Cucumber and Wowspec

Posted by caike on March 09, 2009

It was back in September of last year that I first heard about RSpec. The possibility of bringing requirements in the form of User Stories straight to code amazed me and I quickly started playing around with its Story Runner.

In order to try out RSpec SR, I came up with a few lines of code and named it wowspec, in an attempt to describe and code some (very) small part of the behavior in World of Warcraft. One simple feature, that is.

But why World of Warcraft ?

Well, because it is fun and that is what programming should be all about.

To my surprise, a few months later during Rails Summit Latin America, David Chelimsky announced that the new Cucumber project would replace RSpec SR. Since then, I have been reading about Cucumber but never really tried out.

This week I decided to give Cucumber a try by rewriting my little wowspec example. I chose to keep the old name because I couldn´t come up with a better one related to Cucumber.

The project itself (check it out on my github) is really just an excuse to practice TDD (or BDD, if you wish), Ruby programming and also Cucumber. It is one single Cucumber feature, which describes a character being attacked in three different scenarios.

Scenario: Character in idle mode gets attacked
Given a character in idle mode
When he gets attacked with a sword
Then he should be in combat mode

Scenario: Character in combat mode gets attacked again
Given a character in combat mode
When he gets attacked with a sword
Then he should be in critical mode

Scenario: Character in idle mode gets fooled
Given a character in idle mode
When he gets attacked with a banana
Then he should be in idle mode

I have been using this wowspec example for introducing agile best practices to people new to unit testing and TDD, either using Java (JUnit or JBehave) or Ruby and the results have been great!

Leaving the “enterprisey” world every now and then and looking for inspiration from other sources brings joy back to programming, I believe. I strongly encourage everyone to do the same. Games, sports, nature, space, sci-fi, whatever.

Come up with something you enjoy and bring it to life through code. You will be excercising your coding skills, uncovering your own best practices and enhancing your software craftsmanship.

Test Driven Development in Rails - Part I (Models)

Posted by caike on March 04, 2009

The following is part one of a series of examples of a simple feature developed using Ruby on Rails. The intent of this post is to show how the test code can (and should, as much as possible) be written before the actual implementation code, which is an agile practice known as Test Driven Development.

I expect this series of examples to show how writing tests is actually a design activity rather than simply code verification. Each new test runs along with all the previous tests. This automation helps developers by giving them constant feedback.

The Steps

According to Kent Beck, the rythm of Test Driven Development can be summed up as follows:

1. Quickly add a test.

2. Run all tests and see the new one fail.

3. Make a little change.

4. Run all tests and see them all succeed.

5. Refactor to remove duplication.

The Tools

There are many testing framework options to choose from in the Ruby world (RSpec, Cucumber, Shoulda, etc.) but in this example I’m going to keep it plain and simple using just Test::Unit for unit testing the models and ActionController for testing controllers as well as testing routes.

After writing each test and ensuring that it fails, we will write the simplest thing that could possibly work. At first it may look ugly and not “the Rails way” of doing things, but we will later enhance its quality using another agile technique known as refactoring.

Rails out-of-the-box expects you to have a database setup and creates default fixtures for each of your models. Although there is a way to get around that, I’ll leave it alone for now.

The problem

Our client wants us to develop an e-commerce app for his musical instrument shop. From our meetings, we agreed that users should be able to buy instruments online. He said that for an instrument to be considered valid it must belong to a category, have a description and have a price. If either of those conditions is not true, then the instrument is not valid.

Making it work

Notice how the meeting revealed a few keywords and concepts to be used in the construction of our domain model and its relationships (instrument, description, category, price, belongs to).

We start off creating our application:

$ rails music_shop
$ cd music_shop

and creating our first model:

$ ./script/generate model instrument

The output shows that a bunch of files were created. At this moment, only three files are important for us: instrument migration file, model and unit test.

Our client told us he wants an instrument with description, price and category, therefore they will be the initial attributes for instrument.

Add the following snippet to some_number_create_instruments.rb located in db/migration.

create_table :instruments do |t|
     t.string       :description
     t.decimal      :price, :precision => 8, :scale => 2
     t.references   :category

     t.timestamps
end

This migration file is going to build the instruments database table using the adapter defined in database.yml, located in the config folder. Unless defined otherwise, Rails uses SQLite as dbms and I suggest that you keep it that way until deployment (or even until SQLite becomes a bottleneck for you app).

Run your migration:

$ rake db:migrate

The database table has been created for you and you don’t need to worry about it anymore.

Now we should focus on the business requirements. Open test/unit/instrument_test.rb and add the following snippet that relates to what the client said about a valid instrument.

  def setup
    @valid_params = {:description => "gibson sg",
                     :price => 100.00, 
                     :category => Category.new}
   end

  test "not valid without description" do
    guitar = Instrument.new(@valid_params.merge(:description => nil))
    assert !guitar.valid?
    assert guitar.errors.on(:description)
  end

 

Let’s run our first test

$ rake test:units

and watch it fail!

1 tests, 0 assertions, 0 failures, 1 errors

It was expected to fail since we have not implemented any validation yet. Actually it has not failed, but spit an error instead:

1) Error:
test_not_valid_without_description(InstrumentTest):
NameError: uninitialized constant InstrumentTest::Category

The error says there is no Category class defined. So lets generate our missing model, run the created migration and then run the test again.

$ ./script/generate model category
$ rake db:migrate
$ rake test:units

No complaining about missing class, but it says there is no category attribute for our Instrument model.

1) Error:
test_not_valid_without_description(InstrumentTest):
ActiveRecord::UnknownAttributeError: unknown attribute: category

Indeed, we haven’t coded anything that says that an instrument belongs to a category. So let’s do that in our Instrument model:

class Instrument < ActiveRecord::Base
  belongs_to :category
end

Run the tests again and notice how the errors are gone. Now there is just a failing test that needs to get out of our way.

2 tests, 2 assertions, 1 failures, 0 errors

Notice how the test code is guiding us through design and it’s telling us what needs to be done, like in a two-way conversation.

The process of starting a feature with failing tests and coding towards making the tests pass is known as “red green refactor”, resembling the red and green bars present in previous unit test framework outputs (JUnit being the most famous). Taking baby steps is a safe way to measure the impact of you actions in the code.

Only one line is needed to make the failure go away. In the app/models/instrument.rb add the following:

class Instrument < ActiveRecord::Base
  belongs_to :category
  validates_presence_of :description
end

Run the test again and watch the failure go away.

1 tests, 1 assertions, 0 failures, 0 errors

I believe that as you gain proficiency with test driving your code, you can go ahead and write a couple of failing tests before going into implementation code - as long as they are related to the same context of the unit under test.

Moving on with our tests, let’s add two more:

 test "not valid without price" do
    guitar = Instrument.new(@valid_params.merge(:price => nil))
    assert !guitar.valid?
    assert guitar.errors.on(:price)
  end

  test "not valid without category" do
    guitar = Instrument.new(@valid_params.merge(:category => nil))
    assert !guitar.valid?
    assert guitar.errors.on(:category_id)
  end

Run it again with rake and watch it fail:

3 tests, 3 assertions, 2 failures, 0 errors

Now only the barely essential to make the above tests pass is added, and the complete instrument model looks like the following:

class Instrument < ActiveRecord::Base
  belongs_to :category                      

  validates_presence_of :description, :price
  validate :has_a_category

  def has_a_category
    if category.nil? && category_id.nil?
      errors.add(:category_id, "must have a category")
    end 
  end
end

Run the tests again and they should all pass

5 tests, 5 assertions, 0 failures, 0 errors

Conclusion

I hope the previous steps showed some of the benefits of test driven development, which is, in my humble opinion, one of the most important agile practices.

It should be taken as a design practice rather than pure verification. Running automated tests keeps the developers in control of the application and makes code easier to maintain and evolve.