Guidelines for Good Documentation and Testing
Comments must be written in correct English (but not necessarily complete
sentences. It is better to be clear and concise rather than overly
wordy. You may use point form).
Comments must give more than a mere repetition of what the code itself
says. (Describe what the code does and why, rather than how
it does it.)
An informed reader should be able to understand the program by reading
the comments alone. (Using mnemonic function and variable names is good,
but you should not just assume they will be understood.)
At the top of the program:
Give your name and student number, the course number, the lecturer's and
tutor's names, and the assignment number.
Explain in general terms what the program does. E.g., ``A program for sorting
student academic records.''.
Describe all input to the program --- where it comes from and what its
format must be, and describe the output.
For functional languages, indicate which function is the top-level function,
i.e., corresponds to a main program, if any. Inputs to that function and
the value returned by it can be described at the top of the program or
by that function.
For Prolog, indicate which clause is the top-level clause, if any. The
clause can be described at the top of the program or where it is defined.
Note any special aspects of the program (e.g., cases it can not handle,
fancy tricks or algorithms it uses).
On every procedure/function:
Describe what the subprogram does.
Explain the meaning of each value passed in and passed out.
Describe any access to and/or changes made to global variables (but remember
that global values should be used very sparingly and carefully).
On variable, constant, and type declarations in a procedural language
Explain the use of the thing declared (e.g., for a variable called count,
explain what it counts).
On each conditional or counted loop in a procedural language
Explain how many times the loop repeats (e.g., ``until the command entered
Explain what one repetition of the loop does (e.g., ``read in and process
a single command.'')
For each predicate in a Prolog program:
Explain the form and meaning of each argument to the predicate.
Explain what it means for the predicate to be true.
For each clause defining that predicate, explain how this clause allows
Prolog to prove that the left-hand side is true, i.e., explain the right-hand
% "delete(X, In, Out)" is true iff Out is the list that results from
% deleting all occurrences of X from In.
% (Describe each variable)
% X - an atom
% In - the list X's are to be removed from
% Out - the resulting list, after all X's have been removed
% If In is empty, then the resulting list Out is empty also, no matter
% what it is that we are deleting.
delete (X, , ).
% If the first thing in the In list is the thing we are deleting, then
% it should not appear in the Out list. The Out list is simply what
% we would get from deleting all occurrences of X from the remainder of
% the In list.
% A cut is used here to prevent backtracking to the next delete clause
% when the front of the In list equals X. (The next delete clause
% assumes they are not equal.)
delete (X, [X|Rest], Out) :- !, delete (X, Rest, Out).
% We can only get to this clause if the front of the In list is not X,
% because of the cut in the above clause.
% In this case, the front of the In list, Y, should appear at the front
% of the Out list. The rest of the Out list is what we get from deleting
% all occurrences of X from the rest of the In list.
delete (X, [Y|Rest], [Y|Out]) :- delete (X, Rest, Out).
This may seem like an excessive amount of commenting, but to be complete
you should say all of this. (You may be able to express it more concisely,
and that would of course be good.) It should not require a great effort
to comment this completely if you do understand your code! And it will
probably help you debug, as well as help the reader understand.
On tricky sections of code:
Give the reader extra help in understanding what is going on.
The purpose of your testing is to convince the marker (and yourself!) that
the program works in every case.
You should test ALL base cases!
For Prolog, you should exercise EVERY clause.
Obviously you can not test every possibly combination of inputs; instead
you must break these into classes that cover all possibilites and provide
working examples from each class. If the classes are well-chosen, this
testing will allow you to conclude that all cases in each class, and hence
all cases, are correctly handled.
You must show the marker that you chose the test cases properly by DOCUMENTING
what each case tests. Handwritten explanations on the output are sufficient.
Typed explanations are also fine, but should be cross-referenced to the
Traces of your test runs should appear immediately after the listing of
the program being tested.