Posted: Thu Oct 07, 2004 12:00 am Post subject: Debugging
Think of this as advice on how to write better code. It will be an ongoing tutorial, updated as I get time.
Sponsor Sponsor
Martin
Posted: Thu Oct 07, 2004 12:26 am Post subject: (No subject)
1. Comments
Comments are essential to programming. This is somewhat ironic, as comments do not actually effect the code in any way. A comment is just what it sounds like; it is a programmer's remark, or a note in the code.
In most languages, comments are tagged in one of two ways: there are single line comments, which are usually denoted by '//' and there are encasing comments, opened by '/*' and closed by '*/' . Instead of '//' to denote single line comments, turing uses '%'
Now, the question is: what does a comment do that is so useful that it can help me write programs that don't crash? It tells the computer to ignore a line of code. Below is an example of comments in a turing program:
code:
put "hello"
% This line is commented, and does nothing
var x : int %you can put comments onto the end of lines of code
x := 5
% Everything after the comment sign (%) is ignored by the processor.
% put "This line is actually commented out, and doesn't ever get run"
for i: 1 .. 5
/* multiple line comments
can be encased in comments
like these */
put i
% x := x + 1
end for
Now, quick quiz: what is the value of x at the end of this program? The correct answer is 5, as the line x := x + 1 is commented out.
Alright enough of the boring stuff, now onto why comments are useful. Programmers use comments to leave themselves, or other programmers, notes in their code. This can be for two purposes: either the section of code is confusing, and writing out what it does in english helps make it easier for you to understand, or to simply make it easy to start in the middle of the code and know what is happening. It doesn't matter how good of a programmer you think you are, well commented code is essential. Now, by well commented, I don't mean excessively commented. Lines that are obvious what they do don't deserve comments. As follows:
Useless
code:
var x: int %this is an integer
Anyone could have figured this out
Good
code:
var x: int %stores the number of sheep
Much better, this comment is short, and explains exactly what the variable does.
More specific uses of comments will be explained in later tutorials.
wtd
Posted: Thu Oct 07, 2004 2:08 am Post subject: (No subject)
Even better, use:
code:
var numberOfSheep : int
No need for comments.
shorthair
Posted: Thu Oct 07, 2004 10:57 am Post subject: (No subject)
would you rather type x every time , or numberofsheep
by commenting , you have to only write it once and you get hte point acroos,
wtd your way requires much more effort , the only way that i would use it would be
var X ,NumberOfSheep : int
NumberOfSheep := X
sorry had to be a little sarcastic there
Martin
Posted: Thu Oct 07, 2004 11:08 am Post subject: (No subject)
Damn it guys, that was coming next.
Martin
Posted: Thu Oct 07, 2004 11:26 am Post subject: (No subject)
2. Pre and Post Conditions
Pre and post conditions are simply a specific use of comments. The pre condition of a function is basically a statement of has to be true going into the function. The post condition of a function is what is true coming out of the function.
code:
function divide (a, b : int) : real
result a / b
end divide
So now we have to ask ourselves when this function will go wrong. The answer is, clearly, when b = 0, the program will crash and return a divide by zero error. What happens after the function is complete? It returns a/b. So, we put these facts in pre and post conditions:
code:
function divide (a, b : int) : real
%Pre: b is not equal to 0
%Post: returns a divided by b
result a / b
end divide
Now the problem with this example is that it is very obvious. Anyone who's used turing for a week could look at that and tell you what it does. The larger your function grows, the more difficult it becomes to figure out what exactly it does. Take this function, for example (in java, I didn't feel like translating it):
code:
//pre: takes an ordered list of rowIndicies and colIndicies
//post: returns the subMatrix with rows as numbered in rowIndices, and columns as numbered by colIndices, or null should there be a problem with rowIndices
public Matrix subMatrix(int[] rowIndices, int[] colIndices) {
int subrows=rowIndices.length;
int subcols=colIndices.length;
if (rowIndices[0]<1 || rowIndices[0]>rows) {
System.out.println("Row index out of bounds\n");
return null;
}
for(int i=1; i<subrows; i++)
if (rowIndices[i]<1 || rowIndices[i]>rows || rowIndices[i]<=rowIndices[i-1]) {
System.out.println("Row index out of bounds or unordered\n");
return null;
}
if (colIndices[0]<1 || colIndices[0]>cols) {
System.out.println("Column index out of bounds\n");
return null;
}
for(int i=1; i<subcols; i++)
if (colIndices[i]<1 || colIndices[i]>cols || colIndices[i]<=colIndices[i-1]) {
System.out.println("Column index out of bounds or unordered\n");
return null;
}
Matrix b=new Matrix(subrows,subcols);
for (int i=1; i<=subrows; i++)
for (int j=1; j<=subcols; j++)
b.set(i,j,get(rowIndices[i-1],colIndices[j-1]));
return b;
}
As you can see, pre and post conditions become even more useful.
Next, I will explain error checking within a function
JHanson90
Posted: Thu Oct 07, 2004 1:42 pm Post subject: (No subject)
shorthair wrote:
would you rather type x every time , or numberofsheep
by commenting , you have to only write it once and you get hte point acroos,
wtd your way requires much more effort , the only way that i would use it would be
var X ,NumberOfSheep : int
NumberOfSheep := X
sorry had to be a little sarcastic there
I would rather use the 'numberofsheep' variable. Instead of making the comment everytime you think that you will forget what 'x' was, you could just avoid the coment altogether. I use comments as a form of explaining how the program works and what I am going to do with the variable, not so much telling you what the code is doing.
Tony
Posted: Thu Oct 07, 2004 2:11 pm Post subject: (No subject)
ideally you should be able to look at a block of code and be able to explain what it does without refering to a comment you wrote elsewhere.
even though
code:
a = f(b);
is short to write, it is not descriptive at all. If there's an error in the code and somebody is trying to figure out the (supposedly corrupt logic) they must scroll up to variable declarations to find out what a/b are, and then locate function f to find out what that does. And if you keep up this style of coding, you can really send somebody on a wild goose chaise for comments using nested functions
Posted: Thu Oct 07, 2004 7:31 pm Post subject: (No subject)
Ah. I thought he was merely referring to a basic pattern.
Martin
Posted: Thu Oct 07, 2004 9:43 pm Post subject: (No subject)
People, have a little faith in me
wtd
Posted: Sat Oct 09, 2004 12:01 am Post subject: (No subject)
Functional Decomposition
Huh? What now?
Basically, that rather dry term means breaking a problem into several smaller problems, each with a meaningful name to indicate what's going on.
A function or procedure is a black box. It takes in certain pieces of data and does something. So long as it does those things correctly, we don't particularly care how it accomplishes them.
Why is this important?
By breaking a program up into several smaller problems we end up with small, simple problems that are easier to debug than if we tried to take on the whole problem all at once.
Once each smaller problem is debugged, you can then use it freely in the program without worrying that the code it contains is a source of problems.
Breaking up a program also greatly improves collaboration between two or more programmers on one project. You can, as a team, decide on what functions and procedures to use, and how they should behave, then split them up and separately implement those functions and procedures.
Lastly...
Creating functions and procedures to handle smaller problems in your program means that you give a name to commonly used code. Rather than retyping (or copying and pasting) bits of code you use frequently, you only write the code once.
Should you go back later and want to change that code, you need only do it in one place. The alternative is to change code in several places, and hope you don't miss any.
wtd
Posted: Sat Oct 09, 2004 12:09 am Post subject: (No subject)
Of course, the last point in my previous post is just generally good practice.
If you can write code once, then only write it once.
Bad
code:
if foo = 42 then
put "Something!"
put foo * 2
else
put "Something!"
put foo / 2
end if
Good
code:
put "Something!"
if foo = 42 then
put foo * 2
else
put foo / 2
end if