MTEC1003 — Media Computation Skills Lab
Yep, you guessed it…
Debugging
“[...] the process of finding and resolving bugs (defects or problems that prevent correct operation) within computer programs, software, or systems.”
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?
If so,
After all, our goal is for you to
learn HOW to keep learning,
that is, to squash your own bugs…
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…
1. It takes time,
2. resourcefulness,
3. and problem-solving skills.
There are still
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
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
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.
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…
That was all about debugging temperature.py
Those were fun times, weren’t they?
Some of the most
were discussed in that exercise…
1. a print function
2. a type function
3. using comments effectively
Let’s see these in action…
Which are?
print()
in Python
(Duh, that’s easy to remember…)
console.log()
in JavaScript
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…
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…
[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,
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
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
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…
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.
Which are?
type()
in Python
(Duh, that’s easy to remember…)
typeof()
in JavaScript
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.
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?………
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
First rule about errors:
DON’T PANIC!
Second rule about errors:
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…
Line 2 looks like this:
print("I can lift: " + x + " pounds!")
So, what’s the problem with line 2?
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()
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…
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!
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…
x = 600
print("I can lift: " + x + " pounds!")
# print("I can lift: " + str(x) + " pounds!")
(Line 3 is ignored.)
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!
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.
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!
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.
*/
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:
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.
-->
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…
In any good text editor there is usually
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!
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.
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?
Try to REPRODUCE the bug.
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…
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?
print statements
type functions
commenting in/out different lines
that might be the source of the problem…
Also, never forget to…
Most of the time, your error messages already tell you:
what line the bug is on, and
what kind of error is causing it!
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.
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!
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.
Not much more,
but not much less.
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!
If you still can’t figure it out…
Search forums, e.g. Stackoverflow,
for others who had the same problem…
BUT WAIT!!…
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.
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!
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
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!
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!