DEV Community

Programming Entry Level: beginner debugger

Understanding Beginner Debugger for Beginners

Have you ever written code that just… doesn’t work? It’s a frustrating experience, but a completely normal part of being a programmer! That’s where debuggers come in. Learning to use a debugger is one of the most important skills you can develop as a new programmer. It’s a tool that helps you step through your code line by line, inspect variables, and understand exactly what’s happening – and why it’s not doing what you expect. In fact, being able to confidently talk about debugging techniques is a common question in technical interviews!

2. Understanding "beginner debugger"

Think of a debugger like being a detective investigating a crime. The "crime" is your code not working as expected. Instead of looking for clues at a crime scene, you're looking at the values of variables and the order in which your code is executed.

A debugger lets you:

  • Pause your code: You can tell the debugger to stop running your code at specific points. These are called breakpoints.
  • Step through your code: Once paused, you can execute your code one line at a time.
  • Inspect variables: You can see the current value of any variable in your program. This is incredibly helpful for understanding if your calculations are correct or if data is being stored as you expect.
  • Understand the call stack: This shows you the sequence of functions that led to the current point in your code.

Most code editors (like VS Code, PyCharm, or Sublime Text) have built-in debuggers. They usually have a graphical interface with buttons to control the execution of your code. Don't worry about memorizing all the buttons right away – we'll focus on the core concepts.

3. Basic Code Example

Let's look at a simple Python example. We'll create a function that adds two numbers, but let's say we accidentally make a mistake.

def add_numbers(a, b):
  """Adds two numbers together."""
  result = a - b  # Oops! Subtraction instead of addition

  return result

num1 = 5
num2 = 3
sum_result = add_numbers(num1, num2)
print("The sum is:", sum_result)
Enter fullscreen mode Exit fullscreen mode

This code looks like it should add 5 and 3, but it actually subtracts them! Let's use a debugger to find out why.

  1. Set a breakpoint: In your code editor, click in the margin next to the line result = a - b. This will set a breakpoint.
  2. Run in debug mode: Start your program in debug mode (usually by clicking a "Debug" button or using a keyboard shortcut).
  3. Step through the code: The program will pause at the breakpoint. Now, use the "Step Over" button (it usually looks like an arrow pointing over another arrow) to execute the next line of code.
  4. Inspect variables: As you step through, look at the values of a, b, and result. You'll quickly see that result is 2, not 8. This tells you that the problem is on that line!

By using the debugger, you quickly identified the error without having to guess or add a bunch of print statements.

4. Common Mistakes or Misunderstandings

Here are a few common mistakes beginners make when using a debugger:

❌ Incorrect code:

def greet(name):
  print("Hello" + name) # Missing a space

Enter fullscreen mode Exit fullscreen mode

✅ Corrected code:

def greet(name):
  print("Hello " + name) # Added a space

Enter fullscreen mode Exit fullscreen mode

Explanation: Sometimes the bug isn't a logic error, but a simple typo. The debugger helps you see the exact output, revealing the missing space.

❌ Incorrect code:

def calculate_average(numbers):
  total = 0
  for number in numbers:
    total = total + number
  average = total / len(numbers)
  return average

my_numbers = [] # Empty list

result = calculate_average(my_numbers)
print(result)
Enter fullscreen mode Exit fullscreen mode

✅ Corrected code:

def calculate_average(numbers):
  if not numbers:
    return 0  # Handle empty list case

  total = 0
  for number in numbers:
    total = total + number
  average = total / len(numbers)
  return average

my_numbers = [] # Empty list

result = calculate_average(my_numbers)
print(result)
Enter fullscreen mode Exit fullscreen mode

Explanation: Dividing by zero is a common error. The debugger will show you the ZeroDivisionError and point you to the line causing the problem. Adding a check for an empty list prevents the error.

❌ Incorrect code:

def process_data(data):
  for item in data:
    print(item.upper()) # Assuming data contains strings

my_data = [1, 2, 3]
process_data(my_data)
Enter fullscreen mode Exit fullscreen mode

✅ Corrected code:

def process_data(data):
  for item in data:
    if isinstance(item, str):
      print(item.upper()) # Only process strings

    else:
      print(item) # Handle other data types

my_data = [1, "hello", 3]
process_data(my_data)
Enter fullscreen mode Exit fullscreen mode

Explanation: The debugger will show you an AttributeError when you try to call .upper() on an integer. This indicates that your assumption about the data type was incorrect.

5. Real-World Use Case

Let's imagine you're building a simple to-do list application. You have a Task class and a TodoList class. You add a task, but when you try to mark it as complete, it doesn't work.

class Task:
    def __init__(self, description):
        self.description = description
        self.completed = False

    def mark_complete(self):
        self.completed = True

class TodoList:
    def __init__(self):
        self.tasks = []

    def add_task(self, description):
        task = Task(description)
        self.tasks.append(task)

    def complete_task(self, index):
        self.tasks[index].mark_complete()

# Example Usage

my_list = TodoList()
my_list.add_task("Buy groceries")
my_list.add_task("Walk the dog")

my_list.complete_task(0)

# Check if the task is completed

print(my_list.tasks[0].completed) # Expected: True, but might be False

Enter fullscreen mode Exit fullscreen mode

If the task isn't marked as complete, you can set a breakpoint inside the complete_task method and step through the code. You can inspect self.tasks[index] to see if you're accessing the correct task and then step into the mark_complete method to see if self.completed is actually being updated. This will quickly pinpoint the issue.

6. Practice Ideas

Here are some exercises to help you practice using a debugger:

  1. Find the Bug: Write a function that calculates the factorial of a number. Introduce a bug (e.g., incorrect loop condition) and use the debugger to find it.
  2. List Search: Write a function that searches for a specific value in a list. If the value isn't found, the function should return -1. Use the debugger to verify that the function correctly handles both cases (value found and value not found).
  3. String Reversal: Write a function that reverses a string. Use the debugger to trace the string manipulation process and ensure it's working as expected.
  4. Simple Calculator: Create a basic calculator that performs addition, subtraction, multiplication, and division. Use the debugger to test each operation and handle potential errors (like division by zero).

7. Summary

You've learned the basics of using a debugger – setting breakpoints, stepping through code, and inspecting variables. This is a powerful skill that will save you countless hours of frustration. Don't be afraid to experiment and explore the features of your debugger.

Next, you might want to learn about more advanced debugging techniques, such as conditional breakpoints (breakpoints that only trigger when a certain condition is met) and remote debugging (debugging code running on a different machine). Keep practicing, and you'll become a debugging master in no time! You got this!

Top comments (0)