Too Cool for Internet Explorer

Sunday, April 6, 2008

I have tried a fast delivery, but…


I'm following Amy Hoy as much as I can, since last year, when I hear a podcast about her learning Rails process.


Now I have a testimony about her "Just ship. Seriously" article. We have a popular statement here in Brazil to summarize the idea:

The better is good’s enemy.

Delivering “the good” to achieve “the better”; if you try to deliver the better on the first try, you risk delivering nothing.

I try, as much as I can, persuade my bosses to forget about these HUGE projects, which will take months or years.

Ho Gosh, the testimony please! OK here it is: A few weeks ago, I get a mission:

“There is a user, in trouble getting data from this legacy client server application to pick some thing like 20 lines of information on a daily basis worksheet, I don’t want to involve the business-technology department on this, just go there and bring me a Java based solution”.

Here is the situation: The user takes 40 to 50 minutes, every single day, filtering information at two different pending flags on a supervisor level. There are 10 supervisors, so, 20 filtering actions on the system, counting grid lines returned by each, and put that value on a worksheet cell. Ridiculous! Yes, but that is the situation.

Mocking up the solution:

Execute two queries to get the proper grouped and counted information, and show the results.

My first option becomes: a night shift service, executing these poor performance queries and sending an email with the desired data to the user.

Some problems with the “web servers’ support” department and with the “job scheduler” application let us to another option.

The adopted option: improve the query performance (with specific indexes) and implement an intranet based application, where the user simply gets the information needed any time he wants.

All fine, this is a very simple application, so let me guess, to put it on production status on this BIG full of burocracy company, nothing less then a week, so that is it, my first shot, A WEEK to deliver this very simple application to the user.

Now the facts:

March, 12

I get the queries and specification done, and send it to a third part partner (Java factory) to get things done.

On my side, I start the HUGE burocratic process to get a new intranet application on production status. So, I started three different threads:

To the Data Administration department, create the necessary indexes, improving queries performance.

To the Logical Security department, to create the necessary user, with the necessary privileges to be used by the application.

To the Operations department to get the new application registered like an intranet one.

First problems:

The “partner” (Java factory), ask for a month to get the application done, two days after everyone agree that a week will be.

A week after I received the application, tested it, and figure they (the partners) changed the queries, and don’t get the behavior desired, which was: execute two different queries and show the result. I ask for a new version, with original queries and specified behavior.

Any way to get the burocracy done in advance, I have started another thread to the Systems Architecture department to check this non working version, just to verify if all necessary patterns and good practices where used.

March, 21

I get the final version ready and tested, by me and by the user, on my local development machine; so, I start a new thread to the Pre-Production department to get this new application ready on the Pre-Production environment, to the user evaluation.

Now you could say: well everything possible was done, the burocracy in advance and in parallel, so you have the application delivered and accepted by the user…

NO, not yet. We have more problems:

People from the Development and Pre-production departments do not create the database users on each environment at time (lack of communication between departments).

People from the Data administration department spent too much time to create the indexes on the right way on each environment (lack of competence here).

The procedures and forms to get a new intranet application registered, has changed since the last time I have done, so, I need to start this thread again with the new forms.

With these problems we miss the first chance to get this new application thru the weekly forum. Ooops, I forgot any new application to get into production status, need to be approved by the user department’s manager and get into the weekly technical forum.

When everything was fine, there was some technical problem with the data access configuration on the pre-production environment. Another wasted day…

Now we are close, the user tested the application on the pre-production environment, I get the approvement of the user department’s manager, so, next Wednesday we go thru the forum and finally next Thursday we will get this delivery done.

May be at April, 10, the user will be ready to use it I HOPE !

We know from the beginning the user will love this SIMPLE application, even more if we could deliver it in a WEEK as expected by developers.

There are some cases where you know that you try to deliver it fast…

But; there is always a “but”…

Friday, March 21, 2008

Ruby On Rails: Free Training

Sunil Kelkar is a programmer, author, trainer and speaker. A recognized expert in the field of software development with over 15+ years of I.T. experience, Sunil has consulted and trained teams at various companies in India and the US.

He has been involved with Rails for the last two years and Java since 1997.

The first batch of the Free Online Introductory Course on Ruby On Rails starts from 12th April 2008. Registrations are now open.

I'm already registered !

Sunday, March 16, 2008

Ruby from Test::Unit to RSpec part 3 of 3 b

The second part of this article, is about the Spec framework, the one that give Rspec the original name.

After the customer and the developer agree, over a Story describing the business behavior, is time to go on with a more techical specification.

The Spec framework provides RSpec a Domain Specific Language with which you can express executable examples of the expected behaviour of a system.

Thinking about the grading process, we need to describe our process behaviour, so the initial structure will be like this:


require 'spec'
require 'grading'

describe Grading do
...
end

Now, to describe the behaviour, use the folowing sample structure:

1 - To stablish states, of the involved objects.

before(:each) do
(1..9).each { |i| @stack.push i }
@last_item_added = 9
end

2 - RSpec adds "should" and "should_not" methods to any application object.

@student.grade.should ...
post.should_not ...

3 - And a "expectations" set.

be_...(...)
have(...).(...)
raise_error(...)

All together now…

# grading_spec.rb
require 'spec'
require 'grading'

describe Grading do
GradingOverflowError = '123'
before(:each) do
@grading = Grading.new
end

it "should score more then 50 to pass" do
@grading.score(51) == 51
@grading.status('pass').should == 'pass'
end

it "should complain when score more then 100" do
lambda { @grading.score(101) }.should raise_error(GradingOverflowError)
end
end

# grading.rb
class Grading
def score(grade)
if grade > 100
raise '123'
end
end

def status(status)
@status = status
end
end

To run this specification, use this command:

ruby grading_spec.rb --format specdoc

And should get the following result

Grading
- should score more then 50 to pass
- should complain when score more then 100

Finished in 1.219 seconds

2 examples, 0 failures

Now try to add this specification:

it "should get status 'pass' to be assigned to next batch" do
@grading.status('pass') == 'pass'
@grading.assign_batch('pass').should == 3
end

And try to get this result:

Grading
- should score more then 50 to pass
- should complain when score more then 100
- should get status 'pass' to be assigned to next batch

Finished in 0.875 seconds

3 examples, 0 failures

Now start RSpec in practice on the next project.

Sunday, March 2, 2008

Ruby from Test::Unit to RSpec part 3 of 3 a

This would be the last article on this series, but I decided to split this last article about RSpec in two parts:

  • The Story framework (this one)
  • The Spec framework (the next one)

The reason to do that is the importance of this part over the next one. It is near impossible to find useful and complete samples on the Story framework nowadays.

This is the most important part on RSpec, the one that let the customer and the developer to use the same language on understanding the business behavior and specifying the application implementation.

Behaviour Driven Development or BDD, is a thinking evolution on TDD, basically changing from a developer view point to a problem solver view point. Changing from thinking about technical implementation details, to thinking about the problem itself, and how to provide value to the customer through software.

Even with TDD, developers are, most of the time, thinking about technical aspects of the system and often write poor tests.

BDD helps to evolve into a deeper analisys of what the problem really is, which context does the problem apply to, and what are the specifications proof to show that a solution can be demonstrated, forcing developers to focus on the problem and gain a full understanding on it prior to coding.

As system or business analysts, we all agree that would be nice to express customer desires and application specifications, on a common business domain language and vocabulary.

To achieve that RSpec merge Dan North's RBehave into it, since version 1.1, turning RSpec into a BDD, two pieces framework for Ruby, used to write and execute examples of how the application should behave:

  • A Story framework describing application level behavior.
  • A Spec framework describing object level behavior.

Starting with the Story framework, the story narrative should contain a Role, a Feature and a Benefit. To ensure that we use a template like this:

As a (Role)
I want (Feature)
So that (Benefit)

For example:

As a customer
I want to withdraw cash from an ATM,
so that I don't have to wait in line at the bank.

From this starting point and with the agile TDD in mind, we need to specify the acceptance criteria in terms of scenarios. Again, to ensure that we use a template like this:

Given (some initial context, the givens)
When (an event occurs)
Then (ensure some outcomes)

For example:

Scenario 1: Account is in credit
Given the account is in credit
And the card is valid
And the dispenser contains cash
When the customer requests cash
Then ensure the account is debited
And ensure cash is dispensed
And ensure the card is returned

Now for a practical example, imagine a conversation between a developer and a customer:

Developer: describe how to evaluate a student performance.
Customer: Given a specific student, if the student achieves a grade of 50 it should be assigned to a second chance on the summer class. If the student grade is greater than 50, the student pass, if the grade is less then 50, the student fails.

This is a story about a student's grade evaluation.
The text up here above the Story: declaration won't be processed
So you can write whatever you wish, like this kind of comments!

Story: Student grade evaluation

As a school staff member
I want to know if with a specific grade a student has stay, pass or fail
So that I can easily assign (him|her) a new status

Scenario: student grade is just the average
Given a student named 'Monique'
When the student is given a grade of 50
Then the student batch should be same

Scenario: student grade is sufficient to pass
Given a student named 'Michelle'
When the student is given a grade of 60
Then the student batch should be next

Scenario: student grade is insufficient to pass
Given a student named 'Mike'
When the student is given a grade of 40
Then the student batch should be same

Each Given, When and Then is a Step. The Ands (if any), are each the same kind as the previous Step.

Now with the grade.txt file above we need to check it with RSpec.

To do that we just need a simple Ruby program like this.

#!/usr/bin/env ruby
# grade.rb
require 'spec/story'

with_steps_for :grade do
run 'grade.txt'
end

Runing this program, the story with 3 scenarios will be analized, and produce an output with a final conclusion like this:

3 scenarios: 0 succeeded, 0 failed, 3 pending

And nine pending steps alerts, three on each scenario

The scenarios fragments, the Givens, events, and outcomes, are enough to be represented by executable code.

Steps are defined in Ruby like this:

#!/usr/bin/env ruby
# grade_steps.rb
steps_for(:grade) do
Given("a student named '$name'") do |name|
@student = Student.new(name)
end
When("the student is given a grade of $grade") do |grade|
@status = @student.evaluate(grade)
end
Then("the student batch should be $batch") do |status|
@batch = @student.assign_batch(status)
end
end

And objects involved are supported by a class defined on a program like this:

#!/usr/bin/env ruby
# student.rb
class Student
def initialize(name)
end
def evaluate(grade)
end
def assign_batch(status)
end
end

Now we need to include these programs on the check program above, and it will look like this:

#!/usr/bin/env ruby
# grade.rb
require 'spec/story'
require 'grade_steps'
require 'student'

with_steps_for :grade do
run 'grade.txt'
end