Tuesday, July 27, 2010

Initial Impressions on Ruby

I took occasion the last couple of weeks to introduce myself to Ruby.  I had an exercise as impetus:
  • given 3 .csv data files, each one of which is delimited differently,
  • then produce a report of the data in 3 different sort orders.
The vast landscape of tutorials, books and other literature on Ruby notwithstanding, it was easy to pick The RSpec Book as my basic guide.  It is the only book with an emphasis on both micro- and story-tests, and counts Dan North, David Chelimsky and Dave Astels as authors.  (I am unsure who wouldn't want to follow those guys.)  With that as my guide I would find expert directions on driving solutions from tests.

I also required a language reference that could boot me up as quickly as possible.  This required a little more comparative analysis along the landscape of Ruby resources...along with some fitful starts and detours.  I eventually settled on Design Patterns in Ruby -- because it had a short chapter on Ruby basics in preparation for the discussion of patterns, and because I could use the patterns themselves as examples of good Ruby usage -- and Rails for Java Developers -- because it helped me transfer my Java and C# competency.

What first impressed me was the speed of the interpreter.  It had been many years since I worked with an interpreted language.  Likewise, I remember the vast migration of developers from Microsoft Basic to Borland Delphi Pascal because the compiled code offered execution speeds that were a drastic improvement over interpreted Basic.  I was thus pleasantly surprised to see my Cucumber and RSpec tests execute with speeds comparable to my JUnit tests.  Now, I'm sure the caveat between the speed of compiled and interpreted languages remain, and that the Java compiler will remain appealing to developers for that reason.  However, the speed of the interpreter distinguished Ruby in my mind.

Another impression regards the richness of the Ruby language.  I test-drove a solution to the same problem in Java with 32 tests and 9 domain classes.  My Ruby solution had 15 Cucumber scenarios (story tests) containing 51 steps and 23 RSpec examples (micro tests), so there were a lot of tests, however, I ended up with only 3 domain objects:
  • one to accept the command line input;
  • a report object to print the report; and
  • a parser object to parse the input.
Moreover, the report object only had 3 methods, and the parser object only had 9.  If I knew the language more intimately, then I'm sure the objects would've been even smaller.

What I mean by richness of the language is illustrated by my application's entry point:

def begin command_line
  abort USAGE if command_line.empty?
  abort FILE_NOT_FOUND if not command_line.all? {|file| File.exists?(file)}
  record_sets = command_line.collect {|file| File.open(file).readlines}
  parsers = record_sets.collect {|records| Parser.new(records)}
  Report.new(standard_output, parsers).print

Note how expressive are the guard clauses and the novel way in which Ruby allows to use the "if" conditionals after the clause.  Note also the expressive way in which booleans are asked -- with a question mark.

But for me, since my background is in Mathematics, I was really taken by the way in which the syntax adopts parts of naive set representation.  In mathematics, I can specify the set of all Integers between 1 and 10 as follows:
{∀  i ε I  |  1 <  i  < 10 }  
This reads:
for each i an element of the set of all Integers such that 1 <  i  < 10.
I found myself reading enumerators on arrays and hashes in the same way:
 zero_thru_ten = [] # initialize to empty array
 zero_thru_five = [0, 1, 2, 3, 4, 5]
 # for each element, i, append (2 * i) to array
 zero_thru_five.each { | i | zero_thru_10 << i * 2 } 
 zero_thru_ten # => [0, 2, 4, 6, 8, 10]
As it is common in mathematics to refer to elements of sets by x or y, or elements of matrices by i and j, I found that my refactorings often renamed references from those terms.  For example, here's a refactoring that I missed:
    def parse_input
      parsed = elements.collect { |i| columns.collect { |j| i[j] } }
      parsed.collect { |i| date(i); gender(i); i }

This code should be much more legible.  Nevertheless, the facility that Ruby provides for easily operating on arrays and matrices reminds me a great deal of my first programming language -- APL -- which was designed with matrix mathematics in mind.

(More to follow.)

Friday, June 25, 2010

Industrial Logic

It is difficult to learn agile engineering practices on your own.  No matter how many books you read or how many chances you take with production code, there is always a risk that you will end up in the weeds trying to slash your way out.  That's because the principles and practices inherent in agile software engineering require an apprenticeship with a master who has failed at all those practices for many...many years, and can guide you so that you can avoid the pitfalls.  This is not unlike other crafts -- most notably, carpentry and martial arts -- in which expert guidance is imperative.

But what of the aspiring agile software engineer, such as myself, who's inspired by the mastery of those at the vanguard of the movement toward agile?  One cannot afford the price of a coach unless you are independently wealthy.  And with the current state of agile adoption in the corporate enterprise at only 20% [Martin Fowler, ThoughtWorks Lunch-and-Learn, Chicago, circa late 2009], it is fortuitous if you gain coaching from a master during the normal course of your employment.

There is an approach that I can, with confidence, highly recommend: eLearning at Industrial Logic.  The reason why I can be so confident is that I could not have won my first agile job without that curriculum.

I had no prior agile experience before I was hired as an agile developer/tester.  But when I did my code review during the interview process, the reviewer was impressed with my application of test-driven development, refactoring, mocking and patterns that was evident in my code.  These are practices that I refined while working on Industrial Logic's courseware.

What makes the courseware most effective, and what distinguishes Industrial Logic from other Agile Training, Transitioning and Consulting Organizations, is the level of expertise of their team -- most of whom are luminaries in the agile community -- and the fact that their courseware is designed for them to provide you near-realtime feedback as you work through the exercises.

These exercises require you to think through problems. Many require you to write code to implement refactorings or patterns, or to test-drive toward solutions to problems that come from their real-world practice.  And if there is something that you don't understand about your answer, then Joshua Kerievsky or Bill Wake or Brian Foote or Naresh Jain or someone like that will respond to your question by the next day.  I cannot think of a better way to get that kind of intimate coaching at such a high level and at a price that is affordable to individuals like myself.  They, on the other hand, have even found a way to improve upon that.

They recently added a new pricing model to make the curriculum even more affordable to individuals.  But the most exciting prospect is their Early Access Program for their Sessions Album:  Sessions EAP.  I think this innovation, in lieu of an expert coach, will help me toward my goal of agile mastery.

The concept is simple.  Install their plugin into your Eclipse IDE.  When you press record and start test driving, the plugin will accumulate data in the background.  When you stop recording and upload your session data, you can obtain graphics on the quality of your test driving:
  • how many refactorings did you apply?
  • what kinds of refactorings?
  • what kinds of code smells did you address?
  • how long did you stay in the following cycles -- 
    • red? 
    • green? 
    • refactor?
  • etc.
You can begin to track your sessions with feedback like this:

and this:

So there is a path toward software engineering agility for individuals upon which I can embark.  My new goal is to spend the next 6-12 months following the entire Industrial Logic eLearning curriculum in much more depth than I was here-to-fore able, so that I can advance to that next level.