Debugging

Debugging Is the search for the cause of problems, ‘bugs’, in code and fixing them. The term comes from The origin of the term “debugging.”

Stack Trace

Is bunch of printed text that appears in your console/terminal when things go bad. As the name implies, it’s a Stack (data structure) that shows a trace of the steps executed in your program leading to the crash. It’s often enough to see where the error lies, as most stack traces inform us of the line where the code crashes as well as the Exception or Error that occurred. The very first line of the stack trace will generally provide the most useful information about the error your program encountered.

Debugging by ‘printing’

This is Noob behavior, BUT it’s also practical and real. By printing statements at certain junctures in our code we can be certain of how our code behaves and what it’s doing, enabling us to confirm if it runs as expected. In the REAL WORLD and Production environments this should be avoided and removed immediately after confirming suspicions if used! It will signal out rookies from experienced programmers.

A flaw of this debugging method is that when printing nil we simply get a blank line… so use p instead of puts to print when you use this debugging method as p yields more information and provides a string representation of whatever it’s called on.

Debugging with Pry-byebug

Pry is a Ruby gem that provides you with an interactive REPL while your program is running. The REPL provided by Pry is very similar to IRB but has added functionality. The recommended Ruby gem for debugging is Pry-byebug and it includes Pry as a dependency. Pry-byebug adds step-by-step debugging and stack navigation.

To use Pry-byebug:

  1. Install it in your terminal by running gem install pry-byebug.
  2. Make it available in your program by requiring it at the top of your file with require 'pry-byebug'.
  3. To use it, call binding.pry at any point in your program.
  4. Then run ruby your_program.rb and it’ll open a debugging session in your terminal that resembles IRB.
  5. Via pry you can check values of all variables up to the point where you placed binding.pry.
  6. Enter next to skip over to the next line…

For example:

require 'pry-byebug'
 
# Isogram is a word with no repeating letters
def isogram?(string)
  original_length = string.length
  string_array = string.downcase.split
 
  binding.pry
 
  unique_length = string_array.uniq.length # Not included in pry's scope...
  original_length == unique_length
end
 
isogram?("Odin")
 

when the program hits binding.pry it opens an IRB-like session in the terminal. This session allows us to check values of anything within the scope of where it’s included, but not anything written or evaluated after…

This practically makes adding binding.pry similar to a breakpoint in other languages when debugging. // In wish this was simply the case TBH

How to Debug

  1. You encounter an error or exception. If there’s a stack trace, follow it, and see where it went wrong and try to figure out why. Sometimes it’s obvious sometimes you’ll need to do some digging. Use the debugger if available.
  2. If the program runs but doesn’t execute as expected or the result isn’t what you want, you’ll need to do some investigating to understand why.