My Love for Debugging

01 Jul 2016

As programmers, we typically set out with the intent of creating a seamless program that always runs perfectly, or in other words, is bug-free. Yet bugs always seem to rear their ugly heads, even in what seems like the simplest of situations. But do not despair! Fixing bugs is where I have learned the most and often I only truly understand the flow of the program I’m working on during this process.

Nobody Writes Perfect Code

Earlier this week, I worked with my manager on a change to our existing database model. He had already started on it previously so had a skeleton in place, but it needed to be finished. We followed the existing structure and made whatever changes were needed to create our new table and integrate it properly with the existing application. We wrote tests, but when we ran them, they failed. This was a good thing - now we knew we were trying to do something meaningful and had written tests that were reasonably robust. We stepped through the code, included some print statements, and eventually figured out one bug. So we ran the tests again. Failed, again. We repeated the above process, fixed another bug, and continued, until eventually we managed to pass all the tests. Then we tested on the server using Postman, and no surprises, failed there initially too. Again, we repeated our debugging process and eventually figured out the issue, and finally we had a working piece of software. The lesson here is that even someone as immensely experienced as my manager makes plenty of mistakes while coding. We probably spent 20% of the time writing the initial solution, and 80% debugging. Debugging is a key skill and integral part of being a software engineer.

The Debugger is your Friend

Last week, I faced a particularly baffling bug. I was developing for iOS in Swift and had just finished up creating a view component and laying it out the way I wanted, but the code was a little messy and unreadable, so the responsible engineer that I am, I started refactoring. The first time round, I just pulled all the different components I was creating inside one function and split them into multiple functions. After cleaning that up and fixing any compile errors, I reran the app and suddenly most of my components were appearing twice.

First lesson: Refactor and test piece by piece, instead of trying to refactor everything at once. My refactoring process seemed to have introduced a very strange bug that at first glance I did not understand at all. I then checked out my changes (Hoorah for Git!) to return to a presumably working state and repeated the process step by step until I could reproduce the bug, and that happened immediately after I had made one of my previously local variables global. That stumped me. How on earth could turning a local variable for the y position of the next component global cause everything to render an extra time? I turned to my mentor and after explaining the situation to him, he suggested that perhaps everything had always been rendering twice, except before, the second render was just on top of the first. Genius. As I thought about it, that explanation made a lot of sense.

Second Lesson: The debugger is a great tool! To confirm, I used the debugger and set a breakpoint in the layoutSubviews function, ran the program, and as expected, the breakpoint was triggered twice. This happened because of a fundamental misunderstanding of the layoutSubviews function. Instead of creating my components there, I really should have created them in the view initializer (specifically required init?), and then moved them around as needed in layoutSubviews. Clearly, this process was long and could have been avoided with some more up front research about the functionality of built in iOS functions and how they interact with the rest of the application (but I’m warning you - Apple Developer docs are not the easiest to understand). However, I’m glad I struggled through it - that process taught me far more than just building the view and getting it right the first time would have.

Key Takeaways

So next time you find a bug in your program, don’t despair! Take a calm and structured approach to understanding the program and what created the bug, and remember, it is a great learning experience! The more you practice, the better you will get - after all it is an art.