Introduction to Debugging

einbahnstrasse.github.io/MTEC1003-slides/slides/debugging.tutorial.v01/

MTEC1003 — Media Computation Skills Lab

In this tutorial, we’ll discuss…

Yep, you guessed it…

Debugging
bug

What is Debugging?

“[...] the process of finding and resolving bugs (defects or problems that prevent correct operation) within computer programs, software, or systems.”

Wikipedia

It’s can also be thought of as
a process of identifying:

what variables

hold what values

at what point in time.

—Rebecca Hill, WeTransfer.com
Debugging Specialist + JavaScript Developer

By now, you’ve had plenty of opportunity
to create bugs in your code…

I mean, think of all those lovely JavaScript + Python exercises we’ve done!

But, have you fixed these errors on your own?

debug-meme

If so,

CONGRATULATIONS!!

After all, our goal is for you to
learn HOW to keep learning,
that is, to squash your own bugs…

bug

Much of the time, however,
catching + solving our own coding mistakes…

well, it can be difficult…

and maybe we don’t always figure it out…

The truth about debugging is

1. It takes time,

2. resourcefulness,

3. and problem-solving skills.

Yet Surprisingly,

we rarely teach debugging!

bug

There are still

computer science programs

where you can spend your entire degree
never learning how to debug!

How could that be, you ask??

Maybe it’s because
we’ve always relied on the

NATURAL PROBLEM SOLVING SKILLS
of so-called “good students?”

Maybe we’ve even taken this for granted…?

Or, maybe it’s because now there are

a lot more computer languages

to learn…

Or maybe it’s because

software projects today

typically use pieces of code

from these different languages, packages, libraries, frameworks, etc..

all having their own documentation!

Developers need to be well-prepared
to interact with these languages.

Imagine being asked to speak to a room full of
English, Spanish, French, and Chinese speakers without

brush

FULLY UNDERSTANDING THE RULES
that govern those languages?!

You’ll probably make some mistakes, right?

We need tools to navigate situations like that.

Plus, software today serves a wide variety of purposes:

web development / front-end

game design

app development

endless machine learning initiatives

…just to name a few

Which means:

efficiently debugging

many languages

at the same time

becomes an ever-greater challenge.

How To Debug

So, “How do I fix my broken code,” you ask?

Actually, you’ve already debugged something!

If you’ve been doing your labs, of course…

Do you remember?

brush

Lab 6 / Part 2 ?

That was all about debugging temperature.py

Those were fun times, weren’t they?

Some of the most

Essential Debugging Tools

were discussed in that exercise…

Essential Debugging Tools

1. a print function

2. a type function

3. using comments effectively

Let’s see these in action…

1. Our Print Functions

Which are?

print() in Python
(Duh, that’s easy to remember…)

console.log() in JavaScript

You may think

these functions are only good
for Day #1 of your programming class:

console.log("Hello world!");
print("Whoa, I can print something... How useless.")

But, we teach them for a good reason…

Let’s say you need to quickly make a list
of numbers from 1 to 20 in Python, like this:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

To do this, you’ve written a lovely for loop:

count = 0
myList = []

for i in range(20):
    count = count + i
    myList.append(count)
print(myList)

Looks good…

This should work……

We’re finished here, right?………

So you run your Python script in Terminal,
and to your surprise,
you get:

[0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190]

This… uh… doesn’t go from 1 to 20…

HEY WHA' HAPPENED?!

So, you go back to your beautiful Python code:

count = 0
myList = []

for i in range(20):
    count = count + i
    myList.append(count)
print(myList)

and realize you need to see what’s going on
inside the loop, that is, at every step…

How do you know this?

[0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190]

Because it’s not incrementing in 1s.

Also not incrementing in regular intervals, which is weird…

Plus, the increment gets wider each time… Bizarre!

To see what’s happening each time,

Add a Print Statement

count = 0
myList = []

for i in range(20):
    count = count + i
    myList.append(count)
    print("current i is: " + str(i) + " and count is: " + str(count))
print(myList)

This converts i and count into strings using str()

It also concatenates them into 1 string,
and passes the string to print()

It’s indented, so it’s inside the for loop.

Our print() statements give us a new point of view:

current i is: 0 and count is: 0
current i is: 1 and count is: 1
current i is: 2 and count is: 3
current i is: 3 and count is: 6
current i is: 4 and count is: 10
current i is: 5 and count is: 15
...
current i is: 19 and count is: 190
$ 

Now it’s clear that i indexes by 1s, but count is irregular.

We also see count increasing by the current i each time.

Once we’ve “seen it this way,”
it occurs to us that what we need is to

add a constant

at a value of 1 to the value of count

and not an expanding interval like i

So, we make one small change to our code:

count = count + 1

to ensure that count increments by 1s, as we intend.

And our Terminal output confirms it works!

current i is: 0 and count is: 1
current i is: 1 and count is: 2
current i is: 2 and count is: 3
current i is: 3 and count is: 4
current i is: 4 and count is: 5
current i is: 5 and count is: 6
...
current i is: 19 and count is: 20
$ 

Now count properly increments by 1s, from 1 to 20.

And maybe you noticed we don’t need count
to do what we want at all…

The final version of our code is much cleaner:

myList = []
for i in range(1, 20):
    myList.append(1)
print(myList)

and our Terminal output is correct:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

Turns out we only needed to append our index variable i.

To fix our mistake, all we needed was this

change in perspective

made possible using a

Once we could see the results of the loop
at each step, the rest just fell into place.

So, next time you can’t figure out
why something isn’t working…

Add some print statements!

like print() in Python

or console.log() in JavaScript

to monitor changing variables,
and to reveal where things went wrong
at internal levels of your programming.

2. Our Type Functions

Which are?

type() in Python
(Duh, that’s easy to remember…)

typeof() in JavaScript

What does a Type Function do?

Sometimes, an error results because
it’s unclear what type of data you’re working with.

Often, this happens when a variable holds
a different kind of value (or type) that should be
processed by a function you pass your variable on to.

Wait, what?!

Okay. Say, for example, you have Python variable x
and you want to concatenate x inside a print statement:

x = 600
print("I can lift: " + x + " pounds!")

And you’re expecting this output:

I can lift: 600 pounds!

So, you run your code…

Looks good…

This should work……

We’re finished here, right?………

Surprise!

ERROR IN THE CONSOLE:

Traceback (most recent call last):
  File "/path/to/my/file.py", line 2, in <module>
    print("I can lift: " + x + " pounds!")
TypeError: can only concatenate str (not "int") to str

HEY WHA' HAPPENED?!

Understanding Errors

First rule about errors:

DON’T PANIC!

Second rule about errors:

READ YOUR ERROR MESSAGES!

Traceback (most recent call last):
  File "/path/to/my/file.py", line 2, in <module>
    print("I can lift: " + x + " pounds!")
TypeError: can only concatenate str (not "int") to str

Look again:
It tells us the problem is on line 2…

Go back to your Python code

Line 2 looks like this:

print("I can lift: " + x + " pounds!")

So, what’s the problem with line 2?

READ YOUR ERROR MESSAGES!

Traceback (most recent call last):
  File "/path/to/my/file.py", line 2, in <module>
    print("I can lift: " + x + " pounds!")
TypeError: can only concatenate str (not "int") to str

Look again:
It also tells us line 2 has a TypeError

It can’t concatenate
an integer (“int”) to a string (“str”)

That just means we forgot
to convert variable x into a string,
before we passed x to the print() function.

But maybe, for whatever reason, it’s not obvious
what type of data is contained in variable x.

Well, we can test x to find out what type it is…

…using type()

Determining the type

Go back to your Python code, and comment out line 2:

x = 600
# print("I can lift: " + x + " pounds!")

This way, we can make changes without losing line 2.

Now our program won’t run line 2 since it’s commented out, and so it won’t throw an error.

We can always comment in line 2 again if we need it…

Then, insert a new line 2 that reads:

x = 600
print(type(x))
# print("I can lift: " + x + " pounds!")

We use type() to test the type of value
contained in variable x.

Then we print() the result.

Run the code in Terminal to see the result…

<class 'int'>

This is the output of the the type() function.

It tells us that the variable x is an ‘int’ or integer,
and not a string like we need.

Now it’s clear: we gave print() the wrong type

So we got a TypeError

Let’s change x’s type and see what happens…

Fixing a TypeError

Go back to your Python code.
Comment out print(type()), then comment in
your original line 2 (now line 3). Make 1 small change:

print("I can lift: " + str(x) + " pounds!")

We use str() to convert x into a string.

Now, our complete code looks like this:

x = 600
# print(type(x))
print("I can lift: " + str(x) + " pounds!")

Let’s see what the output will be.

I can lift: 600 pounds!
$

Just as we expected! It works!

There you have it:

Fixing a TypeError is a piece of cake!

3. Using Comments Effectively

Normally, we think of comments as a great way to document our work.

For example:

x = 600
# set variable x to value 600
print("I can lift: " + str(x) + " pounds!")
# concatenate string, then print!

The comments above are ignored by the compiler
when you run your code.

They’re used to remind us what our code is doing,

They can also annotate + explain complicated algorithms in “human-readable language,”

so we should use them frequently for these purposes!

But we can also use comments in other ways…

For example, recall when we were about
midway through our last example:

x = 600
print(typeof(x))
# print("I can lift: " + x + " pounds!")

Here, we commented out the original print statement

so it wouldn’t throw an error.

We could always comment in our print statement later.
That way, we don’t lose our work.

But how about this version?

x = 600
# print("I can lift: " + x + " pounds!")
# print("I can lift: " + str(x) + " pounds!")

Now, there are 2 lines commented out:

2 different versions of the same print statement.

This lets us try different solutions
and keep track of our progress without loosing our work, like this…

Possible solution #1:

x = 600
print("I can lift: " + x + " pounds!")
# print("I can lift: " + str(x) + " pounds!")

(Line 3 is ignored.)

Possible solution #2:

x = 600
# print("I can lift: " + x + " pounds!")
print("I can lift: " + str(x) + " pounds!")

(Line 2 is ignored.)

We can freely comment in and out these lines
without deleting any of our work!

So, you can use comments to:

1. remind yourself what your code is doing, esp. long after you wrote it (e.g. when you need it in a future class…)

2. document, annotate + explain complicated algorithms.

3. save + organize problematic lines, and

4. try multiple solutions to the same problem,
without losing your work.

Single-Line Comments

If you just need to comment out 1 line at a time:

In Python, use #
(pound sign, number sign, “hashtag”)

In JavaScript, use //
(2 forward slashes)

For example:

# I'm a single-line comment in Python!
// I'm a single-line comment in JavaScript!

Multi-Line Comments

If you have more than 1 line to comment out:

In Python, use 3 quotes: ”””
on lines before + after your comment.

In JavaScript, use /* before,
and */ after your comment.

For example:

"""
I'm a multi-line
c O m M e N t
in Python!
Compilers always ignore me.
"""
/* I'm a multi-line
C o M m E n T
in JavaScript!
Compilers always ignore me.
*/

HTML + CSS

We haven’t learned much about these yet,
but we will later this semester…

These 2 languages have one comment format
for both single-line and multi-line comments:

In HTML:

Use <!-- before,
and --> after your comment.

For example:

<!-- I'm a single-line comment in HTML! -->
<!--
I'm a multi-line
c O m M e N t
in HTML!
Compilers always ignore me.
-->

In CSS:

Use /* before,
and */ after your comment.

…Just like in JavaScript!

For example:

/* I'm a single-line comment in CSS! */
/*
I'm a multi-line
c O m M e N t
in CSS!
Compilers always ignore me.
*/

Wow that’s a lot of differing syntax!
How do I keep track of all these comment formats?

Well, the good news is…

You don’t have to remember them!!

In any good text editor there is usually

1 keystroke to rule them all…

Toggle Single-Line Comments On-And-Off

In your text editor, position your cursor
anywhere on a line of code, then:

On macOS, type Command ⌘ + /

On Windows, type Control + /

Do it once to comment out,

// console.log("I'm a single-line C o M m E n T in JavaScript!"); 

Your text editor adds the
proper comment characters for you!

do it again to comment in.

console.log("I'm a single-line C o M m E n T in JavaScript!");

Your text editor removes the
proper comment characters for you!

Multi-line Comment Blocks

Easy! Just highlight the lines you need to comment,
and use the same keystroke you did before!

On macOS, type Command ⌘ + /

On Windows, type Control + /

With your multiple-lines highlighted,

Do it once to comment out,

do it again to comment in.

Amazing!

You don’t need to memorize anything but the keystrokes!

So far we’ve seen some of the essentials…

But, there must be an order to all this madness, right?

What steps should I take to debug effectively?

Debugging Step #1

Try to REPRODUCE the bug.

Ask yourself:

Can I make this error reappear in some predictable way?

Does it only happen sometimes or always?

Observe + try to make the error appear again…

By the way, this is gonna feel
a little bit like detective work…

Debugging Step #2

ISOLATE the bug.

Can you narrow down all of your code
to just 1 part that’s causing the error?

What are some tools you can use to do this?

How about starting with

print statements

type functions

commenting in/out different lines
that might be the source of the problem…

Also, never forget to…

READ YOUR ERROR MESSAGES!

Most of the time, your error messages already tell you:

what line the bug is on, and

what kind of error is causing it!

Debugging Step #3

DON’T CHANGE TOO MUCH AT ONCE!

Be methodical and systematic
about the changes you make
in pursuit of a solution…

Break down your plan of action
into a series of logical steps.

Document each solution you try.

Hey! Here’s an idea:

You can even think of this process like
one giant conditional statement…

IF my 1st idea doesn’t squash the bug,

THEN try something else…

ELSE IF that doesn’t work,

THEN try the next idea…

and so on…

But, if you introduce
too many new elements into your code
all at the same time…

You’ll have made changes

that impact your program

in too many ways to keep track of,

changing multiple behaviors
within your code.

Then, you’ll probably get confused,

and forget what you’ve already tried.

And if you fix it,

it will not be clear what worked!

Debugging Step #4

If you can’t figure it out at first…

Spend about 1 hour working on the problem, and

take frequent breaks to refresh your brain.

An hour can make a difference

Not much more,
but not much less.

Or try the Pomodoro Method

If you want to be more systematic…

Taking a break means you’ll return
with a fresh perspective…

And maybe the solution will be instantly clear!

Debugging Step #5

If you still can’t figure it out…

Search forums, e.g. Stackoverflow,
for others who had the same problem…

googleit

BUT WAIT!!…

Don’t just copy/paste!

Why not?! It’s so easy!

Because you won’t learn anything that way…

If you copy/paste code from a forum,

You won’t understand why your own code didn’t work,

and you also won’t know
why the solution you found does work.

If you copy/paste code from a forum,

without fully understanding what that code does,

you’re going to keep repeating the same mistake!

So if you find something online that helps…

you must study and understand it
in order to use it.

And to avoid possible disciplinary action,
you must also cite someone else’s code.
See our syllabus blurb on plagiarism for more info.

Debugging Step #6

If nothing else works…

Ask someone for help.

But, be prepared to
show them what you’ve already tried.

Be mindful of your colleague’s time:

Don’t ask for too much of it.

Don’t expect them to start from scratch for you.

Guide them to the source of the problem, and

show what you do understand about the bug!

Treat this person as if they were a
senior developer at your new job…

You need them to
believe in your ability
to work independently!

Protips on asking for help

Prepare specific questions about the bug.
(not “OMG HAAALP! I don’t know what to do!”)

Share what you’ve done + what you understand so far.
Don’t worry: it’s a process… You’re learning!

Gather your questions in advance so you don’t keep asking.

But most importantly…
Before asking anyone for help,

Follow the previously-mentioned

Debugging Steps

and challenge yourself
to find a solution on your own.

You will grow as a coder because of it!

You’ll remember how to
solve similar problems
more frequently!

Think of it this way:

We actually don’t learn enough
from “pretty” examples of perfectly-working code…

We learn WAY MORE from fixing
our very own broken code!

So, debugging is basically its own study,

and these were just a few ideas to get you started.

There are some powerful debugging tools out there…

For example, our web browser Google Chrome
has excellent support for debugging JavaScript…

We might explore more advanced debugging
strategies, such as this, on another day.

Meanwhile,

the concepts discussed above
are really the essentials we need.

So for now…

Happy debugging!

bug

Resources

Some of the ideas in this presentation were borrowed from the following episode of the Ladybug Podcast:

Listening to the whole conversation is highly recommended!

Also, check out how this guy
locates + solves a nasty Python bug:

You don’t need to understand all the code he uses.
The concepts are more important!

Finé

bug