I'm sitting here trying to estimate the time I'll use on a
programming project I'm working on. I'm doing this because I was asked
to provide a schedule. Normally I'd just make sure I'm doing themost
important parts first so we could release whenever we were happy with
it.
But this time I'd like to give it a try and see if I can actually
manage to get somewhere. I find making estimates really hard. How
can I know how much work it will be before I've tried? And when I've
tried, I've already really done the work. I know an estimate isn't
supposed to be correct. It's an estimate, not a prediction.
But if I'm going to make it, it ought to be a rather good estimate, or
what's the point?
Now, how to achieve something even ballpark?
Gut feeling
One thing I am sure of: My gut feeling about how much time I'll
need is completely unreliable. My guesses are always vastly optimistic.
I think this may be because of how I learned to program - or more like,
how I taught myself to program. Since the first
computer
my
dad brought home when I was a kid I've had an interest in programming.
Though, for all of the time I've spent on hacking growing up I have
nothing really to show for it. I never completed any of my projects.
Not because they were all too hard or too big. It relates to my
definition of
done.
I was done with the project before the project was done. My reason for
doing anything in the first place was that I loved the challenge of it.
I wanted to see if I could figure out how to perspectively correct texture map a triangle, and I eagerly went
hacking at the core of the problem. So when I had
figured out I needed to interpolate 1/z and optimized this killer innerloop, the challenge was overcome, and my motivation went
elsewhere. If I was to really get the any project
done I'd have
to work on all this other boring stuff that just seemed irrelevant then
- and indeed was for a one-time proof-of-concept. My code worked at the
moment, and I had proven to myself that I could crack it.
- Cool! Now,
let's try this other thing...
So I have all this practice with going at the core of a problem,
and so my gut feeling about a task naturally gravitates towards this,
not taking into account all the other things that come along with it.
It takes me a bit of thought to include things like planning,
refactoring, unit testing and documenting into the estimates. And even
with years of solving problems I still can't tell how much time it will
take me to solve one - that's the nature of a problem. If I know, I've
solved it already.
Details
I've figured that the first thing I need to do is actually plan
all the tasks that makes up the project, and in incredible detail. I
have to do all the thinking that I normally do while coding in order to
come up with the actual fine-grained tasks, or I'll be far off. I can't
have a task in my project that says "Adding a file to the synced
folder". It needs to be broken up into "Uploading a file through the
web page", "Save the file to disk and add to the ChangeLog", "Notify
the SyncService of the change". Only at this level can I truly know
what needs to be done and guess how much time I'll need. This isn't far
from actually coding it, but then, coding is mostly thinking about how
to do it anyway, with the small addition of typing it in, getting it to
run, and test it.
Setting up these tasks are actually a good thing whether or not
I'm estimating them. Doing the thinking before I code helps me find
and eliminate more problems in my design early. But the thing I am not doing - coding it - is exactly the part that is missing for the estimate to be good: knowing what trouble I'll get into while
coding. Usually this trouble comes from me not thinking it through
carefully enough and I'm missing something that ends up giving me
trouble, or some functionality I'll be reusing doesn't work just the
way I think it does, and my approach is wrong. I can't know this
without coding.
One solution to this is of course to add some buffer time all over
the place. But that isn't really estimating, it's just being defensive.
Though, often, applying the "times-pi rule" is the best I can do, short
of trying things out to verify my assumptions. However, this might end
up with the same amount of work as just coding it for real. And there
are many assumptions I won't think of verifying - the things I think I
know, which turn out to be wrong anyway.
Well, I figure out all the small tasks that need to be done, and I
try and estimate how many hours I'll spend on each one, including
coding, refactoring, unit testing, debugging and documenting. Now all
these hours add up to a total for the project. But a bunch of hours
isn't what I need. I need a date. So I need to know the number of days
of work this amounts to.
A day's work
This got me thinking: How many hours of real work can I allocate
per day? My first thought was that it should be 7.5 hours. My working
hours are from 9 till 5, I get half an hour for lunch, so I'm getting
paid for 7.5 working hours. Though, when I think about it, I don't get
to spend them all on coding.
The first hour in the morning is code free. When I arrive here at
9, I say good morning to my colleagues, log in to my computer, check my
email on my three different accounts, and try and remember what problem
I was working on yesterday (or last week if today is a Monday). Then,
there is the quick daily status meeting at 9:30. It takes no more than
10-15 minutes to go through everyone's status, but then someone has a
little problem and we take the opportunity to discuss it, so half an
hour often will go by.
So now it's already 10 o'clock before I'm back at my keyboard. It
takes a few minutes to get going, but the following hour is normally
quite effective - up until lunch is due at 11:30. That's 1.5 hours
worth of productivity before lunch. Lunch is about half an hour, so
at noon (or perhaps a tad past) I'm back at the desk.
I actually had this misconception in my head that the day was
split in half by lunchtime with about the same amount of time before
and after. That's just wrong. It may be almost true for 8-to-4 workers,
but I'm starting at 9 and having lunch at 11:30, so there are only 2.5
hours in there to begin with. And with my brain boot-up time and the
status meeting, there's not that much left.
The day really starts after lunch. (which suits me well as this is
usually my breakfast anyway. It's a bad habit, but I just can't eat in
the morning.) The rest of the day is pretty effective. In the
remaining five hours between noon and 5 pm I'm getting some work done.
Of course, I need some small breaks in-between to rest my eyes, stretch
my legs and fetch a cup of hot beverage. And with a few questions from
my colleagues, checking more email, a bit of chatting on msn, being
stuck on a problem and googling for a solution, jotting boxes and
arrows on a piece of paper, having some trouble with the computer,
checking out some cool links someone sent me, and participating in
discussions around the office about remodeling bathrooms or the price
of gasoline, I might get as much as 4 hours of actual coding done if
I'm having a really good day. Probably a bit less on the average.
So, in total, of those 8 hours spent in the office, I get about 5
and a half hours of productive time if I'm really focused. If I say 5
hours on average, that might not be too far off.
So...
Now I'm starting to get an estimate that I think is approaching
the ballpark - given that my requirements do not change, that all my
assumptions hold, and that I'm able to focus and don't get any more
interruptions than I've calculated for. I'd say that's a pretty thin
thread to hang by. In fact, I would bet none of these will hold, and
then what is the value of my estimate? It might be somewhat useful
to know where the ballpark is, but I've spent a lot of time on it to
get this far and I'll need to spend even more to keep it updated. The
cost/value for this time I'd say is pretty bad.
Bottom line: Estimates, to me, aren't the way to do things. Rather, I'll take a wild guess for what I can get into an
increment,
get started on the most important things first and go from there.
Things change anyway, so it's better to do what I need right now rather
than going into incredible detail about what I think I'll be doing next
month.