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.
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.
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.
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.
Comments
Post a Comment