
Over the past few weeks I’ve been pretty quiet on the blogging and list front. I’ve had a lot going on behind the scenes, and can now announce that I have accepted a position with a wonderful XP shop (and great company) called CARFAX in Columbia, MO. I am very excited by the opportunities there, and though I’ll miss my current employer, I look forward to the fun stuff that will be going on.
The next few weeks will be incredibly hectic between heading to Florida briefly for the holidays, preparing to move, buying a house, selling a house and moving. Whew! I’ll still be lurking, just not as vocal as I normally am. Don’t worry, I’ll be back to my normal self soon. Assuming I can make a succesful transition from a Southerner to a Midwesterner. :)
A couple of weeks ago I posted a tutorial for getting Fitnesse and .NET working together. It was a good success, but I had an ulterior motive. I really just wanted to suck you, the reader, in so I could bring to you Ruby – a fun OO language.
However, getting Ruby hooked up proved to be a little trickier than I expected. Partly because I’m not all that well-versed in Ruby yet, and partly because there is even less documentation on the net for Ruby and Fitnesse. But, nonetheless, I’ve got my Ruby tests working, so lets get down to business!
Step 1 – Install Ruby
First things first, you’ll need to get and install Ruby. I created this tutorial on my Linux box, so I just emerge Ruby‘d it. However, you can just as easily download it and install it.
Step 2 – Install Fitnesse (and Ruby FIT)
If you haven’t installed Fitnesse, grab it and install it. Once you have it installed, grab the ruby.zip file from here and unzip it to your Fitnesse install directory.
(Note: There are other versions of Ruby FIT around. I chose to use the one off the Fitnesse site. However, you may want to check out the discussions and choose for yourself. )
Finally, start up Fitnesse and browse to it. So far, so good.
Step 3 – Setup our test
Let’s get down to business. Create a wiki page called MyRubyTest. Similar to the .NET runner, we have to specify a different command pattern. Setup your page so it looks like:
!define COMMAND_PATTERN {ruby -I %p ruby/bin/FitServer.rb -v}
!|mytest.Division|
|numerator|denominator|quotient?|
|10 |2 |5 |
|12.6 |3 |4.2 |
|100 |4 |24 |
Now save it, and set the properties to be a Test. Run the test and you should get something like:
Which means we are ready to dive into some Ruby!
Step 4 – Build our class
This step was the big stumbling block for me. The class was easy to write. It was getting the Ruby Fit runner to find it that was the hard part. The trick is that Fit wants your class to be in a directory path and module that sync up. Let’s look at the code and I’ll explain more.
Create a directory somewhere called mytest. I chose ~/apps/mytest, but for windows, use c:\projects\mytest or whatever you prefer. In that directory, create a Ruby file called division.rb. You can do this with notepad, or use the FreeRIDE IDE that comes with the Ruby installer for Windows, or the good ol standby, vi ;) The contents should look like:
require 'fit/column_fixture'
module Mytest
class Division < Fit::ColumnFixture
attr_accessor :numerator, :denominator
def quotient; @numerator.to_f / @denominator.to_f; end
end
end
(which I got mostly from the division.rb file in the lib/eg directory).
So, now you have a file, division.rb that is in a directory called mytest. The class definition for Division is in a module called Mytest. This is the key to getting Fit to recognize your classes. Or so it seems – I’m always open to corrections if someone has different information.
Step 5 – Hook up the class to Fitnesse
So, now we have a failing Fitnesse test, and a class that we think will make it pass. Let’s edit our page and add the path to our class. Open up MyRubyTest for Edit, and add the path definition, modified for the path you chose above, just below our COMMAND_PATTERN. Your test should now start with
!define COMMAND_PATTERN {ruby -I %p ruby/bin/FitServer.rb -v}
!path ~/apps/
(Or !path C:\projects. You want to go one directory below the directory your class is in).
Save it and run it. You should now get:
Great! We’ve managed to get Fitnesse talking to our Ruby class. Now, modify our test so that we are expecting the right values (change the 24 for the 100 test to 25) and run the test again. You should get green!
And just like that, you’ve got Fitnesse talking to Ruby. You deserve a hardy pat on the back. Now you can get cracking with your customer tests not letting any language stand in your way. As long as that language is Java, .NET, Ruby, Python, or one of the other supported servers.
Have fun!
(Note: I posted this to Slashdot about a week ago and it’s still pending. I’ll update this when they finally get it in their review section)
(Update: It finally got posted, only two months later.)
I recently got sent a copy of Bruce Tate’s newest book Beyond Java – A Glimpse at the Future of Programming Languages. Having read Bruce’s Bitter Java and Better, Faster, Lighter Java, I was intrigued to see what he would have to say about moving beyond Java. In short: If you’re a hard-core Java (or to a lesser extent, C#) developer who thinks Ruby is something that goes on a ring, Pythons will bite you, and Smalltalk is something you have to do at parties, you are in for a rude awakening.
Let’s get down to it. For many people, Java pays the bills. For dealing with big problems, it is a wonderful language with a myriad of libraries for solving domain-specific problems. The author thinks that this focus on the larger applications is causing Java to alienate the developers who need solutions to small, real-world problems, like babysitting a database with a web site.
Bruce starts out in Chapter 1 discussing a disrupting experience he recently had when he discovered how much faster and more productive he and his team were when they switched mid-stream to Ruby on Rails. He gives some controversial numbers that discuss this improvement. This experience leads him to realize that maybe Java is dying – or at least fading in certain areas.
His next sections (Chapters 2 and 3) discusses the “Perfect Storm” that led Java to become the leader it is today. How it traded the OO purity of Smalltalk to woo C++ developers. And how the programming environment was calling out for a language like it.
But that landscape is changing, and Java is having a hard time keeping up. In chapter 4, he gives an example of servlets. Earlier servlet specs allowed you to get a Hello, World servlet, albeit ugly, up rather quickly. That same example now requires deployment descriptors, packaging into WAR files, configuration files, etc, etc. For Java developers, this is the norm, but for a developer new to Java, who wants to learn all that?
Chapter 5 is a discussion of what Bruce feels is the Rules of the Game, or what the next “Killer language” will need in order to beat out Java. This was a very good treatment, highlighting some of the good and bad of Java and languages as a whole. For example, he rates high that you will need some sort of Enterprise Integration, Internet Focus, and Interoperability. He also feels things like dynamic typing, rapid feedback loops and dynamic class models (making reflection more natural).
Most importantly, it needs a killer app to act as a catalyst to get people’s mindsets changed. In Chapters 6, 7 and 8, he gives examples of some killer apps – Ruby on Rails and Smalltalk’s Continuation servers (like Seaside). Chapter 6 is a kick-in-the-teeth intro to Ruby (which left me wanting to go out and pick up Dave Thomas’ Programming Ruby book). Chapter 7 shows a sample Ruby on Rails application, and Chapter 8 gives a very interesting look into Continuation servers and the work being done by the Smalltalk community on it.
Finally, he closes the book with a list of Primary and Secondary contenders that could up and replace Java. Primaries include Ruby, Python, Groovy, and .NET (C# and VB.NET). Secondary contenders include Perl, Smalltalk, PHP and Lisp, which he summarizes as: “Perl’s too loose and too messy, PHP is too close to the HTML, Lisp is not accessible, and Smalltalk wasn’t Java”. To which he adds, “…go ahead and fire up your GMail client and your thesaurus, and drop me a nasty note. Ted Neward reviewed this book, so I can take a few more euphemisms for the word sucks“.
Thankfully there is nothing in this book that would cause me to write a nasty note to Mr. Tate. In fact, if you haven’t begun looking at other languages and are heavy in the Java world, I would highly recommend picking up a copy of the book. It’s a fast, intriguing read with great insights and the chance to save yourself from looking around 4 years from now wondering what the heck happened, and why all of these developers can afford jewels and play with snakes while chatting among themselves.
Recently on the C# Design Patterns mailing list, an email came over about this post by Andres Aguiar. In it, he makes an argument that I have heard several times before – why should I write a simple test when I know it’s going to fail, and besides, I know what it needs to do, so why shouldn’t I just do that?
I thought about this, because I see it a lot. People looking at the pattern and examples for Test Driven Development dismiss it without trying or after trying it only a little bit because they don’t feel it is necessary. After all, they write perfect code, right? Setting aside that there are other reasons for TDD (#1: It’s not about testing, #2: Requirements change, features get added, and modifications invariably happen, and you want a safety net for that, etc) I wanted to focus on the hump developers seem to run into when they try it. It usually goes like:
“Ok, I want to add this feature. I’ll try it TDD! Ok, first add a test. Hmm, alright. What should I put in it? Oh, huh, a call to what I want the feature to do. But that’s going to fail! I don’t even have the class built! But fine, I’ll do it.
Ok, so now make it work. Wait, do the simplest thing? What the heck, hard code the variable? What kind of nonsense is that?! I have more important things to do. This TDD stuff is for the birds!”
Which brings me to my guitar. I’m a musician at heart. I’ve been playing drums forever, and play a little guitar and keyboard (and now bass) on the side. I’m also an impatient person, who wants to get right to the point.
So, when I first got a guitar, I ran out and picked up a guitar magazine. It had tablature to several songs I knew and I figured, heck, how hard can this be? Then the whirlwind of chords, notes, rests and other symbols flashed in front of me. The chord above the notes said G, but the tablature said:
--10--
--X--
--9--
--7--
--8--
--X--
and then, 5 measures later, the chord above the notes said G again, but this time it showed:
--X--
--10--
--9--
--7--
--8--
--X--
How was I going to remember all of that?! I got so frustrated that I put down the book and would get mad just looking at it. I mean, there’s just six strings! This shouldn’t be that hard. Besides, those guys (and gals) can’t be human – who gets their fingers to bend like that anyway! Mine hurt from 10 minutes of playing. This is crazy, I’m going back to drums.
But, as the musicians in the crowd know, it’s not as bad as it sounds. Sure, *that* guitarist chose to play a G *that* way, but there’s plenty of other, easier ways to do it. In fact, my Mel Bay chord reference lists 14 different ways one can play a G-Chord including:
--3--
--2--
--0--
--0--
--0--
--3--
and even:
--X--
--2--
--0--
--0--
--0--
--X--
And the funny thing is, from the craziest way to play a G, to the simplest, the masters use them all. Sometimes you go for the open chord. Sometimes you go for the barre chord. Sometimes you pick it. Sometimes you turn on distortion and crank it.
So how does this relate to TDD? It’s a challenge, because we are in familiar territory. We’re using a language we know, in a familiar environment, with the same challenges that we normally face, and, even better, we know the workarounds to those challenges. We have a method, a procedure in place. We know our code. We’re comfortable.
TDD takes us out of the comfort zone. It forces us to think differently about our code, about our problems and tasks and stories and features. We have to do planning and thinking and breaking down of our tasks into bite size chunks that we can give definitive endpoints to. It makes us actually do *more* work then what we normally would have done upfront. When I see I need to calculate the total from some entries, I want to just calculate it, not think about how best to calculate it, what are some ways we could verify it is calculating, etc, etc. I just want to type:
decimal total = 0.0m;
foreach Order order in orders
{
total += order.total;
}
return total;
and be done with it. Just like I want to learn the silly Pearl Jam song, and be done with it. I don’t care about the nuances, or the harmonies. I just want to be done. I’m too busy – don’t bother me with the details.
Some people are like that. I heard a story about Slash, the former guitarist of Guns n’ Roses, walking into a music store, picking up a guitar magazine featuring one of their songs, and remarking, “Oh, so *that’s* what I play.” He didn’t need to know the details, or back it up with theory. He knew what worked, and reliably did it over and over. He couldn’t tell you that the turnaround sounds good with a B minor because that is the 6th of the root and traditionally is used as a turnaround. But he could play it.
Like Slash, I believe there are a small set of coders who can pull this off. They don’t make mistakes. They know the design. They get it right the first time. They’ve no need for tests, or refactoring tools, or design documents. Give them a whiteboard and a silent office with a door, and let them be. Two weeks later you’ll have your incredible new feature that works the first time.
But, I don’t know first-hand any Slash coders. I know I certainly am not one. I have to slug through learning the positioning of the G chords. I have to work and work to build up dexterity in my fingers and calluses at the tips. I have to read books on theory, books on chords, books on song writing, and above all, practice. Sure, I’m annoyed with having to do repetitive runs over and over. And when I’m learning a new style, it irks me to have to muddle through the beginner stuff, playing slow. I want to be fast. I want to be good. I want the pill that makes me a star now.
Since I don’t have the pill, I just have to practice. And along the way, I learn I don’t have to play a G chord barred. I don’t have to do a turnaround in B minor. I learn C# minor works (even though it’s a bear to play) in some circumstances.
Above all, I learn that as I learn, I find the shortcuts so that I don’t have to start at page 1 of every book. I know what works for me. I know where I stumble. And if I want to just open to the middle I can. And if I just want to write the class before I run the test, I do.
And when I fail, I go back to Page 1 until I don’t anymore.
So, the tests are frustrating because they slow us down at first. They slow us down because we are learning a new language in a familiar syntax. Sure, the references and methods and classes seem the same, but really it’s all brand new. Which means we aren’t going to be good at it at first. Its going to take some time to get through. Time of going back to basics and reteaching ourselves this new-fangled thing called TDD that happens to use the same syntax that we use in C# or Java or Ruby or Python. Time of going slow, making mistakes, getting frustrated and working through it. Time of learning where our strengths are, so that we can shortcut, and where our weaknesses are, so we make sure we don’t.
Scott Bellware likens this to the movie the Karate Kid. I think that’s a great analogy. Practice, doggedly at first, until you learn what you are capable of.
So, my advice to Andres would be, stick with it. If you don’t like the duplication, factor it out. It might seem easy to just revert back, but push through. Figure out how you can make the things you don’t like go away. It seems you are on a good road, and you’ll get there. And if you run into bump
s along the way, there’s a whole community waiting to help.
A recent discussion on the TDD list led me to this paper from Rick Garlikov about how he used a method of asking questions to teach a group of third graders binary arithmetic in a short interactive session that I found quite fascinating:
The Socratic Method: Teaching by Asking Instead of by Telling