Debugging is an important skill, and although we, the faculty and tutors in CS110, are glad to help you, it's important that you learn how to do this yourself. Here are some strategies that are worth trying.
Debugging JavaScript is a bit harder than debugging HTML, and requires some additional advice, so I've broken this essay down into three sections: general remarks, HTML advice and Javascript advice.
It's inevitable that you will make coding mistakes as you learn HTML and JavaScript; everyone does. Sometimes you can find the error easily by just scanning over your code, but if that doesn't work, you'll have to debug it. Don't get stuck reading and re-reading your code. It's better to have a plan of attack for debugging it. Frustrating as debugging is, it is a good opportunity to practice some logical detective work. We will all try to emulate Sherlock Holmes, and remember that
eliminate the impossible and whatever remains, however implausible, must be the truth.
We have a lot of support in this class, including some excellent tutors who work very hard. We're all glad to help you, but we also want you to become more savvy and independent. Towards that end, we'd like you to think about the following hints and guidelines when you need some help with your assignment.
The most important idea is cutting down the size of the problem. Finding an error in a 100 line HTML file is a lot harder than finding an error in a 10 line HTML file. So the first thing to do is to cut out parts of the file. Anything that you think is irrelevant, cut out. Do this in several steps: first cut out all the stuff that you're really sure is irrelevant, then test the file. If the error remains, cut out the stuff that you're more dubious about, and test again. Keep cutting back until the error disappears. Of course, if your file is already small, you may want to skip ahead to additional HTML advice.
Aside: emotionally, it's very difficult to cut out code that you've worked on and possibly debugged, because you don't want to have to re-do it. Furthermore, it feels like it's a waste of time, compared to just re-reading the code. This is an illusion, though. You will actually save time by debugging in an effective way. First, there are two ways to avoid having to re-do all the code you cut out. One is to copy the entire web page to a temporary page called, say "bug1.html." You can then cut parts out of "bug1.html" and experiment with it until you determine what caused the error in the original file, then you can discard "bug1.html" and go back to the original file and just fix the error. Alternatively, you can copy/paste the pieces you remove from the original to an "outtakes.html" file. Once you've found and fixed the bug, it's easy to copy/paste them back. Cutting out code makes your debugging more efficient even if you're just re-reading the code, since you have less to re-read and your reading is focussed on the relevant portion of the file.
How do you decide which parts are irrelevant? This is not an easy decision: it depends on the nature of the problem you're having, and you will get better at it as you learn more. First, you know that the text (like what you're reading now) is irrelevant; only HTML tags (and JavaScript code) can cause errors, so you can cut the text out. Also, anything later in the file than your problem is irrelevant (for HTML), so that goes. (In other words, if something goes wrong in paragraph two, nothing in paragraph five can have caused it.) Next, if the problem doesn't seem to be related to images, bullet lists, colors, font styles and other simple formatting tags, they can all go. Eventually, you'll get down to tags that seem like they might be relevant to the problem. So cut those out in small, coherent chunks and test after each cut. If the problem goes away or changes, you'll know that the chunk you just cut out is related to the problem. Sometimes, you'll want to restore that chunk (so that the original problem comes back), or you may want to continue to leave it out, debugging this changed problem. The goal is to understand the effects of different chunks of code, so these discoveries will help you debug the problem and help you become a better coder. Thus, part of debugging is learning what is relevant. As you get better, you'll be able to cut the problem down faster.
As you cut out parts of the file, eventually you will cut out the part of the file that is causing the error. Once the error disappears, you know that the error must have been caused or at least facilitated, by some of the code you just removed. Hopefully, this is a small amount of code (say 10 lines of code), and you can read it carefully. If not that doesn't work, start cutting it down. In other words, suppose your original file was 300 lines of code. You start cutting it down and your first step is to cut out about 100 lines of code. (Go ahead and be brutal; your goal is to quickly narrow the problem.) You're surprised to find that the problem goes away. That means the problem is caused by that chunk of 100 lines of code. But 100 lines is too much to re-read. So, you put back 50 of them. That doesn't fix the problem, so you figure the bug is in the other 50 lines of code. You put back 25 lines of the other 50, and the bug returns. Aha! Now we're getting someplace. If you can't determine the bug by closely reading those 25 lines, continue to narrow down the region that could be causing the problem. Try to whittle the code down so that you can determine that just one or two lines of HTML are causing the erroneous behavior.
Many of you will be reminded of the scientific method, where there is a control group and a treatment group (or experimental group) and the experiment is designed to minimize the differences between the two other than what the researcher is interested in. Ideally, the only difference is due to the treatment. In CS110, we're interested in whether a particular tag or line of code causes the error, so we want to find two files such that one of them has the error and the other doesn't, and the only difference between them is the single tag or line of code.
You know you'll have made a lot of progress if you can come up with two files, call them A.html and B.html, such that A exibits the bug or problem and B doesn't, and A and B are as alike as possible. If that's the case, you know that whatever is different between A and B must be the source of the problem.
Unfortunately, A and B may still be fairly large. In that case, you should continue to cut out lines of code that you think are irrelevant, this time doing the same changes to each file. Make sure you test both files after each change, so that you can be sure A still has the bug and B still doesn't. Your first goal is to get them to be as small as possible and as similar as possible, while still exhibiting the difference. I have often ended up with files shorter than a dozen lines of code, where the body of the file is just a few tags, before finally determining the problem.
Once you've got the problem cut down to size, read over the problematic lines very carefully. Very often the error is just a single thing: an incorrect tag or a bit of bad syntax or punctuation. Here are some common ones. I'll give you the code snippet and a hint; you see how quickly you can find the actual error.
<IMG SRC="me.jpg" <blockquote> This is my OneCard picture....
<IMG SRC="me.jpg> <blockquote> This is my OneCard picture....
<IMG SRC="me.jpg"> <block quote> This is my OneCard picture....
<IMG SCR="me.jpg"> <blockquote> This is my OneCard picture....
<IMG SRC="mee.jpg"> <blockquote> This is my OneCard picture....
<IMG SRC="me.JPG"> <blockquote> This is my OneCard picture....
Very often the browser will try to help. If you do "view source" in your browser, it will often blink or highlight in color the place where it got confused. Students who have stared fruitlessly at their code for hours are able to see the problem in a moment once they look at it that way.
Compare your code against the examples in the book or on the web. Is there supposed to be a pound sign here? Is there a quotation mark after this thing? Once you've cut the code down to size, it's much easier to pose and answer these questions for yourself.
The technique of cutting down the code works in a lot of cases and should always be your first line of attack. However, it's important to keep in mind how HTML and JavaScript work as you do this. For example, make sure you cut out code in syntactic units: don't cut out the beginning tag of a region without also cutting out the ending tag.
Sometimes the bug is not in the file, as a coding error in HTML or JavaScript, but is outside the file in some way. For example, anytime a filename or a URL is involved, it's possible that the filename or URL is incorrect. (Cutting down the file size will usually help you determine this, but won't necessarily guide you all the way to the solution.) If a URL is involved, try typing it directly into a web browser, to see if the page is there and visible. You can do this with relative URLs by finding the starting page and then editing the "location" box in the browser to substitute the relative URL information. You can even do this with graphics: if you type the URL of a graphic into your web browser, it will show you the graphic itself, without any surrounding web page. Finally, if you go to a directory (end the URL with the slash after the parent directory), the browser will often give you a directory listing. You can then click on filenames to see what the individual files look like. Carefully check the URL in the "location" box of the browser to make sure there aren't any funny characters. Several times recently this technique helped students find errors in which the filename started with a space. (Spaces like that are insidious because the error is literally invisible. However, it will show up in the browser's URL as a %20. Other funny characters show up with percent signs and a pair of digits.)
In general, once you've done the debugging steps above, if you're still not able to figure out the cause of the error, or why the tag is wrong, by all means ask us. You can ask the tutors during drop-in hours. You can ask the professors during office hours (or make an appointment!). You can post the relevant line or two of code on the Q&A.
Furthermore, because you've done all this work, we will be able to help you more effectively. After all, our first steps would be to boil the code down to its essentials, so if you've already done this, we probably will be able to answer your question correctly right away. In addition, you will have learned a lot about debugging, so that you'll be better at it when the project comes along. The next section is on JavaScript, so if you want to skip ahead to the conclusion, feel free.
This section needs to be improved; suggestions welcome.
As we said, JavaScript is harder to debug than HTML. JavaScript programs have more state: state is stuff stored in variables and other places that might affect the future course of the program. State is part of the power of JavaScript, but with that power comes greater vulnerability to errors.
Don't write a hundred lines of JS code and then try to debug them. It will save you time in the long run to write smaller chunks of code and to test them before proceeding to the next chunk of code. You should code as few lines of code as you can test. Consider the following:
var grade = parseInt(prompt("Enter numerical grade"));
var gradeLetter;
if( grade < 90 ) {
gradeLetter = "A";
} else if ( grade < 80 ) {
gradeLetter = "B";
} else if ( grade < 70 ) {
gradeLetter = "C";
} else if ( grade < 60 ) {
gradeLetter = "D";
} else {
gradeLetter = "F";
}
alert("Letter grade is "+gradeLetter);
This is 12 lines of code, and they all conceptually belong together, so
it's tempting to write them all at once and test them all at once. And
you might be able to do that successfully. But there's an error in this
code. (Actually, there are four errors in this code, all
variations of the first one.) The error would be easier to find if
you'd done:
var grade = parseInt(prompt("Enter numerical grade"));
var gradeLetter;
if( grade < 90 ) {
gradeLetter = "A";
} else {
gradeLetter = "non-A";
}
alert("Letter grade is "+gradeLetter);
It's less to write, so you get to the debugging quicker. Then you can write the expanded version correctly the first time.
If the code doesn't seem to do anything, the first thing you must do is see if there are any error messages, and if so, what they are. The trouble is that browsers are designed to be user-friendly, not developer friendly, so most browsers will hide the error messages from you. Finding the error messages is crucial, and doing that depends on the browser.
Develop with a number of useful
tools on it. You can choose Develop > Show Error Console to see an
error console similar to Firefox's. There's also a Start
Debugging JavaScript menu item that turns on a debugger like
Firebug. To activate the Develop menu, go to Preferences
> Advanced and check the box:
Once you see the error message, you might not understand it. Part of learning how to read them is experience, so don't hesitate to ask (post to the Q&A or email a CS110 faculty member) if you're truly mystified, but you'll find that you can often figure it out with a little guesswork and trial and error.
One reason that the error messages are often unclear is because the browser doesn't know exactly what went wrong, it just knows the place it was when it got confused and what it was expecting. Sometimes it tries to guess what you did that caused the confusion, but when it guesses wrong, the result is even worse. So, you should take the actual message with a grain of salt, but know that the error is at or just before the place that the browser is saying the error is. Sometimes, it's even a line or two earlier. Sometimes it helps to reduce the code to narrow down the exact nature of the problem.
If you're cutting down JavaScript code, make sure you delete, say, an entire "if" statement, rather that leaving pieces of it still around. In fact, everywhere that I said "lines of code" above, I really meant "syntactic units," whatever those are for the language you're working on.
In some cases, which are fortunately rare, you'll find that a bug is caused by the interaction of two things. What this means is that changing either or both of two or more elements in the file causes the bug to appear or disappear. This is very rare in HTML, but a bit more common in JavaScript, just because the language is more complex and interconnected. When this occurs, it's an opportunity to learn more about the language and how things are related. Think about it for a little while, and then, if you're still confused, bring the example to your professor or a tutor. They can then explain the problem and the example that you've developed will show the essential features of the problem and its solution.
One of the mistakes that can cause you to tear your hair out in frustration is debugging the wrong code. That is, you think the problem is on line 15, but something went wrong at line 10 that you're not aware of, and nothing you do to line 15 is going to help.
The solution to this is to
Test your assumptions
One way to do that is to use alert() to print the values
of intermediate results so that you can check to see if they are what you
thought they were.
For example, you're writing code to solve one of those horrible word problems:
Mary is twice the age that Bob will be next year. When will Mary be ...
Your code looks like this:
At the end of this code, including the elided part, you realize the wrong value is being computed. Where do you look? You can check the the value of each variable and compare it to what you expect it to be.
(So, what's wrong with the code above?)
The FireBug plugin that helped us to understand the HTML structure of web pages and debug CSS code also has very helpful JavaScript debugging tools. It will give you syntax error messages, and it also has ways for you to poke around in your code when it doesn't do what you want.
Many of the following tips are variations on the test your
assumptions
mantra from above:
NaN (Not a Number) when you
expected it to be a number?
houron a 24-hour clock or a 12-hour clock?
>=
or >
alert() or using Firebug to step through your
code (or to set a breakpoint at the line in question).
To recap:
Also, out of respect for the time and patience of the tutors, you should follow these etiquette rules: