What advice can I provide to help you debug your code?
In this episode, I give you seven tips to help you debug your code. One of the students brought in a programming assignment to the live class last week. This assignment was from another class and I explained some of these tips and we used them to solve the problem.
Here are the tips that I recommend to help you fix software bugs:
- Make sure you know exactly what is expected and what’s not working. Just being very clear about what should happen and what’s actually happening will be a huge help. Sometimes, the problem is just a misunderstanding.
- Try to isolate parts of the code. If you can replace methods with versions that just return known good data, then you can start narrowing down your search.
- Try to simplify your data. Just like the previous tip, this will help you to narrow down your search.
- Focus on the edge cases and try to purposefully cause some bugs. Fix the bugs and you just might fix the original problem. Sometimes a bug is similar to an edge case. What do I mean by this? Modify your data so maybe there is no data at all. If you have a range of values, try the lowest and the highest. And try values outside of the range. Even try creating malformed data.
- Keep track of all the scenarios you identified when working with the edge cases because these make excellent unit test cases. Make use of unit test cases and run them after making a set of changes as soon as your program is back in a running condition. This will help raise your confidence in your changes.
- Learn to use your debugger. This is a great tool to use even when you’re not looking for a bug. It can help you become familiar with code that somebody else wrote.
- Create a log file and add trace statements. Record information as you enter and leave methods, as you test conditions and branch into various if and else statements. And record your loops and data variables you’re working with. Remember that many times, the clue to helping you fix a bug won’t be what’s written to the log file but could also be what wasn’t written to the log file.
Listen to the full episode or you can also read the full transcript below.
Thank you for your review and comments. The thing I liked about this review was the support from recommending the podcast to other students. If you know anybody who would like to learn how to program, then let them know about it. I put a lot of effort into producing each episode so that you can get the most benefit from an organized and information packed 10 to 15 minutes. Your friends will be sure to thank you for the recommendation.
Okay on to the question this week. And, well, it’s not really a question. In the live class last week one of the students was struggling with a programming assignment from another class and he asked for my help. I don’t believe in doing somebody’s homework for them but I do believe in helping people learn skills so they can breeze through assignments like this. This episode contains seven tips that I provided during the class. And maybe one or two more that I thought of while preparing this episode.
I don’t always know what you’re struggling to understand. If you’re having difficulty with something, then others are probably having the same trouble. Taking the time to ask a question is a great way to get an answer to your situation and help others too.
The first problem was a lack of clarity about what was expected. The assignment was not clear at all even to me and we made some good guesses for what was expected. When you’re faced with a situation like this, make sure to ask questions and don’t stop asking until you know what the problem is and what solution to provide.
In fact, when I’m interviewing an experienced programmer, I’ll often give a vague problem on purpose just to make sure that a candidate knows how to define a problem and the requirements.
#2 When looking for a bug, try to isolate parts of the code. Just like how I described in episode 38 with binary searches, dividing your problem in half will help you find it much quicker. How do you do this? Well if you have some code that calculates some information that’s used in another part of your code, then you really don’t know if the problem is due to how the information is calculated or in how it’s used later. So my advice is to temporarily change the code so you have some sample information that you know to be correct and can then rely on. Just substitute this into your code and see what happens.
By the way, this is an excellent tip for making your code more testable and ready for use in a full software project. By allowing components to be able to be swapped out and replaced with a mock component, you’ll have a design that’s ready for some serious testing.
#3 If your program is reading data, then try to simplify that data. This is similar to advice #2 but allows you to work with your data instead of the code. If you have a data file with 25 records or pieces of information, try creating a new data file that has just a single record. Work through the simple cases before you move on to more complicated cases.
#4 Don’t ignore the edge cases and make sure you have proper error handling in place to handle malformed data. How do you do this? Simple. Create some malformed data yourself. You might find that by doing this and solving the obvious bugs that come from this that your original bug was just another example of malformed data. Here’s where you definitely want to focus on the edge cases. Some ideas include, create a data file with no data at all, or remove the data file entirely. When we did this in the class, we were surprised to see that the program was still running just fine. It turned out that there was another data file that the program was reading instead. This allowed us to find that because we started looking for sources where the program could still be getting its data. Another idea is to change data types. So if your data is a number, make it a string. When you do these things, you should expect your program to crash or run badly. Fix the problem and try to break it in a different way.
Let’s take a short break here for this message from our sponsor. Yes, the sponsor is me. It’s quite appropriate actually since the live classes have been the source of many of the questions that I’ve been explaining in the Q&A Friday episodes. There really is a lot of extra value that you can get from joining a live class.
( Message from Sponsor )
Okay, we’re back for tip #5 Keep track of the things you did to break your program because these can form some really good unit test cases. When you start work on a project that you intend to work on for a while. In other words, something that you want to work on for more than a one night homework assignment. Then you’ll want to create automated unit tests that you can run anytime. I recommend that you run your tests after every change that brings your program back into a running state. This will give you confidence in your changes because if it can continue dealing with all your scenarios, then you know you haven’t broken anything. You’ve maintained the same level of functionality.
#6 Learn to use your debugger. This is a great tool to use even if you’re not trying to find a bug. Why? Because you can use it to step through your code one line at a time to see what it really does. You can set a breakpoint that will stop at a specific line of code whenever your program reaches that line. This allows you to set a breakpoint in some interesting location, run your program, and let your program stop whenever it hits your breakpoint. You get to learn when and under what conditions certain parts of the code is run.
And finally, #7 Add trace statements to gather extra information. Sometimes, stepping through with a debugger is not practical. Open a file on disk and write some information to the file. If you have a loop that reads and processes some information, then write a line to the new file each time you start going through your loop. And write the data that you’re working with to the file. Then once you reproduce the problem, open this file and see if the information is what you were expecting. This is called a log file and is critical to being able to solve problems in major software products.
You see, a lot of the bugs you’ll likely encounter in a major software product will be due to some unexpected data or some unexpected configuration that only a few customers will have. It likely will be something that the whole team never thought possible. Having a log file will tell you exactly what the program was doing when it encountered a problem.
It’s important to note that log files will tell you exactly what your program did. They won’t tell you what your program didn’t do. So if the bug was due to something that your program should have done but didn’t, then the log file won’t contain that information. That in itself could be exactly the clue you need to be able to fix a bug. Just be aware when examining log files that sometimes the clues will be what wasn’t logged.