Skip to main content

The Ego Roller Coaster

In my varied life experiences, I have never encountered a vocation or activity that could build up one's confidence before snatching it away in such quick succession as in software development. There is magic in bending a computer to your will and having it execute your commands faithfully. However, as with all good tales of magic, there are many pitfalls, which can rapidly deflate your ego.

Little Oversights Can Bite

I once wrote database upgrade code that repaired some broken references in a database. This fixed several known defects. I was really proud of myself because the code came together quickly, it looked good and it worked well. It passed all tests and review, it was merged with the product and all was well. That is, until someone discovered that some databases were triggering crashes on upgrade. Fortunately, it took little time to find the source of the problem, but all of my pride vaporized, as I had to explain to my manager that I forgot to account for the possibility of null entries within the database.

Obvious is a Matter of Perspective

I was working on a side project developing an iOS prototype app for some clients. After many meetings hashing out the requirements and several months of development, I was ready to demonstrate my work for the first time. The clients were really excited to see their ideas presented back to them in a more concrete form. There were many technical challenges for me, as I had to implement several features I had never implemented before, but I thought I had done a good job, all things considered.

Of course, one of the first things the client did after starting to play with the app was press the Back Button. I stared, horrified in that moment, realizing that in all of my testing, I had never thought to press that Back Button myself. Of course, everything after that point was completely broken. I reset the app, and we tried again, but even after informing the client that the Back Button would break the app and needed to be fixed, she kept pressing it because it was just a very natural thing to do. This served as a wonderfully repetitive reminder of how incompetent I was.

Don't Leave Anything Out

Toward the beginning of my career, I worked on an issue that had been plaguing the product for a while and very much needed to be fixed before the next release. I spent several 12-hour days trying to find a workable solution, with each iteration becoming more complex than the last, as every path I went down failed for one reason or another. Finally, I stumbled upon something that worked. I coded it up and tested it during a couple more long days and late nights, and all looked good. After merging the code, the bug in the product disappeared, so the release went out.

I felt great. My manager had demonstrated a lot of trust in me to have relied upon me to fix the issue. He had restrained from reassigning the problem to our lead developer even when I was struggling, and I had solved the problem for him, reinforcing his trust in me.

Perhaps a month or so later, during a team meeting, we started discussing a peculiar bug that had cropped up. The behavior didn't make any sense in the context of the fix I had implemented before, so I was tasked with investigating further. After doing some significant research, I realized that I had missed checking in a particular file when I "fixed" the bug. This file was the one that invoked the logic that I had written to fix this issue, which meant my code had never actually executed inside the product.

This raised a lot of questions in my mind. How did the test I had written work if the code was never executed. Well, on my machine, of course, it worked just fine, as I had the missing file in my local repository. However, I had submitted the test; how did it pass on other machines? After closer examination, I realized my test was inadequate. It passed even in the presence of the bug. This was an important lesson for me. I learned it's always a good idea when possible to execute regression tests both in the context of the buggy code, to verify the test actually triggers the bad behavior, and in the context of the fixed code, to verify the issue is really fixed.

After discovering my test was flawed, one important question remained, why did the bug disappear in the product after I merged my fix? It turned out that someone else had simultaneously made some changes that happened to resolve the issue. Unfortunately, these other changes left open the possibility of future problems, which is how we ended up discovering that my fix was never really implemented.

I am sure you can imagine how embarrassed and ashamed I was that a key bug fix that I had worked so hard on had never really even made it into the product. The good news is that it gave me an opportunity to come up with a really clever fix for the subsequent problem that did actually get into the product and worked quite well.

From Hilltop to Facedown

Such is the ego roller coaster of software development. You're the king on top of the hill one moment, and the next you're lying face-down on the floor in a pool of your own vomit. Despite the bumpy ride though, it's always a great thrill and an adventure.

Comments

Popular posts from this blog

Books That Have Influenced Me and Why

A mantra that I often repeat to myself is, "Don't abandon the behaviors and habits that made you successful." I believe this trap is actually much easier to fall into than most people realize. You can sometimes observe it in the context of a professional sporting event such as American football. One team might dominate the game, playing exceptionally well for the first three quarters. Then, as they sit with a comfortable lead, you see a shift in their strategy. They start to play more conservatively, running the ball more often than they had. Their defense shifts to a "prevent" formation, designed to emphasize stopping any big plays by the other team while putting less pressure on the short game. The leading team often looks awkward in this mode. They have switched their perspective from that of pursuing victory to that of avoiding defeat. They have stopped executing in the way that gained them the lead in the first place. I have seen more than one game ult

Code Maintenance Requires More Than Testing

Writing and running automated tests can go a long way to help maintain the quality and reliability of a code base. Tests help ensure the code you've written executes the way you expect it to. However, even though automated tests are a great tool for helping to ensure quality over the years in which people will contribute to the code, they are not sufficient in and of themselves. It may be inevitable that all software products will reach a point of obsolescence no matter how much work is done to keep them current. The inherent problem is that if we view tests as constraints upon what the software system under test can be, then as we add more and more tests over the years, we will have more and more constraints on the shape our software is allowed to take. It then seems we must reach an inevitable point where we can no longer change our software system without violating a constraint, i.e. causing a test to fail. In more practical terms, we'll more likely first reach a situat

Notions of Debugging

Bugs can be really evasive and produce some surprising, even "impossible" behaviors. Part of a software developer's job is to relentlessly hunt them down and destroy them. However, often at least half the battle is finding them to begin with. The best debuggers I have seen rely a lot on experience, both experience with the application and experience with debugging in general. The former is situation-specific, and there many not be any good ways to advance in that regard other than practice. However, we can extract some information pertaining to good debugging practices in general. Dig for Clues Using All Available Resources The first step in debugging an issue is ideally to reproduce the problem. This isn't always possible, but if you want any significant level of confidence that you have fixed a bug, you need to observe the broken behavior and understand how to trigger it from a user's perspective. Sometimes we're lucky, and a tester has taken the time to