Friday, November 27, 2009

Invoking Glimmer Tests and Specs via Rake

As part of implementing the Game of Life UI in Glimmer, I actually updated Glimmer's Rakefile to invoke all tests successfully. Since the Game of Life domain logic was test-driven with RSpec, I also had Rakefile invoke both specs and regular unit-tests with the default command: jrake (the j is needed because Glimmer runs on jRuby instead of Ruby)

"jrake spec" invokes specs alone.
"jrake test" invokes unit-tests alone.

More improvement and changes are coming Glimmer's way including an attractive image on the landing page:

Thursday, November 26, 2009

Conway's Game of Life - Glimmer Edition

I recently attended a Chicago Ruby group meeting where everybody paired up on implementing a version of Conway's Game of Life in Ruby. At the end of the meeting, the logic of the game was completely test-driven and ready for use, so I decided to slap on a Glimmer UI on top of it afterward:



Here is Glimmer's repository:
http://dev.eclipse.org/svnroot/technology/org.eclipse.glimmer.core/

Here are the tests written with RSpec:
http://dev.eclipse.org/svnroot/technology/org.eclipse.glimmer.core/spec/samples/game_of_life/

And, here is the implementation:
http://dev.eclipse.org/svnroot/technology/org.eclipse.glimmer.core/samples/game_of_life/

The game logic is in grid.rb and cell.rb whereas the UI code is in game_of_life.rb. cell_presenter.rb provides the presenter needed for data-binding with the MVP pattern.

Here is how the Glimmer UI code looks like:

width = 7
height = 7
grid = Grid.new(width, height)
shell {
  text "Conway's Game of Life (Glimmer Edition)"
  composite {
    layout GridLayout.new(width,true)
    (0...width).each { |x|
      (0...height).each { |y|
        button {
          layout_data GridData.new(fill, fill, true, true)
          text bind(CellPresenter.new(grid, x, y), :alive)
          on_widget_selected {
            grid.toggle_aliveness!(x, y)
          }
        }
      }
    }
    button {
      text "Step"
      on_widget_selected {
        grid.step!
      }
    }
  }
}.open

It simply iterates over the Game of Life grid cells, wrapping each with a presenter and binding it to a button in the UI:
text bind(CellPresenter.new(grid, x, y), :alive)

When a button is clicked, the cell aliveness is toggled to "alive" (showing 'o') or "dead". This enables player to lay out the grid of cells:
on_widget_selected {
  grid.toggle_aliveness!(x, y)
}

Finally, to step the game, there is a "Step" button that steps the grid into the next generation, resulting in cells that die, new cells born, and cells that simply continue to be alive:
button {
  text "Step"
  on_widget_selected {
    grid.step!
  }
}

One thing that is noteworthy is that Glimmer's support for data-binding greatly facilitated the decoupling of the UI from the domain logic enabling us to write our domain code in full isolation of the UI, and later adding the UI and its related presentation logic via the Glimmer UI DSL and the presenter.

Hit me up with comments or an email if you have any questions.

Happy thanksgiving!

Tuesday, November 24, 2009

Conditionals in Unit Tests

One of the questions newcomers to TDD (Test-Driven Development) often ask is: how can I trust test code to be correct?

Well, the reality is that it is not black and white. Not every instance of implementation code is prone to bugs (think getters and setters) and not every instance of test code is perfectly free of bugs. However, as software engineers, we are more concerned with the practical aspects of software development, and experience seems to indicate that if you write your test code in a linear fashion without using conditionals, then it is less prone to having bugs, and thus can serve as a useful tool in driving reliable implementation code as per the requirements specified.

Back to the question: how can I trust test code to be correct?

Test code often follows this structure:
  • Pre-conditions setup
  • Action being tested
  • Post-condition verification
For example (in Ruby):

# pre-conditions
time = Time.new

# action
hours = time.hours_between(9am, 2pm)

# post-conditions (specified with RSpec)
hours.should == [9am, 10am, 11am, 12pm, 1pm, 2pm]

Since that code is linear and free of conditionals, if it parses successfully, it generally expresses what it says without much ambiguity and thus has very little chance for error.

Now, let's look at a version of the implementation after a few tests have been written:

def hours_between(start_time, end_time)
  (numeric_time(start_time) .. numeric_time(end_time)).map do |numeric_time|
    textual_time(numeric_time)
  end
end

def numeric_time(time)
  meridian_indicator = time[-2..-1]
  numeric_time = time.delete(meridian_indicator).to_i
  numeric_time = meridian_indicator == "am" ? numeric_time : numeric_time + 12
  numeric_time = 0 if numeric_time == 24
  numeric_time
end

def textual_time(numeric_time)
  meridian_indicator = numeric_time < 12 ? "am" : "pm"
  textual_time= numeric_time < 12 ? numeric_time.to_s : (numeric_time - 12).to_s
  textual_time= "12am" if textual_time == "0am"
  textual_time+ meridian_indicator
end

Do you notice how much complexity there is with reading statements that involve conditionals. It's doable, but definitely takes work despite how factored the code is.

Note that the implemented functionality is not entirely correct as it only works if the range specified is between 1am and 11pm. More tests need to be written to drive the rest of the implementation. However, given that tests do not have any conditionals, they provide us with an automated way of testing that our implementation works according to plan.

So, avoid conditionals in unit tests, and you will benefit from them in implementing more reliable code.

Friday, November 06, 2009

Social Dev Camp - Iterative Prototyping: Discover Your Interface Sooner!

Updated Nov 8, 2009

I'm giving a presentation at Social Dev Camp / Chicago this Sunday at 2:30PM.

Title:

Iterative Prototyping: Discover Your Interface Sooner!

Abstract:

Iterative incremental design of software is great as it helps developers discover how to build their applications gradually with small low-risk steps followed by user acceptance testing. However, why limit this agile approach to writing code? This same technique can be applied to user interfaces too during the early conceptual stages of design, enabling ability to make changes in hours instead of weeks since it is done to paper instead of code. For example, can you think how much more time it would take to redesign each page in MySpace to look more like Facebook if it is already coded vs when it was still on paper? Come to this talk to learn the basics of Iterative Prototyping and how you can apply this valuable tool to achieve better user experience.