DEV Community

Programming Entry Level: step by step debugging

Understanding Step by Step Debugging for Beginners

So, you've written some code, and… it's not working as expected? Don't panic! This is completely normal. Every programmer, even the most experienced, spends a lot of time debugging. And one of the most powerful tools in your debugging arsenal is step by step debugging. This post will walk you through what it is, how to use it, and why it's so important. Knowing how to debug effectively is a key skill employers look for, and it will save you hours of frustration.

2. Understanding "step by step debugging"

Imagine you're baking a cake. You follow a recipe, but the cake doesn't rise. You wouldn't just stare at the finished (flat) cake, right? You'd go back through the recipe, step by step, checking if you added the baking powder, if the oven temperature was correct, and so on.

Step by step debugging is exactly the same! It means running your code one line at a time, and observing what happens with your variables and data at each step. It's like having a magnifying glass for your code. You can see exactly what the computer is doing, and pinpoint where things start to go wrong.

Most code editors (like VS Code, PyCharm, or even simpler ones) have built-in debuggers. They let you:

  • Pause execution: Stop the code at a specific line.
  • Step over: Run the current line and move to the next.
  • Step into: If the current line calls a function, jump inside that function to debug it line by line.
  • Inspect variables: See the current value of variables.

Think of it like controlling a movie player – pause, play, rewind, and examine the scene closely.

3. Basic Code Example

Let's look at a simple Python example:

def add_numbers(a, b):
  """This function adds two numbers together."""
  sum = a + b
  return sum

number1 = 5
number2 = 10
result = add_numbers(number1, number2)
print("The sum is:", result)
Enter fullscreen mode Exit fullscreen mode

Let's break this down.

  1. def add_numbers(a, b): defines a function called add_numbers that takes two arguments, a and b.
  2. sum = a + b calculates the sum of a and b and stores it in a variable called sum.
  3. return sum returns the value of sum back to where the function was called.
  4. number1 = 5 assigns the value 5 to the variable number1.
  5. number2 = 10 assigns the value 10 to the variable number2.
  6. result = add_numbers(number1, number2) calls the add_numbers function with number1 and number2 as arguments, and stores the returned value in the variable result.
  7. print("The sum is:", result) prints the value of result to the console.

Now, let's say we suspect something is wrong with the add_numbers function. We can use a debugger to step through it. We'd set a "breakpoint" (a pause point) on the first line of the function, then:

  • Step over the first line.
  • Inspect the values of a and b. We should see 5 and 10.
  • Step over the second line.
  • Inspect the value of sum. We should see 15.
  • Step over the third line.
  • The function returns, and we continue debugging the rest of the code.

4. Common Mistakes or Misunderstandings

Here are a few common pitfalls when starting with step by step debugging:

❌ Incorrect code:

def greet(name):
  print("Hello")
Enter fullscreen mode Exit fullscreen mode

✅ Corrected code:

def greet(name):
  print("Hello,", name)
Enter fullscreen mode Exit fullscreen mode

Explanation: You might expect the greet function to print "Hello, [name]", but it only prints "Hello". Stepping through the code reveals that the name variable isn't being used in the print statement.

❌ Incorrect code:

def calculate_area(length, width):
  area = length + width
  return area
Enter fullscreen mode Exit fullscreen mode

✅ Corrected code:

def calculate_area(length, width):
  area = length * width
  return area
Enter fullscreen mode Exit fullscreen mode

Explanation: You're calculating the perimeter instead of the area! Stepping through the code and inspecting the area variable will quickly show you that it's the sum of length and width, not their product.

❌ Incorrect code:

my_list = [1, 2, 3]
for i in range(len(my_list)):
  print(my_list[i + 1])
Enter fullscreen mode Exit fullscreen mode

✅ Corrected code:

my_list = [1, 2, 3]
for i in range(len(my_list)):
  print(my_list[i])
Enter fullscreen mode Exit fullscreen mode

Explanation: This code will cause an IndexError because you're trying to access an element beyond the end of the list. Stepping through the loop will show you exactly when the error occurs.

5. Real-World Use Case

Let's imagine you're building a simple to-do list application. You have a Task class:

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

    def mark_complete(self):
        self.completed = True

    def __str__(self):
        return f"Task: {self.description}, Completed: {self.completed}"

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

    def add_task(self, task):
        self.tasks.append(task)

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

    def display_tasks(self):
        for task in self.tasks:
            print(task)

# Example Usage

todo_list = TodoList()
task1 = Task("Buy groceries")
task2 = Task("Walk the dog")
todo_list.add_task(task1)
todo_list.add_task(task2)
todo_list.display_tasks()
todo_list.complete_task(0)
todo_list.display_tasks()
Enter fullscreen mode Exit fullscreen mode

If the complete_task function isn't working, you can set a breakpoint inside it and step through to see if task_index is the correct value, and if self.tasks[task_index] is actually a Task object. This helps you understand if the problem is with the index, the list itself, or the mark_complete method.

6. Practice Ideas

Here are some exercises to help you practice step by step debugging:

  1. Find the Error: 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 Manipulation: Create a list of numbers and write a function to find the largest number. Debug the function to ensure it works correctly with different lists.
  3. String Reversal: Write a function to reverse a string. Use the debugger to trace the string manipulation process.
  4. Simple Calculator: Build a basic calculator that performs addition, subtraction, multiplication, and division. Debug the functions to handle different inputs and potential errors (like division by zero).
  5. Debugging a Loop: Write a loop that prints numbers from 1 to 10, but intentionally introduce an error that causes it to stop prematurely. Use the debugger to find the error.

7. Summary

You've now learned the basics of step by step debugging! It's a crucial skill for any programmer. Remember to:

  • Use breakpoints to pause execution.
  • Step over lines to see what happens.
  • Step into functions to debug them in detail.
  • Inspect variables to understand their values.

Don't be afraid to experiment and practice. The more you use the debugger, the more comfortable and efficient you'll become. Next, you might want to explore more advanced debugging techniques like conditional breakpoints and watch expressions. Happy debugging!

Top comments (0)