Friday, November 23, 2007

Reflections on Quality

In October my team released a new version of our system, which represents several months of extremely hard work and is the culmination of everything we've learned so far. (It's also the reason I haven't posted for a long time.) We were all very proud of what we'd created, and confident that it was going to solve all of our (and our users') problems.

But from only 2 weeks after going live, we started having a string of major problems - almost every day something horrible happened. It was almost unbelievable, and I'm sure one day we'll look back and laugh, but right now it's an absolute nightmare.

After yet another disastrous week, I spent a weekend thinking about "quality" in software development, and trying to figure out where we went wrong. As I have done before, I made a pilgrimage to Joel Spolsky's site to get some perspective. I read and re-read The Joel Test - a simple list of 12 yes/no questions that works like a scorecard for software development teams. Joel says, "A score of 12 is perfect, 11 is tolerable, but 10 or lower and you've got serious problems."

We scored 3.

It was depressing, sure, but I was already so depressed anyway, I was actually just happy that here at least was a list of things I could do to try and correct the situation. Also, it was nice to know what we are already doing well.

The first thing that jumped out at me was #5 - "Do you fix bugs before writing new code?" I think this is really a fundamental part of where we went wrong. If you have bugs, that means you're not perfect (nobody is!), which means any new code you write will have bugs, too. So by not stopping dead and fixing the bugs you already have, the number of bugs can only increase. Obvious when you think about it like that, but easy to forget when there is a lot of pressure to implement new features. I can only imagine what it must feel like to know that there are no bugs (that your best efforts could find) in the production code. I'm sure it's a lot better than knowing that there are!

So the first action item: Stop all new development. Fix all the bugs we know of, then go & find some more and fix those too.

The next big one was #7 - "Do you have a spec?" To tell the truth, we have almost zero documentation. As Joel says, "Writing specs is like flossing: everybody agrees that it's a good thing, but nobody does it." I would expand that to cover all documentation. So far our team has been operating under a sort of modified XP credo, where anything that even faintly smells of an old-school waterfall methodology was implicitly rejected. But the reason #7 stood out to me was that in a couple of incidents, the users were asking us what the system does in this case, and we didn't know. The users didn't know, and neither did we. That's bad. If we had a spec, they wouldn't even have had to ask, and anyway there wouldn't have been a problem, because the system would have done what they wanted (instead of what it was doing!)

The worst thing I found when examining our methods was that we had all but abandoned our sacred Law One anyway. So it wasn't that our philosophy was wrong, it was that we had forgotten it, to our peril. But how do you know when you have enough testing? Code coverage tools are fantastic, if a little fiddly to set up, but you really need a human brain to imagine scenarios in which the code you're looking at might fail.

So the second action item: Build documentation and test coverage reviews into the process that puts code into production.

Speaking of reviews, our code review process was extremely weak. Basically it consisted of just me having a look at the code changes as I packaged them for release. But even then, with so much (perceived) pressure on time, I must admit there are huge swaths of code which has never been seen by anyone other than the developer who wrote it. Uncool.

So the third action item: Build a 2-level code review into the process that puts code into production.

The combination of documentation review, test review, and code review I've called the "critical review", meaning both that the reviewer should try to be as critical as possible, and that it's of critical importance. It's difficult to be critical of the work done by your friend, especially if they are relatively senior to you, but the important thing to remember is that every problem you find is saving them from the crippling shame and panic that grips you when code you wrote has caused a production problem. So I've told everyone to try as hard as they can to find a problem when it's their turn to review.

The final test that made me shudder was #6 - "Do you have an up-to-date schedule?" I've always hated giving estimates to the users. It's never much more than a wild guess, and yet they really hold you to it. You can't get away with saying, "it'll be done when it's done!" either.

I read Joel's article about Evidence-Based Scheduling (EBS), which quite frankly struck me as a shameless plug for his bug-tracking product, FogBugz, since it's virtually impossible to implement with anything else. I like his previous idea much better, mostly because of its simplicity, but also because it lends itself easily to constructing a burn-down chart to catch potential delays early.

Basically, the big message for me was we have to generate a new estimate every day. The moment before we start working on something is the moment we know the least about the work involved. Every day we work on it we know a little bit more, so it makes sense to re-invest that knowledge into the quality of the estimate - and if this is done for every in-progress task, the reliability of the whole schedule increases every day too. By giving the users a new schedule every day/week, they don't get any big shocks from huge and sudden delays, and every little slip can be explained in detail.

A key requirement for this is that the estimates are provided by the developer who will do the work. Again this is because nobody knows the work better, but it also prevents unrealistic schedules from being handed down from above.

Another important rule is that estimates and work logged must include all the time doing non-coding stuff - code reviews, talking to people, helping other developers, setting up environments, testing, documentation, picking your nose - everything. In essence the estimate and work logged for a task must be the total time spent in the office not working on a different task. That way everything adds up to a number of calendar days, which in the end is the only thing that matters to the schedule.

So the fourth action item: Estimate everything, and update the estimates every day.

The actual implementation of all this is in our issue tracking system (JIRA). I've added a few custom fields and worked out a process flow for each issue/task, so it gets estimated and re-estimated, reviewed, and scheduled. I'm sure that if we can stick to it, our quality problems will disappear - the trick is now to make sure the extra burden it places on us is more than repaid by a reduction in production panic.

At least it will get us a score of 6...

 

Gmail & Mail.app - the right way

I was getting a bit sick of firing up Parallels just to do email and GTD in Outlook, so today I thought I'd give Apple Mail another look.

I had already set up Gmail IMAP in Mail, but it was more than a little clunky, and I was a bit worried about what happened when I pressed "Delete".

I Googled around a bit and found these tips, which as far as I can tell iron out all the problems. To save you following the link, here's what you do:

  1. Set up Gmail IMAP according to Google's instructions
  2. Open Mail Preferences
  3. In General, set Dock unread count to Inbox Only
  4. In Accounts, select your Gmail account and set IMAP Path Prefix to "[Gmail]"
  5. In Composing, set Create Notes & To Do's in to On My Mac (notes & to do's really don't work with IMAP - don't even try)
  6. Close Mail Preferences
  7. From the menu bar turn on View > Organize by Thread if you haven't already
  8. Select the All Mail mailbox, then from the menu bar select Mailbox > Use This Mailbox For > Trash (this makes the Delete button in the toolbar work like Archive in Gmail)
  9. Repeat for the Spam mailbox - use it for Junk
  10. Repeat for the Drafts mailbox - use it for Drafts
  11. Repeat for the Sent mailbox - use it for Sent

That's it! Now Mail will essentially work just like the Gmail web UI, with one disappointing exception: when new messages arrive for existing conversations, Mail doesn't show the previous messages of the conversation in the Inbox, so you have to scroll through the reverse-order quoted text like a moron. I wonder if there's a way to use the Rules option to do this automatically... dunno.

Saturday, February 03, 2007

What You Don't Measure, You Can't Control

After this discussion on the GTD newsgroup, I picked up a copy of Mark Forster's latest book, Do It Tomorrow. I'm trying to see if there are any good ideas that may help me improve the effectiveness of my GTD system, and also just to find out what other systems are out there.

I'm only up to about Chapter 3 so far, so I won't go into a big compare/contrast analysis of his method, but one thing that I picked up straight away is his suggestion to try to quantify the amount of "randomness" in my day.

His idea goes something like this: each day is filled up with 2 types of activities - those that were planned, and those that were not. He calls the latter "randomness" - ie. things that randomly crop up and take up time, including things you might randomly just decide to do on the spot, like watch TV or chat with a colleague (or post a blog).

He recommends you make a plan for the day, his "Closed List", of what you are going to get done. The closed list has a line at the bottom of it, and you write down everything else you do during the day under that line. By doing this properly (which means honestly), you can numerically quantify what percentage of your day was filled with "randomness".

Putting the benefits or drawbacks of the "Closed List" concept aside for now, I definitely like the idea of a metric to find out unambiguously how much of my day is ruled by me and how much by my environment. GTD has an operational problem in that it's very easy to spend too much time Collecting, Processing, Organising and Reviewing and almost no time Doing any of the Next Actions on your lists. There's no framework or guidelines to maximise the Doing time.

I've always believed that you can't control what you don't measure. That's why the most successful thing I've ever done to lose weight is to religiously weigh myself every morning. Even when I'm not really trying to watch what I eat, just getting on the scales every day keeps the weight down - I assume it's due to some kind of sub-conscious mechanism that has control of my hunger impulse.

So I'm curious whether the same could work for GTD. David Allen recommends strongly against daily to-do lists, so presumably he doesn't agree with Mark Forster's "Closed List". I'm undecided - so long as the "Closed List" was made up of Next Actions from my GTD system, it seems like a reasonable approach. But, again, putting that aside for now, at the very least it should be possible to quantify each day how many Next Actions from my GTD system I do, and how many "random" other things I do. And just like weighing myself every morning, I reckon just seeing that number every day might just help keep my focus on the Next Action lists.

So this week I'm going to try an experiment: I will write down absolutely everything I do that isn't a Next Action from my GTD system, and at the end of each day tally up the Next Actions vs the Randoms. (For completeness, I will also track the hours I spend working on my GTD system as Randoms.)

I'll post the results of my experiment next week.

 

Saturday, January 20, 2007

Are Your Actions "Next" Enough?

If you're not getting things done, it's not GTD.

Early on, I often found myself looking at an action on my actions list, and thinking, "nah - I'm not going to do that now." It didn't take long for the alarm bells to start ringing.

I started asking myself why I wouldn't do that action now. In most cases, I found that the action wasn't "next" enough. That means I hadn't done the "processing" job properly because I hadn't whittled the job down to the very next physical action.

So now if I find an insufficiently processed action on the list that makes me want to avoid it, I just figure out right then and there what the real next action is, and usually I do feel like doing it straight away. I move the original, not-very-next-action to my projects list, and put the actually-next-action on my actions list, do the action immediately, and cross it off my list. Feels great.

Saturday, January 13, 2007

GTD Evangelism

A few months ago I was in bad shape. I had recently taken on a lot more responsibility at work, and found that the main thing I enjoy about work, Java architecture & coding, I didn't have any time left to do. More than that, I couldn't seem to find time to do the other stuff either. And on the rare occasions I found myself with a chunk of spare time to get some work done, I floundered, not knowing which of the hundreds of things I should tackle. This got me really, really stressed out.

Curiously, around the same time I was doing a lot of posting on the Java Posse newsgroup. Evidently I had no time to do any work, but I managed to make time for answering questions on a Java forum! Dick Wall, the guy who runs the Java Posse podcast, is also a fairly senior dude in his company. This made me wonder, how the hell does he find time to put so much work into the podcast, as well as do his job, and have a home life?!

I put this question to him, and his response included a reference to David Allen's GTD (Getting Things Done) system. I had a look at the website and although I was very sceptical I was also desperate, so I bought the book from Amazon, which arrived a couple of days later.

I started reading, and, as expected, it's very American-rah-rah which I suppose is to be expected. But, as I said I was desperate, so I kept going and pretty soon got very excited. It was clear from the first couple of chapters that this was going to be the answer to my problems - or at least, it had the best chance to be.

I read the whole thing in about a day and a half, then headed off to OfficeWorks. The book recommends a lot of specific stuff you should get, like an electronic label maker. I didn't see how that could be important (I do now), but I didn't want there to be any reason the system wouldn't work for me, so I just took everything literally.

My out-of-work life was a mess, to be sure, but it was my work situation that was causing me 95% of the stress, so that's where I went to work implementing the system.

The results were incredible. Within a week, I was feeling a LOT better. After 2 weeks, I had completely organised absolutely everything at work into the system, plus everything I could think of that I wanted to do with my team in the future. It was an awesome feeling - racking my brain, I could not for the life of me think of anything I hadn't covered. What I had in front of me was a beautifully organised filing system, lists of current and future projects, lists of things I needed other people to do, and best of all, a complete list of immediately doable things that would all contribute to the progress of my work. Now I would know exactly what to do when I had a chunk of time at my desk.

The effect on my stress was like magic. Since starting GTD I've been sleeping better, I feel generally positive and more energetic. Even more amazing is the effect it had on my team. The improvement is palpable.

I've been using GTD for 3 months now, and I've made many improvements to my system in that time. No doubt I will make more as I get better at it. I might use this blog to document those improvements as I go, to help people to whom I've been evangelising GTD. (I bought 4 copies of the book to hand out as Xmas presents!) I've also been watching and asking questions on the GTD forums on David Allen's website, mostly for clarification of various concepts presented in the book.

There are various software tools and add-ons out there for implementing GTD, and I looked into them, but the beauty of the system is that it is incredibly simple, and built of things that all of us already do (albeit incorrectly) to organise ourselves. So I've found the built-in features of my email applications (Outlook and Gmail) to be sufficient, although I have invested a lot of energy in getting those settings just right. I also have gone extremely low-tech for the non-digital parts of the system - for example, I now take a simple memo pad and pen to meetings.

I really think this has changed my life, and saved my career. It was clear to me already that I wasn't even coping with my current level of responsibilities, so there was no way I could take on more. And there are lots of non-work things in my life that haven't been progressing, which I feel now I can finally get moving on.

Gushing enough?

 

6 Tips for Java Threads

A while back I replied to a message on the Java Posse newsgroup entitled "Threads are EVIL". The poster was having trouble with Java threads, so in addition to recommending Java Thread Programming and Java Concurrency in Practice, I summarised the basics in the following tips.

#1 - Know what each of your threads does, and which threads can be inside which methods
...You can use asserts to check the names of executing threads in sensitive methods.

#2 - Know which variables are accessed by multiple threads, and which lock guards them
...Brian Goetz recommends annotating/commenting your variables to describe how they are guarded. But the best way to simplify this job is to avoid variables - use immutable classes wherever you can. (They're automatically threadsafe, very fast, and easy to code.)

#3 - Remember it's not enough to synchronize the writes to a shared variable
...You also have to synchronize the reads with the same lock.

#4 - Don't be afraid of the synchronized keyword
...It is NOT evil. Do be afraid however of large stacks of code inside a synchronized block/method. If you find one, take out the bits that don't need to be synchronized and/or split it up into smaller synchronized blocks.

#5 - Avoid nesting locks (ie. synchronized within synchronized)
...Try to think of another way to do it. (There are ways to get away with it, but you're asking for trouble later down the road.)

#6 - Keep it SIMPLE
...Don't do with 2 threads what you can do with 1. (Unless you get a measurable performance improvement by parallel processing CPU-intensive or IO-blocking code.)