Last time was a refactoring session. Each pair reported which classes it improved and how. The tests mattered -- our system still works!
Question: Would we be better off by implementing the last stories on the board? As your customer, I say, "no". Your code is much better now than it was. Several of you now know another corner of the system you didn't before. As the person who will be maintaining and extending your code, the time was well spent.
Quick introduction to retrospectives. Safety. Positive and negative experiences.
What worked? Story selection. Continuous integration. Pairing. Tests.
What needs improvement? Many of the same. Some members are still uncomfortable with no BDUF, with tests first.
Aside on BDUF: If we had designed the system at the beginning of the project, knowing what you knew then, would we have as good and complete a system as we have now? In my professional judgment, no way. You know a lot more than you did then.
Most agreed that the team could be more productive if they were not required to do all programming in pairs. With my guidance, the team decided to loosen the restriction on pairing as follows:
At the next daily stand-up, the developer will explain all work done solo.
What could we experiment with?
One suggestion from two different team members: Start the iteration with a "gang programming" episode (similar to what we did at the start of Iteration 1). Everyone agreed.
We did the Planning Game, estimating 3/5 of a week based on the Memorial Day holiday and the end of the semester. Having completed 24 story points this full iteration, this gives the client ~15 story points for Iteration 2.
The team did some gang-programming. Before writing a test, the team began discussing "how things will work". At the start, it was not quite BDUF, but it got closer and closer the more you talked. Finally, the lead navigator said, "Can you write a test for that?" Excellent!
Writing a test led the team to design an interface deeply dependent on the underlying implementation. The coach jumped in with perhaps too much of a controlling attitude, and pushed the team back toward a design that expresses a requirement, not an implementation. Here is the sort of test we should be producing:
journal = GeneralJournal.new( Transaction.new( ... ) ) account = Account.new( initial_balance ) journal.close assert_equal( expected_balance, account.balance )
Or write a test at a lower level, the sort of code that expresses the interface between the journal and the account:
transaction = Transaction.new( ... ) account = Account.new( initial_balance ) account.applyTransaction( transaction ) # or pass only parts assert_equal( expected_balance, account.balance )
In any case, the key is: Tell, don't ask.
Please do read all three. It won't take long!
And keep learning Ruby. Enjoy!