Pages

Monday, March 29, 2010

My Venture into JBehave via Conway's Game of Life

Having used Conway's Game of Life (CGoL) at several CodeRetreats* to practice Test Driven Design (TDD), I thought I would revisit it when I took my first steps into Behavior Driven Development (BDD) with JBehave.

I downloaded JBehave 2.5 and refreshed my memory of the GoL rules:
  1. Any live cell with fewer than two live neighbours dies, as if caused by underpopulation.
  2. Any live cell with more than three live neighbours dies, as if by overcrowding.
  3. Any live cell with two or three live neighbours lives on to the next generation.
  4. Any dead cell with exactly three live neighbours becomes a live cell.
What I love about using GoL for learning BDD is that the rules are practically already written as Given-When-Then scenarios. Just minor tweaks (including changing to the US spelling of neighbor) gave me:
  1. Given a live cell with fewer than two live neighbors, Then the cell is dead.
  2. Given a live cell with more than three live neighbors, Then the cell is dead.
  3. Given a live cell with two or three live neighbors, Then the cell is dead.
  4. Given a dead cell with exactly three live neighbors, Then the cell is alive.
All that's missing is a "When". All 4 rules have the same "When", which is "When I calculate the next generation". Taking that into account, I get:
  1. Given a live cell with fewer than two live neighbors, When I calculate the next generation, Then the cell is dead.
  2. Given a live cell with more than three live neighbors, When I calculate the next generation, Then the cell is dead.
  3. Given a live cell with two or three live neighbors, When I calculate the next generation, Then the cell is dead.
  4. Given a dead cell with exactly three live neighbors, When I calculate the next generation, Then the cell is alive.
Since any given rule could only have 9 different cases (0-8 alive neighbors) I decided that, rather than deal with the logic of "less than"/"fewer than"/"exactly", I would spell out every specific condition that meets a rule.

JBehave expects scenarios to have separate lines for Given, When, and Then. Rule #1 can be completely expressed as:

Scenario:
Given Rule 1: alive cell with 0 neighbors
When I calculate the next generation
Then the cell should be dead

Scenario
Given Rule 1: alive cell with 0 neighbors
When I calculate the next generation
Then the cell should be dead

I've written the variables in the scenario in bold here. That will become more clear later. I inserted "Rule 1" into the given just to make it easier to know what rule I'm on when a scenario fails.

I wrote scenarios for every condition for all 4 rules (it came out to 18) and put them in a file named "i_can_calculate_the_next_generation". JBehave requires scenarios be named all lower case with words separated by underscores. You can see all the scenarios and all the source code in my github repo for this project.

(If you're a Windows developer and you don't like the idea of files without extensions, I found a blog post that showed a customization that allowed JBehave to read ".scenario" files instead of files with no extension, but I decided not to bother with that for this first experiment.)

Once I have my scenarios written, it's time to code. JBehave requires that the class corresponding to the scenarios be the same words, but camel-case, and without underscores, so I created ICanCalculateTheNextGeneration.java

The entire class is:
import org.jbehave.scenario.Scenario;

public class ICanCalculateTheNextGeneration extends Scenario {
public ICanCalculateTheNextGeneration(){
super(new RuleEngineSteps());
}
}
Now for the meat of the code, starting with the implementation of RuleEngineSteps:

@Given("Rule $ruleNum: $aliveVal cell with $aliveCount neighbors")
public void aliveOrDeadCellWithPossiblySomeAliveNeighbors(int ruleNum, String initialLiveState, int numberOfAliveNeighbors){
ruleEngine = new ConwayRuleEngine();
cell = new Cell(initialLiveState.equals("alive"), numberOfAliveNeighbors);
}

@When ("I calculate the next generation")
public void iCalculateTheNextGeneration() {
ruleEngine.CalculateTheNextGeneration(cell);
}

@Then ("the cell should be $resultingAliveState")
public void theCellShouldBe(String expectedAliveState){
String actualAliveState = "alive";
if (!cell.isAlive()){
actualAliveState = "dead";
}
Assert.assertEquals(expectedAliveState, actualAliveState);
}


Look for a moment at how variables are used between the scenarios and the code. Remember I had: "Then the cell should be dead"? Look at the corresponding @Then in the code:
@Then ("the cell should be $resultingAliveState")
public void theCellShouldBe(String expectedAliveState){
Whatever I want as variable in the scenario, for example dead above, I name a variable starting with "$" in the attribute line and use the same name (without "$") as the parameter to the method.

Cell.java is basically only setters and getters. ConwayRuleEngine.java is where the business logic lives (Excuse the pun). Initially, CalculateTheNextGeneration() will do nothing.

When I run ICanCalculateTheNextGeneration.java as a JUnit test in Eclipse. I get a red bar. In the console I see:
(i_can_calculate_the_next_generation)
Scenario:
Given Rule 1: alive cell with 0 neighbors
When I calculate the next generation
Then the cell should be dead (FAILED)
and other failures. All that's left is the implementation of the business logic, which I'll leave as an exercise for you. (Or you can look at my code).

Once I got my code working, I refactored it. I've tried to reduce duplication and make the code very clean. I'd appreciate any comments you have.

Finally, I invite you to check out the Agile Skills Project, a non-commercial, community-based project which aims to establish a common baseline of the skills an Agile developer needs to have, skills possibly including TDD and BDD.

---------------------------
*A plug for CodeRetreat if you're not familiar with it: Patrick Welsh and Corey Haines have created a kind of one-day coding dojo that gives software developers who want to improve their craft a chance to practice agile skills like Pair Programming and TDD. We do 40 minute iterations on Conway's Game of Life, have mini-retrospectives, throw out our code before the next iteration, and have a retrospective of the whole event at the end of the day. CodeRetreats have been held in Java and Ruby (that I know of) and in several countries. If you haven't been to one, I encourage you to go to one.



Wednesday, March 3, 2010

Why do we Pair Program?

One of the most controversial agile practices has to be Pair Programming. Matt Wynne has a blog post that lists several personae and why they don't want to pair program. It's a preview of what he presented at Agile 2009.

Other people have written about the benefits of successful pair programming, which is an after-the-fact analysis. Right now I'm going to look at why we pair program, which is about intention

I recently started thinking about why we pair program. What is our intention in using this practice? I came to the conclusion that Pair Programming promotes many of the Seven Skill Pillars named by the Agile Skills Project.

Pillar: Collaboration
Pair programming is specifically listed as a skill of the Collaboration pillar, but it also supports Collective Ownership by preventing silos of knowledge (technical or domain knowledge) from forming.

Pillar: Technical Excellence
Working directly with another developer reinforces good development practices, and two sets of eyes on code lets fewer mistakes make their way into the product.

Pillar: Self Improvement
Pair programming sets a tone for a culture of continuous learning by creating ongoing opportunities for co-mentoring.

Pillar: Supportive Culture
The transparency around each developer's skill level that comes from programming in front of each other gives a developer an opportunity to be tolerant and encouraging, knowing they will receive the same treatment in return.

Pillar: Confidence
By supporting each other in the practices of Continous Integration and Test-Driven Design, and by having a design and implementation that is jointly created, a pair can know they are producing quality code.

Saturday, January 16, 2010

CodeMash Precompiler Session # 1 - Ruby Koans

As I mentioned in my last post, I recently returned from CodeMash 2010, where I attended two PreCompiler sessions. For the morning session, I attended "The Ruby Koans, Learning Ruby One Test at a Time with Joe O'Brien and Jim Weirich" which taught Ruby syntax and how to write tests in Ruby. (Joe also gave an excellent and extremely popular talk called: "Refactoring the Programmer"

The word "koan" comes from Zen Buddhism. As I understand it, Jim and Joe called their talk "Ruby Koans" because of their unique style of teaching that relies as much on mystery and intuition as it does on rational thinking.

Jim has asked participants in the CodeMash session to show the koans to someone else, so I encourage you to look at them. You can try the koans yourself as follows:

(1) Have a working version of Ruby:
- Windows: Install from: http://rubyforge.org/frs/download.php/66871/rubyinstaller-1.8.6-p383-rc1.exe
- Macs: OS X comes preloaded on Macs so you are ready to go.
- Linux Users: Use apt-get, or whatever is appropriate for your system

(2) Download the Ruby Koans and install into a working directory:
- http://cloud.github.com/downloads/edgecase/ruby_koans/rubykoans.zip

The file README.rdoc is a text file that explains the concept, tells how to get started, and gives contact information.

To set up for the exercise: unzip the koans, open a command-prompt, and cd to the directory containing the koans. The exercise starts at the most simple level possible, but if you complete the koans, you will learn most of the Ruby syntax and see examples of how Ruby behaves at edge cases.

To start the exersise, give the command:
ruby path_to_enlightenment.rb
You should see the following result:

Thinking AboutAsserts
test_assert_truth has damaged your karma.

You have not yet reached enlightenment ...
is not true.

Please meditate on the following code:
./about_asserts.rb:10:in `test_assert_truth'
path_to_enlightenment.rb:28
The line " is not true." gives a hint as to why the test failed.
The line after the "Please meditate..." line tells what line of code the test failed on.

Looking in the file about_asserts.rb around line 10, we see:
def test_assert_truth
assert false # This should be true
end
In Ruby, def/end declares a method, and the word: "test_" at the start of the method name declares it as a test. The comment is a hint from Joe that the test fails, in this case rather obviously, because it is asserting false. So this koan demonstrates the a test in its simplest form, one that asserts a boolean condition. If you change false to true and run "ruby path_to_enlightenment.rb" again, that test will pass and the error you will see:
Thinking AboutAsserts
test_assert_truth has expanded your awareness.
test_assert_with_message has damaged your karma.

You have not yet reached enlightenment ...
This should be true -- Please fix this.
is not true.

Please meditate on the following code:
./about_asserts.rb:16:in `test_assert_with_message'
path_to_enlightenment.rb:28

So now the test_assert_truth test passes and the test_assert_with_message test is failing. The code for the second test is:
def test_assert_with_message
assert false, "This should be true -- Please fix this"
end
and we see where the "This should be true..." message comes from. Joe has now shown us what an assertion with an error message looks like. Again change false to true, rerun the ruby command and you'll see the next failing test.

The koans go on to present illustrations of control statements, hashes, scope, strings, arrays, inheritance, iteration and others language details. I don't think anyone at the PreCompiler finished all the exercises during that session - I sure didn't - but it's clear that I will know a lot about Ruby syntax when I do.


Finally if you have questions about the koans, you can reach Jim at his website http://onestepback.org/ or @jimweirich on Twitter. Or you can reach Joe at his website http://objo.com or @objo on Twitter

Back from CodeMash 2010

I just got back from a great experience at CodeMash 2010. This was my first CodeMash, and it will certainly not be my last. If you're a software developer and you've never gone to a CodeMash, I can't recommend it enough. (If you're a developer and you've already gone, I don't have to say anything because I know you'll be going back.) Besides all the technical goodness, there was lots of fun!

If you're not familiar with CodeMash, its home page describes it as a unique two (or optionally three) day event:
"... that will educate developers on current practices, methodologies and technology trends in variety of platforms and development languages such as Java, .NET, Ruby and PHP. Held [in] January, at the lush Kalahari Resort in Sandusky, Ohio, attendees will be able to attend a world-class technical conference amid Ohio's largest indoor waterpark.
There were also sessions on career development, TDD/BDD, Agile/Lean/Kanban methodologies, dynamic languages like F# and Scheme, development for mobile platforms like iPhone and Android, and too many more for me to list here. See the session list for more, and for detailed writeups and presenter bios.

This year, there were three keynote addresses and loads of software-development-related sponsors, the likes of Microsoft, Amazon, Compuware, RedGate, and ComponentOne gave talks, demonstrations, held raffles and gave away lots of swag.

But some of the most valuable experiences come from talking with other developers in the hallways, between sessions, at open space meetings organized by participants based on their interests, in the Coding Dojo room, and at the cocktail party.

I mentioned that CodeMash is two or optionally three days. They call the optional third day events, held the day before the official conference opens, the PreCompiler. The PreCompiler Sessions are 4 hour, hands-on, interactive labs. That's not to say that if you only attend the main conference you won't have a chance to sit down at a machine and try somethings out, but interactive sessions at the main conference are shorter (only about an hour) and tended to be less in-depth.

I attended 2 PreCompiler sessions, "The Ruby Koans, Learning Ruby One Test at a Time with Joe O'Brien and Jim Weirich" and "Practical T/BDD - Half Day Hands-on Lab with Phil Japikse"

I'll tell about these in subsequent blog posts.

Monday, January 11, 2010

Grand Rapids CodeRetreat ... but it's in Ruby

I'm a big fan of CodeRetreat. Besides being a fun day, it's a great way to practice agile things like: pair programming, supportive environment, software craftsmanship, TDD, retrospectives, courage, and so on. I think they are great events for both aspiring Agilists and experienced Agilists.

I read Jeremy Anderson's blog post about an upcoming CodeRetreat in Grand Rapids. I was all set to go when I read that it will be held in Ruby, and since I haven't used Ruby, I was discouraged. As much as I'd like to try it, I'm not sure how much time I'll have in my schedule before then.

Then I found TryRuby. It offers an interactive Ruby prompt and a follow-along tutorial, right in your browser! And there's another tutorial I found, Ruby in Twenty Minutes .

So I guess I'll have to revisit the sessions I planned to attend this week at CodeMash 2010 and see if there are beginner Ruby sessions. Perhaps, between them and some extra work during downtime, I'll pick up enough Ruby to feel comfortable attending the Grand Rapids Code Mash next month.

Monday, November 23, 2009

What is agile communication?

In thinking about some things for the Agile Skills Project, I realized that agile teams communicate differently than non-agile teams.

It seems to me that agile communication aims to be:
  • public (vs private or secret) [public within the entire team, not public as in news media]
  • early (vs delayed)
  • spoken, preferably in person (vs email)
  • free from judgment (vs assigning blame)
  • osmotic (vs selectively broadcast)
  • flat (vs hierarchical)
A significant enabler of agile communication is the Supportive Environment Agile Pillar.

What characteristics of agile communications do you notice?

Monday, November 16, 2009

Why we say: "No Best Practices"

I came across an great article from 2005 titled: No Best Practices and it reminded me that there was some discussion about the term "best practice" at the recent 1DevDay event.

Besides speaking to reasons why we say there are no best practices, James Bach gives a nice list of "simple, honest alternatives":
  • “Here’s what I would recommend for this situation.”
  • “Here is a practice I find interesting.”
  • “Here is my favorite practice for dealing with {x}.”
  • “{Person X} attributes {practice Y} for his success. Maybe you’d like to learn about it.”
as well as a list of answers to common replies to his argument, replies like:
  • “I don’t mean ‘best practice’ literally. I’m just suggesting that this is a damn good practice.”
  • “When I said this practice is a ‘best practice’ I meant it was best for a certain context. But pretty much everyone in the industry shares that context, so what’s the point of talking about context?”
  • “This practice represents a consensus among industry leaders.”
  • “Lighten up. It’s just an expression.”
It really helped me get clear about why we say: "No Best Practices".