Reporting or commenting on just a few bugs on Launchpad seems to produce lots of karma. I now have just over 8000 karma. Reincarnation as a multi-celled vertebrate comes closer everyday. I’ve fallen behind on translating application strings to Korean though (my last submission was early on in the Dapper release cycle), so I’m going to check on the progress of a few of my favorite applications – Banshee, Sound Juicer, and Easytag.
zerokarmaleft's Life List
-
1. create a parallel universe
13 cheers5 people -
2. record a new album
2 entries . 3 cheers33 people -
3. sell 1000 copies of The Commission's independently released, debut album
5 cheers1 person -
4. gain weight
3 cheers3,066 people -
5. Get Democrats elected to Congress in 2006
4 cheers12 people -
6. buy a Mac
1 entry . 4 cheers399 people -
7. try behavior-driven development
2 team members . 1 entry5 people -
8. master Ruby
2 entries . 3 cheers179 people -
9. write a custom GTK widget
2 people -
10. write a GTK application
1 cheer1 person -
11. play piano better
1 entry . 3 cheers222 people -
12. hook up with a surfer girl
5 cheers1 person -
13. learn 10 new Korean words
4 cheers14 people -
14. buy a digital camera
1 entry . 7 cheers832 people -
15. scan all my old photographs
3 cheers257 people -
16. Go to the dentist
1 cheer1,030 people -
17. write a simple application on Camping
1 cheer1 person -
18. re-design my website
1 cheer540 people -
19. finish a 1.0 release of r43
2 team members . 1 entry . 1 cheer2 people -
20. write an application on Rails
1 entry . 2 cheers476 people -
21. go on tour
208 people -
22. read Karen Armstrong's "A History of God"
2 people -
23. read Stanley Cohen's "Visions of Social Control"
3 people -
24. read Richard Rosecrance's "The Rise of the Virtual State"
1 person -
25. learn to ballroom dance
4 cheers767 people -
26. Learn Cocoa
1 cheer181 people -
27. play a round of golf in under 100 strokes
2 cheers1 person -
28. Build a recording studio
1 cheer120 people -
29. write a useful program in Python
1 entry . 3 cheers6 people -
30. relearn the trumpet
1 cheer6 people -
31. learn to snowboard
4 cheers2,451 people -
32. learn Japanese
8 cheers9,753 people -
33. learn how to drive stick-shift
1 entry . 6 cheers4,462 people -
34. Get new glasses
1 cheer319 people -
35. Give 400 cheers.
4 cheers15 people -
36. earn 10,000 karma on Launchpad
2 people -
37. hit level 60 in World of Warcraft
247 people
RSpec’sAPI for verifying collection behavior (not testing!) reads so well I just had to share with a fellow professional .NET coder (albeit a Ruby enthusiast also). Low-brow hilarity ensued…
zerokarmaleft: damn, i just love reading code that looks like this:
specify “all Players’ hands should have 2 cards” do
@game.players.each { |player| player.hand.should_have( 2 ).cards }
end
zerokarmaleft: instead of:
[Test]
public void TestAllHandsAfterDealing() {
foreach(Player player in game.Players) {
Assert.AreEqual( 2, player.Hand.Cards );
}
}
jm: yeah thats pretty nice code
jm: i’d stick my dick in that code
zerokarmaleft: rofl
jm: its puuuurdy
If you haven’t figured it out already, I started writing a generic card game (buzzword warning) framework to get my feet wet with BDD. Even after my limited foray, I feel that RSpec encourages thinking from a high-level abstraction standpoint and finding descriptive names. Both very good things in my book. To get this particular specification to read naturally, I had to extract an Array attribute out of a class and wrap it in a new class.
class Player
attr_reader :hand
def initialize; @hand = Array.new; end
end
became
class Player
attr_reader :hand
def initialize; @hand = Hand.new; end
end
class Hand
attr_reader :cards
def initialize; @cards = Array.new; end
end
In this minimal form, Hand is fairly worthless, but I wasn’t sure what kind of functionality it needed. So I added some more Player specs to see what would surface. In a card game like Uno, there are many times you have several cards that are the same and playing one is equivalent to playing any other. But Players shouldn’t be concerned with selecting a specific Card instance and deleting it from his/her Hand. They should just be able to say, “I want to play a Skip card, and I don’t care which one.”
class Player
[snip]
def play( klass_of_card, discard_pile )
cards = @hand.cards.select { |c| c.is_a? klass_of_card }
raise CardNotInHandError if cards.empty?
discard_pile << @hand.cards.delete( cards.first )
end
end
class Card; end
class Skip < Card; end
@edward = Player.new
@edward.play Skip
Since I want to pass a Card’s class as a parameter instead of an instance I can’t use Array#include? to cleanly test for inclusion. I wanted a similar one-liner with Hand.
class Player
[snip]
def play( card, discard_pile )
raise CardNotInHandError unless @hand.has_this? card
discard_pile << @hand.discard( card )
end
end
class Hand
[snip]
def has_this?( klass_of_card )
@cards.select { |card| card.is_a? klass_of_card }
@cards.empty?
end
def discard( klass_of_card )
@cards.delete { |card| card.is_a? klass_of_card }
end
end
Still doesn’t look like much but I think the clarity in Player is increased by isolating class-handling logic in Hand. As far as the Player is concerned, he/she is playing a Card…not a Card.class.
My experience with RSpec has been pretty positive so far. I’ll get back to my humble chess variant project in a bit and see how well test2spec executes Test::Unit migration.
My 300th cheer went to kdreyling. Several of my friends have moved to Korea or China to teach English and I also met several expats that were doing the same when I visited the Philippines. So if you’re open to adventure and new cultures, and enjoy teaching, I encourage you to do some research into ESL programs.
