Getting started with BDD, a 1Up Adventure

Over the past month and half I’ve been working hard on my TDD skills. Having come from a learn-as-you-go web development background (as a lot of web developers have) I’ve found the transition to a test-first workflow to be a real challenge. Luckily, I work with a great group of Rubyists and Madison, Wisconsin has a great Ruby community.

First step: RTFM (or RTFB, in this case)
RSpec is central to my everyday workflow. I work in a Ruby shop and have the luxury of working with people who have already mastered this stuff. While this is great, it also means that most of my experience with RSpec up until now has been with maintaining and extending a test suite, not starting from scratch and driving out features.

To begin my study of RSpec, I picked up the RSpec Book (David Chelimsky), which is really more of a TDD/BDD book than it is purely RSpec. It does a fantastic job of covering the BDD development cycle and it’s more of a conicidence that the samples are in Ruby.

The cycle is described as follows:

  1. Focus on one scenario (Cucumber)
  2. Red: Write a failing step definition (Cucumber)
  3. Red: Write a failing example (RSpec)
  4. Green: Write code to make the example in #3 pass (RSpec)
  5. Refactor: Refactor your code, ensure your tests continue to pass (RSpec)
  6. Return to Step #2 and continue to through your step definitions until all are passing
  7. Refactor: Refactor your code, keeping both RSpec and Cucumber test suites passing

The RSpec Book is worth the money on the merit of its coverage of the BDD cycle alone. I also appreciated that the author, David Chelimsky, chose to use a command-line application as the central example rather than a web app. While Rails is a great framework, I’m discovering that if you’re not careful to ground yourself in Ruby fundamentals, you can easily lose your way in the conveniences of the framework and write a lot of bad code. The command-line app gets back to basics and helps liberate the user from having to worry about browsers, databases and servers for awhile and focus on the code itself.

More complex example: Conway’s Game of Life
The next step in my process was to apply it to test-driving Conway’s Game of Life. Conway’s Game of Life is a classic programming exercise used to demonstrate object oriented programming techniques. As I began working on the problem, I was stumped. As I mentioned earlier, most of my experience is in maintaining a mature test suite. This means that much of the infrastructure and helpers have been defined. This was a brand new endeavor: new project, empty test suite and an unfamiliar topic. It was the programming equivalent of writer’s block.

To get unstuck, I did some searching to see if there were any solutions to this problem that I could study. As luck would have it, there is a great screen cast of Ryan Bigg tackling Conway’s Game of Life using RSpec and Ruby. I watched the video a couple times and was able to implement all four rules after getting a feel for how a master approaches TDD.

Global Day of Code Retreat
While it did feel good to get Game of Life functioning, I felt like I had cheated by watching someone else implement the first rule. As luck would have it, I was able to get a ton more practice at the Global Day of Code Retreat.

The Global Day of Code Retreat, held on December 7th, was a collection of local events around the world where programmers worked together along with a facilitator to practice BDD on (you guessed it) Conway’s Game of Life. After each 45 minute session, you trash your code. It’s not about the result, but about putting the principles of BDD into practice. After hacking at the Game of Life from 9am to about 4pm, I learned a valuable lesson: BDD is about practice.

That’s all there is to it. I’m not going to get it all at once. It’s an approach and an attitude, not a silver bullet. After studying RSpec for a month and a half, I’ve learned that I’ll be studying RSpec, or more specifically BDD, for the rest of my career. And that’s fine by me.

About the 1up Project
The 1up Project is the brain-child of Joe Nelson. It is a self-directed program of personal-improvement where the participants choose specific topics, study them over a discrete period of time while applying the knowledge gained to a specific project, presentation or blog post.

Metaprogramming and the Ruby Object Model

Having spent the last couple weeks reviewing Pragmatic Programmer’s screencasts on metaprogramming and the Ruby object model, I discovered one thing for certain. I shouldn’t be doing any metaprogramming any time soon. It’s a tricksy endeavor frought with peril, even for seasoned Rubyists.

I kind of had a feeling that would be my conclusion based on hearing this talk at Madison Ruby by Paolo Perrotta, the guy who wrote the book on metaprogramming. In the talk, he shows just how tricky metaprogramming can make your code.

Essentially, because metaprogramming is code that writes code, you can end up with a codebase that has hidden “gotcha” methods that are created as if by magic. This often conceals what is actually going on, makes the code hard to read, hard to debug and hard to extend or modify.

Definitely an endeavor left to someone who’s a bit more of an expert than me.

That’s not to say that I didn’t learn anything. Quite the contrary. The series starts with a great overview of the Ruby object model, the call chain for methods, inheritance versus mixins, singleton methods and a whole slew of other great stuff.

I plan to cover a couple of these topics here, but as a note to the reader, a lot more has been written on these topics by people infinitely smarter than me. My coverage of the topics here is intended to be more of an exercise of completion of the section of my 1up project than an attempt at a definitive screed on the subject.

The Call Chain
When you call a method in Ruby, the interpreter looks for the definition of that method in the object that maps to ‘self’ in the current context, if that method doesn’t exist on self, Ruby moves “up the chain” and checks self’s parent class, and so on until it runs out of parent classes. Here’s an example:

# define a specific string
my_string = "I'm a string!"
# call #reverse
# 1) this first checks to see if my_string has a method called reverse
# 2) it doesn't find one
# 3) it then checks for reverse on my_string's parent class, which is String
# 4) it finds the method and executes it and outputs the following:
my_string.reverse
=> "!gnirts a m'I"

# if we define a singleton method on my_string like so:
def my_string.reverse
  "I'm overriding .reverse"
end
# and then call .reverse on my_string
my_string.reverse
# we get the result of the new method and not that of
# the default behavior of String

my_string.reverse
=> "I'm overriding .reverse"

This concept becomes important in metaprogramming because the Ruby interpreter has several “hooks” for methods, classes and modules, marshalling and coercion that can be used to execute code that extends Ruby’s functionality. When you use these hooks, you need to be sure where exactly which member of the call chain you’re attaching your meta-functionality to. For example, in the screencasts, Dave Thomas demonstrates how to attach console tracing to methods by using the method_added hook. It’s really impressive to watch him implement the code, but there are a lot of nuances that he has to work around. A list of all these hook methods can be found here: http://stackoverflow.com/questions/5127819/is-this-a-comprehensive-list-of-ruby-hook-methods.

One of the more well-known uses of these hooks is to use the method_missing hook to create the semantically-rich find_by_xxxx methods in Active Record where xxxx is a model attribute that is essentially a column in a database. (I sure hope I said that right)

You must realize the truth: there are no class methods
Another interesting tidbit that stuck with me was this: class methods are really nothing all that special. In actuality class methods are really just singleton methods on a Class object. The following two examples are essentially the same:

class Foo
  def self.bar
    puts "I'm at the bar!"
  end
end

# is essentially the same as
Foo = Class.new 
def Foo.bar
  puts "I'm at the bar!"
end

While this kind of prototype-based development is valid, it’s not typical Ruby style. The screencast advised that that type of idiom is more prevalent in Javascript, so I’m going to squirrel that knowledge away for my future 1up investigations into Javascript and it’s popular libraries like jQuery, Backbone, etc.

I’m sure there was a ton of information in these screencasts that just didn’t stick. It’s my hope that I’ll learn more on subsequent viewings and more practice. I’d definitely recommend them to anyone who wants to learn more about the Ruby object model and how important it is to have a deep understanding of those concepts before embarking on any metaprogramming adventures.

Also, if I’ve made any egregious errors in my explanation of concepts above, please let me know. I really want to keep this stuff straight in my head.

For my next topic, I’m going to tackle Test Driven Design (TDD) with Ruby and Rspec in an effort to write cleaner, better-designed code. I’m always amazed when I watch some of the giants in the industry sit down and drive out features and functionality with TDD, and I’m looking forward to a lot of practice.

The End of Learn Ruby the Hard Way

I’m finished with Learn Ruby the Hard Way. It took me way longer than I thought it would. All in all, it was a really great overview of the Ruby language, test-driven development, and project organization. I found Chapter 37 to be one of the more valuable in the course. It’s simple enough: go through [...]

Continue reading...

Learn Ruby the Hard Way – the Halfway Point

I’ve been plugging away at Zed Shaw’s Learn Ruby the Hard Way and made it to the half-way point tonight. So far, so good. I haven’t discovered anything earth-shattering just yet. I think the biggest thing that’s stood out for me thus far is an idiom of string substitution I’ve not seen before. It involves [...]

Continue reading...

The 1-Up Project, Player 2

Plotting my course of study

Earlier this summer, Joe Nelson embarked on a quest to become a world-class developer over the course of one year. He calls it his “1up Project“. The approach is 2-week iterations of concentrated study on a variety of topics ranging from the HTML5 Canvas to PPC advertising. Each 2-week sprint culminates with a blog post, [...]

Continue reading...

Go to UXMad. Seriously. It’s gonna be awesome.

Spot the UX Pro

UXMad is coming. Some of the greatest minds in User Experience will be descending on the Overture Center in Madison, Wisconsin on July 19 through the 21st. If your product, application or service has any room for improvement you owe it to yourself to attend. The conference is single-track, so you won’t miss a thing. [...]

Continue reading...