It's tough to pick just one.
One of my favorites comes from a developer who had a bit of a superiority complex. They were the lead developer on a system and they liked to fly solo. One day, they made a lot of fuss about a bug that had cropped up that stopped the system running. It would just hang and crash every time.
My initial reaction was the typical one. It was working before you made changes, so revert the local changes and try again. They didn't want to "lose all that work" (how much work could it be... haven't you been committing changes every couple of hours?)
A few days later, they were still investigating the bug. We offered to pair up on the issue. The problem with this was that they were far smarter than us, so they didn't want us slowing them down.
After a couple of weeks of them "still working on this bug... it must be a problem with .NET..." there was a sudden shuffle of the work. My boss came and told me (developer) had been re-assigned to an urgent issue and I needed to take a handover and fix this bug.
So, I asked (developer) to bring me up to speed on the bug so I could take a look. They didn't have time to take me through it (they were working on something far more important than... the whole system being broken and unreleasable?!!)
All they could supply was a 70 GB IntelliTrace file they generated from the broken application.
What?!
So I looked at their changes. It won't surprise anyone to find out the changes were extensive. Thousands of lines of code. Any one of them could have caused the issue.
Now, working in small steps means you don't often debug your code. But in this case, I dusted off my debugging paws and fired up the system in "break on error" mode. It didn't take long to explode, so I walked the call stack to see where things were falling apart.
Then I set a breakpoint and stepped through until I found the problematic code.
private string _field;
public string Field {
get { return Field; }
set { _field = value; }
}
It took less than an hour to find and fix the issue (Field/_field). But history is all about lessons.
- Work in small batches. A couple of hours can mean a lot of changes. Make it smaller. Commit to the mainline. Use progressive delivery techniques to hide work in progress rather than long-lived branches or massive local changes.
- Build, test, commit frequently. If the build and test part fails, it's often as easy to revert the changes as it is to debug.
- Pair/ensemble on problems when you need to as that's how we all learn.