Notes on writing and commenting programs

Contracts

Every function in your programs should have a contract. The contract explains what the function does, to the extent that
  1. Somebody who wants to use the function can read only the function contract and the function heading, and know everything necessary to make effective use of the function.

  2. If a competent programmer with a basic knowledge of the terminology and concepts of the program were given only the contract and the function heading, then he or she could write a correct implementation of the function.

A contract tells what needs to be known to use the function. It does not tell how the function works. It does not tell what the local variables are used for, why there is a loop, or anything like that.

A contract necessarily tells in what way every parameter affects the function. A contract must discuss every parameter. Always discuss parameters by name, never referring to a parameter called n, for example, as "the number".

If a function returns a value, the contract must explain what is returned.

A function must take credit or blame for the actions of any other functions that it calls. The contract for a function must tell the entire effect of a function, including what happens as a result of functions that it calls.

A contract does not tell how a function fits into the overall program. For example, suppose there is a parameter called n that is passed to function f. When f is used, suppose that n happens to be a number that was typed to the program by the user. That is, the actual parameter was given to the program by the user. When describing f, do not say that n (the formal parameter) is the number typed in by the user. The reason is that it is not function f that has interacted with the user, but some other part of the program. Function f has just been given a number, and it does not care where that number came from. In general, when describing a tool, avoid describing the details of what some other part of the program will do with this tool. Instead, tell what the tool does in general.

Contracts should be written in complete sentences with correct grammar and punctuation. That does not preclude the use of technical terms or mathematical notation. Just make the contact clear.

A contract should not be excessively wordy. Make the contract as concise and to-the-point as possible without sacrificing correctness or completeness.

Comments inside the body of a function

Comments inside the body of a function should be concerned with how the function works. Assume that anyone reading them wants to know the details of how it works, and is willing to read the code.

Avoid margin comments. Instead, use paragraph comments. A paragraph comment consists of a short paragraph describing what the next block of code does, and is followed by a short block of code. Indent the comments to the same level as the code that it describes.

Avoid throw-away comments that simply restate what the code says. Assume that the reader understands the programming language. Instead, describe the intent of a paragraph, and how it fits into the solution of the function.

Sometimes a function body begins with a paragraph that describes the algorithm that the function uses. That is fine. It is also often a good idea to give comments describing what variables are used for, but only if the comment is informative.

Writing functions

Whenever possible, write your functions so that they might reasonably be used in more than one application, rather than tying them to one application. That is, where it is easy to do so, make them general. If you find, for example, that you need a function that computes the fourth root of a number that you know lies between 1 and 2, write a general fourth-root function, not one that only works on numbers between 1 and 2. If you need to take the fourth root of A[i], write a general fourth-root function (taking a parameter x, say) rather than passing array A and index i to it. Make functions simple and sensible, and, wherever possible, general.

Use sensible variable names. Wherever possible, use descriptive names. But do not go to such an extreme that your variable names are too long for convenience.

Global variables

Professional programmers occasionally have use for global variables. Their use is discouraged, however, because they have been found to lead to a plethora of errors. For example, any function that uses global variables is non-reentrant, and that might make it difficult to use. Use of globals often causes functions to interfere in bad ways with one another.

You may use a global variable when it is appropriate. However, I insist that every global variable be accompanied by a clear paragraph describing, in detail, what it is used for and why it needs to be a global variable. If I disagree with the reasoning, I will grade you down.