Does the above describe sounds like you at 9pm after a few beers have hit your system; after spending hours on end to no avail with a problem that has you questioning your very existence in the developer universe?
Do you spend hours on end putting random logging statements in your code with messages like "here", "it works", or just gibberish "hfdhfdhfd"?
Dude, get a debugger!
If the above sounds like yourself, and you're ready to tackle these mundane issues in a more methodical manner to end your torture, then its time to learn how to use A debugger. I say A debugger, because THERE IS more than one debugger. As a Data Visualization Engineer, I focus more on the web technologies so my debugger lineup falls around the ones included within the popular web browsers (I.e. Chrome Debugger, FireFox Debugger, etc.), but other languages such as Python have their own debugger for their language, and even IDEs and Text-Editors such as Visual Studio and Visual Studio Code have their own embedded or available for install.
Why a fancy debugger?
A debugger will allow you to quickly see a problem as it rises in the execution of your code, before waiting for final output of the broken state that's frustrating you. Think of a debugger as a tool that when it runs into a issue, it will pause the program from continuing, show you the location of said problem along with other data available at that time in the program. For example, if you have a variable named "result" that needs to be used elsewhere, but never gets declared; the error raised (undefined) will be displayed in the debugger along with the current value of the "result" which you can quickly see is undefined. If that didn't make sense, no worries, we will have a more in-depth example below which will explain more.
History Lesson: Who the hell called it a debugger?
I'm a firm believer in understanding the past, to grasp on where you're trying to go. I'm not going to bore you to death on the history, but it's some key elements of the story of where the words "bug" and "debugger" you should know (it's programming folklore after all). In the olden days of vacuum tube computing you had machines taking up the size of rooms. As you can imagine, machines of this size could have some little intruders of things other than electronic parts attempt to make their way inside the inner-workings. So legend says that on September 9, 1945 a Harvard Tech noticed something unusual in one of these gigantic machines. Upon removal of the panel, a moth was found and promptly removed. Programming goddess and legend Grace Hoper then recorded in the notes "First actual case of bug being found", coining the first use of the word bug in computers. The subsequent word to follow, de-bug boils down to remove-bug, thus the use of the debugger is to remove bugs from your program. *WOOO* Now hopefully I didn't bore you too much with that history lesson, but now you have a piece of programming folklore to share at your next meetup with other nerds like ourselves.
Great, now lets do the damn thing!
So for ease of access to everyone, I'm going to use the debugger available within the Google Chrome browser. Head on over to This Link and download the training material to follow along. Be sure to NPM install everything before jumping into the next section
So what's the game plan?
The first step to understand where we're going is to understand the problem at hand. We're going to be using this dummy API from HERE that will allow us to do fake mocked API calls. At this time, go ahead and start the downloaded code (
npm run start) from above. Notice on the page there's a button to get some data from our API defined above, along with a spot for the title that's returned from our API call. Go ahead and click on the button, and click it two more times as well. NOTHING HAPPENS, so we have a issue with the expectations and reality of our code. Using the Chrome browser, hit F12,select "sources", use the keyboard shortcut of "CTRL + p" and search for our App.js file. After recognizing our file from earlier now in the browser, you can start to add target lines in here known as "breakpoints" to get a better view of the issue at hand. A better explanation of a "break-point" is a chosen point within the code for the execution to "break" on, hence "break-point". Add the break point on the line involving the return of the data from the API (line 12), and click the button again. What just happened? You should notice the line you put your break-point on is highlighted, indicating the break-point selected earlier was "hit". Now within this mode you can do a few things, and will notice a few things with lots of data within them.
On the right is the call stack of the application. As a stack (LIFO), the call stack holds the calls (execution) that were made up to the state of the current breakpoint. Translation: the call-stack is a map of the code your program ran up to the point it hit your break-point. Thus, using the call stack you're able to retrace the steps made by your program to investigate if the error could be prior than expected. Clicking on the files listed in the call stack will jump you into them for a closer investigation. You will also notice on the right the breakpoints you have setup, and the ability to toggle them on and off, as well as other attributes such as the watchers and global breakpoints (to name a few) which I can cover in a more advanced tutorial (just ask). For now, just be concerned with the call stack and breakpoints section.
Back to the breakpoint we hit earlier; hover over the "response" variable, notice what jumps out, it's the raw data being returned from the API. Seeing that the data is being returned with a valid 200 status code, we now have to use our debugger "step controls" to move closely to the error in order to prevent the error from happening again and us losing our place in the debug state.
Debugger step controls:
- Continue - Run the program until error/next breakpoint/completion
- Step Over - You want to skip OVER the upcoming statement to be executed
- Step In - You want to go INTO the statement about to be executed
- Step Out - You screwed up by stepping into some s**t, and now wana go back up the stack
- Step - You want to go to the upcoming call in the stack
Now Step Over line 12, and investigate the data object being written to the State object, data property (line 13). Notice how if you hover over
json.tileit comes back as
undefined, but hover over the json variable on line 12. Notice that when hovering over it, you see no property labeled as "tile", but "title" instead. We have a typo of "title" being represented in our state object as "tile".
So, hop back over to your code, and correct the typo, and run the code. IT WORKED! You've successfully debugged a program. That's all there is to it. Just remember to think of it in terms of physical stepping. Do you want to continue walking - Step, do you want to investigate what this evaluates more - step into, walked too far into what you're currently in - Step out, do you want to move over what's coming up - Step Over, and do you want to just run the whole way until another breakpoint, error, or full execution - Continue. But the debugger is good for more than fixing issues, you can also figure out how to improve/add features by using the debugger
Let's get creative.
Say we need to add their street name, and geo-coordinates to the row, but are unsure on if the data even exists on our current route, and how the data is structured in the response. We can repeat our same debugging process from earlier by
- Add A break point once the response completes
- Investigate the response
- Investigate how the specific data we want is structured
- Update your code based on your findings
Other Investigate Tools
- All of the major broswers have a debugger included in their respective developer tools
- Visual Studio - Included debugger in their IDE
- VS-Code - Available via a plugin
Thank you so much for reading my first, but not my last tutorial. I hope to create more in the future ranging from beginners to more advanced, and am always open to constructive feedback, suggestions, and to answer any questions you may have.