Pages

23 June 2006

Feedback from another Dojo

Today's Dojo was interesting, at least interesting enough to keep a trace of it.

The subject

I wrote a small Dojo subject a week ago that was selected by the group. The subject was to have a DSL to describe Recipes and to be able to compute some data about it.

Let's take the easy-child-access yogurt recipe:
  • Pour one yogurt
  • Add 3 eggs
  • Add 100 ml of vegetal oil
  • Add 200g of sugar
  • Mix all with 300g of flour
  • Cook during 30' at 180° celsius
The idea is to be able to compute:
  • the list of ingredients with their quantities
  • the cooking time
  • the preparation time
Of course, you can start with simple calculation rules and add more complex ones such as:
  • "Melting 50g of chocolate takes 30'' in the microwave"
You can also play with some grammar aspects:
  • synonyms: Add, Pour
  • complements: in a jar, with a mixer
  • ...
I had several objectives with this subject:
  • Make people collaborate on a quick design session
  • Implement a parser for a DSL
So far, people decided to vote for this subject and we chose to focus on the quick design session then on some coding.

The Quick Design Session

This session was elaborated with somebody at the board during 5 mn, sketching a domain model. We quickly converged on the main classes: Recipe, Action, Ingredient, Quantity and thought about some kind of PreparationTimeEngine that was responsible for calculating preparation time depending on an action and its ingredients.

The acceptance test

We started coding an acceptance test for a very simple recipe: a yogurt with sugar!
  • Take 1 yogurt
  • Pour 10g of sugar
And programming the acceptance test took us the remaining 35' we had on the session,...

The retrospective

Yes, the result was not tremendous, and I am still thinking: "wow, 5 poor classes, 1 acceptance test = 1,5 hour, not a great productivity".

Anyway, I liked this Dojo for what we learned:
  • :-) The quick design session pleased everybody because they really had the opportunity to share a common design. Something to do again "live", because this really accelerates the feeling of common ownership
  • :-) I liked the emphasis on getting the acceptance test as readable as possible and the hunt for local variables that were not necessary
  • :-) I liked the discussion around the necessity to have factory methods: createAction,...
  • :-) There's no better place to jellify the group around fun and quality code
  • :-\ Some pair co-pilot were relatively silent. Their role was taken up by the group
  • :-\ Yes, I still think the productivity was poor and I think this shows plenty of improvement room for the group
  • :-? We should try to enforce the rule that the group is silent and only the pair should talk. The other ones could take notes, observing the functionning of the pair
  • :-? I wondered about the use of Java for this kind of Dojo. Python or Ruby would be more appropriate and productive
  • :-? It is certainly better to prepare the Dojo subjects, so that the participants can get up to speed in a limited time. I had prepared a written spec with an acceptance test, but written acceptance tests would have been better. I think this is even more true with some of the subjects we wanted to do: Bayesian Filter for spam, Java Plugin Framework,...
Now, let's see how goes the next one.

22 June 2006

Responsabilities dilemna

When can you say "too much is too much"?

Let's say you have an object: Customer. Wow, how original! Anyway, please bear with me.

So, your Customer class has some "customer info" responsabilities, but also it may be a "billable customer" or a "prospective customer" (for cross-selling). Hey wait, it can also be a "persistent customer". And so on.

How do you manage all these responsabilities with a classical object-oriented language?

The Horror show

First of all, you could put all the code in the Customer class. Boo-oo! "OO for beginners" tells us its bad, you end up with a 2000 lines class.

or,... you could have only a Customer class containing the customer info and a BillManager that bills a customer, a SellManager that tries to sell him stuff,... No, I'm kidding, let's forget that one too.

or,... you could inherit from a PersistentObject class, derive BillableCustomer from Customer,...

Time to stop the horror show.

Delegation forever

Then you can put everything in the Customer, but it can delegate to other objects. For instance, customer.save() would delegate the real action to a CustomerRepository. This would be the same for other responsabilities.

What about testing? Oh yes, testing,... Ok, you can use your best-of-breed dependency injection framework to inject the proper objects behing finely crafted interfaces.

Right, but what about dependencies anyway !? Your Customer class is still not reusable without a whole bunch of interfaces! What if you don't want your customer to be billable at all?

Ok, you can set the persistence aside by having the Customer clients make calls to an appropriate factory after dealing with the customer. But what can you do with the billing responsability (No, not the BillManager again,...)?

Object inheritance

Another way, suggested by the Streamlined Object Modeling book is to use "Object Inheritance". You use the Actor-Role pattern and define 2 classes:
  • the actor: Customer class
  • the role: Billable customer class
A billable Customer class will have the same interface as the Customer class and will delegate all customer info requests. We could say this is a kind of "external delegation" in contrast to the "internal delegation" mentioned before.

When discussing this pattern with a friend recently, I told him that I felt uneasy with one thing (beside the heavy use of delegation which results in silly code in Java). It was strange for me to have 2 objects representing the same logical entity.

He told me to consider another way to see things: BillableCustomer would be a "decorator" of Customer. If I need a BillableCustomer, I write: new BillableCustomer(customer) and do my job with it. I really like this way of seeing things. There's still one drawback in my mind: if BillableCustomer needs to be persisted, you still have to consider 2 entities for the same logical object in the system.

Dynamic languages to the rescue

In the end, what I would like to do is to mix behaviour into an object. This is exactly what Ruby allow me to do: I have a Customer class and I can extend it Billable responsabilities at runtime:

customer.extend(Billable)

This is the idea of "Duck typing". You cannot rely on the object type alone to know its capacities. If it walks like a duck and quack like a duck, then it is a duck (even if it is really a swan,...)

There is certainly closer to "object-orientation" than any class-interface-inheritance pattern. If we think of it, object are often thought as human when doing object analyzing. And we, as humans, often learn and forget, get abilities and loose abilities. Objects should be able to do the same.

A new persistence challenge

But "when is easy, too easy?".

Yes, when it comes to persistence, how do you do in Ruby with something like that? ActiveRecord was not thought with that kind of use in mind.

;-) I have no doubt that Rails fanatics could come with a fairly elegant solution to that problem.

18 June 2006

Enlightment, planning and convictions

Sometimes, learning new things is scary.

You've just learned something you find very important, acquired a new skill and you ask yourself:

"How can I have worked without understanding something so crucial during all this time?"

Well, another more useful question usually pops up in my head:

"Why was I not able to pick this up before?". This is certainly more useful because it opens up the possibility to pick it up faster next time!

Recently, I got the feeling that I learned very important lessons about the raison d'être of agile methodologies.

The cards array enlightment

I remember standing in front of our cards array contemplating the next iteration planning and the result of our last planning game. I was thinking: "now I know why I was not so effective as a project manager for planning the activity of the project" (better late than never!)

Planning, yes but why?

I always had difficulties for planning software activity, and was even beginning to think that development was something like the butterfly story introducing any chaos theory presentation: a beat of wings and milestones go away.

Many of my attempts to get more insightful plannings failed. Here's a set of recurring issues:
  • how can the development planning stay in line with the global roadmap (especially if it is very "ambitious" but also a moving target)?
  • how do you plan bugs?
  • how can you make accurate predictions regarding the delivery date?
  • how do you fight developers natural optimism ("well, 2 days should be ok for the parser")?
  • how do you plan non-development time (meetings, holidays, illness,...)?
Moreover, every "aggressive planning" I saw was the recipe for repeated failure. And the effects on the team are disastrous: "Whatever we do, we are late". But "late" relative to what? A release date set by a manager and approved by a developer muttering to himself "I'll do what I can". So what's the real use for a planning?

A manager answer included: "setting a challenge to motivate the developers". This is the "aggressive planning" theory. A really counter-productive one, since it leads to the "We're always late" syndrom, which is soon followed by the "We're poor developers" consequence.

I had my own variant on aggressive planning: "Watch what you do and register time passed". I thought that doing this will drive individuals to be more conscious of "unproductive" time and get rid of it. I was wrong. A developer can chase "unproductive" time only if he has decided to, not if he has to fill a time report precise to the hour (I have even read about minute-precise time report, where bathroom time is to be precised!). And then, as a mean, he can watch his time spent.

So I figured out there must be better reasons for doing plannings (instead of the "I develop to my best abilities, you pick the product when ready" approach).

One of the reasons is resources management. If time-to-market is a crucial issue to the Product owner, then he may wonder "how many people can I add to the project to get it faster?". Once you keep in mind the Mythical man-month essay by Fred Brooks (and this funny anecdot), you can still try to add people to reach the project optimal size.

One other reason, is some kind of control over what is developed. Plan your activity, do the job. If along the way, the plan is not respected, this may be interpreted as a warning. However, if the meaning of the warning is that your plan was not accurate, you have not gained much.

And maybe the most evident reason is the need to communicate dates to people outside of the project: customers, sales representatives, consultants, investors,...

Planning revisited

After our 6 months effort to implement the full agile practises stack (we already had continous integration, unit testing, iterations), I now understand why this works:
  • you deliver software in a time-box manner and focus on priorizing customer value, having both short-term control (the iteration) and mid-term control (the milestone)
  • you have a very simple measure for productivity: velocity. You globally measure the capacity of the team to deliver useful functionality. Meetings occur, bugs occur, obscure technical work occurs but it is not counted as such
  • estimations are more reliable because of the planning game. Indeed, estimating a task is better done by a bunch of people having different experience and knowledge about it (I used to do that on one-to-one with the "concerned" developer - which is not a relevant concept in eXtremeProgramming anymore)
  • estimations are also more reliable because of the frequency of the planning games (every 3 months)
By the way, I want to emphasize all the benefits of the planning game:
  • developers have the opportunity to understand precisely the customer objectives
  • the customer can get a better grip on development risks and difficulties
  • the team is really empowered and feels responsible for the overall project
Let the team manage itself

The last point is what stroke me in front of the cards array: many brains are better than one.
  • the team is much more efficient at organizing the project than the project manager
  • the team is much more efficient at defining and estimating the tasks
  • the only way to get the maximum productivity is to trust the team members and let them set high-productivity standards. No management indicator can ever imply high productivity. You cannot measure commitment, smartness, collaboration
The consequences for a project manager seem pretty clear to me: you are only here to help the team manage itself.

How to do better next time?

Thinking about that, I concluded 3 things:
  • I should have experimented more. Some agile practises seems evident. Continuous integration is one of them (spend machine time instead of developer time). Some other are not so intuitive: why use physical cards to track development tasks? It is not until you hold one in hand that you can feel why
  • Empower the team. This is the brain number effect. I also find some relations with Michel Crozier's theory regarding the fundamental liberty of any worker to gain power around him. This also means that team management can never be an easy path
  • I should live up to my convictions. For instance, I was not strong enough on emphazising why continuous integration should always be green, no matter what (this one I experimented)
Don't give up on your conviction

We all make mistakes, learn more or less painful lessons. However, when we learn something the hard way, we'd better not forget about it. What we learn become our convictions and the remaining questions have to be experimented.

I recently read a blog entry of an experienced developer analyzing the reasons behind his software projects failures. The whole entry is worth reading and wondering about. But one specific thing was worth remembering for me right now:

And if you decide to make changes, have the courage to go 100% with your gut. I've failed more than once when I watered down my convictions in order to appease dissenters. The only thing worse than evangelizing change and failing is looking back and realized you might have succeeded if you'd held firm on your convictions. What a waste!

I won't be caught twice on that one.