DEV Community

Justin E. Samuels
Justin E. Samuels

Posted on

Dude, get a debugger!

IT JUST DOESN'T F***ING WORK !

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?

MY CONSOLE.LOG()/PRINT() STATEMENTS NOT HELPING !

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?

Programming Goddess Grace Hopper

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:


You can find these in the right corner, above the call stack in order below.
  • 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.tile it 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

  1. Add A break point once the response completes
  2. Investigate the response
  3. Investigate how the specific data we want is structured
  4. Update your code based on your findings
Voila! If your code is structured correctly, along with the correct results from your findings, then you should now have the geo-cords and street names on each button appropriately. If you want to try this, you can swap out the endpoint to THIS

Other Investigate Tools

Other debuggers


Thank You!

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.

Top comments (4)

Collapse
 
srishanbhattarai profile image
Srishan Bhattarai

From "The practice of programming" by Brian W. Kernighan, co-creator of the C programming language:

"As personal choice, we tend not to use debuggers beyond getting a stack trace or the value of a variable or two. One reason is that it is easy to get lost in details of complicated data structures and control flow; we find stepping through a program less productive than thinking harder and adding output statements and self-checking code at critical places. Clicking over statements takes longer than scanning the output of judiciously-placed displays. It takes less time to decide where to put print statements than to single-step to the critical section of code, even assuming we know where that is. More important, debugging statements stay with the program; debugging sessions are transient."

This is the problem with tech articles/blog posts these days in general. There are no silver bullets to any situation and some solutions will be better than others, but one must not be so crass as to completely ridicule a potentially viable solution that has proven to work.

I've encountered situations where a classical debugger doesn't help me and I have to work with something like dtrace. Other times, a debugger is perfect. Other times, a few log statements get the job done.

Collapse
 
nicolus profile image
Nicolus

There's a huge difference between "I don't have a debugger", and "we tend not to use debuggers beyond getting a stack trace or the value of a variable or two" which implies that they do use a debugger on a regular basis to get stack traces and variables, and that they occasionally use it for more in-depth debugging (hence the use of "tend").

Not every problem suddenly becomes a nail because you have a hammer, but you definitely need to have a hammer in your toolbox.

Collapse
 
srishanbhattarai profile image
Srishan Bhattarai

Sure. None of what I said contradicts what you're saying right now. I never said that a debugger isn't needed or isn't valuable. I even went out of my way to say that a debugger is perfect for many situations. Other times, log statements work. To discount their value by painting a picture that debuggers are always the solution is a bit misleading IMO.

Collapse
 
itr13 profile image
Mikael Klages • Edited

Everyone should learn how to use the debugger, though I must admit I often tend to be lazy and use print statements instead.

Sometimes I sneak in a global variable to limit the amount of times it prints something, and I haven't forgotten to remove such a variable yet, so I'm in the clear for now.

Though on the other hand, I sometimes end up using the print statements to figure out where I should put a breakpoint to debug faster, so I guess debugging wins in the end.