Last year, Charles Calvert and Robert Kozak wrote an excellent article
about commenting techniques: "I
have a comment...". We see so many poorly commented programs that I
think this topic is important enough to address again -- slightly differently.
Most code in CodeCentral and even the VCL source modules distributed with
Delphi are not commented properly in my opinion.
When can we call a program properly commented?
It depends on who reads the code, and what is the intention of the code.
1. No one will read the source
We write these programs for testing a new feature of a programming
language tool, or calculating something quickly. These programs are usually
deleted after we learn the new feature or get the result of the calculation.
But even if we save them it is unlikely that we will use them again. Programs of this kind are not commented. Sometimes they live longer than we
expect, and we find them years after they are written and
wonder who wrote them so poorly, why they were written, and what on earth they
might do.
2. Only the author will read the source
These programs help us learn more complex things like database handling
or graphics. Such programs may perform complex operations, even if
the user interface is somewhat sketchy. Help files and additional documentation
is rarely made, and we must rely entirely on the comments. Programs that we write in our free time for just the pleasure of creating
them are
another in this group of programs. We often forget to comment these, thinking
that no one but us will see or use them. We think why should these programs be commented at all?
But, sometimes they have long lives, and writing comments helps us understand the workings
of the programming language. When we buy the next version of the programming
language tool these commented programs could help us learn the new features.
3. The source will be read by a team and will be maintained for more than
a year
These are the typical commercial programs, and are found everywhere. We can rely
on the skills of the team to follow common coding techniques, and comment only
those things that are uncommon. Additional documentation and help files usually
exist, though they may cover mostly the use of the program and not help
much in the maintenance. It often pays to keep a private help file, and place most of the explanation
there. The code will be more readable despite the reduced amount of comments,
and the explanations will be readily available via context-sensitive help. A typical example is the help file for a new component. A reusable component
with a context-sensitive help file is a valuable asset that will help when
generating a new project quickly, and help in maintaining an existing one.
4. The source is published and can be read by anyone
If we plan to publish the source either as a freeware, shareware, or part
of a commercial package, we must think that users of the program will read it
and form their own opinion about our programming skills. Every program
of this kind is a sort of reference work. We can assume that users who are interested
in the code are good programmers and know how to find information in help files
and additional documentation, so we do not have to rely entirely on comments.
However, we have to make allowances for programmers with different levels of knowledge
and backgrounds, and explain everything in detail. Help files are very good at
explaining the general structure and the intent of the code, while comments can
explain the finer details. There is another advantage of commenting the program well: if users understand
the way program works they might be able to help in improving it and finding
bugs.
5. Example code for articles or books
These are the most critical programs of all, because they will be read by people
who do not understand every aspects of the program, and may not be able to use
the information provided separately. Here we have to explain how the program
works and why, often repeating with different words what is in the help
file. We have to be very careful to balance the information we give in comments, in
printed or electronic documentation, and in help files. If we
rely too much on information provided elsewhere, the code will be difficult to
read. On the other hand, if we write everything in the comments it will bury the
code and give the impression that these programs are too complicated.
Categories of comments
Explanation of tricky code
We cannot always avoid using tricky code. In time-critical parts of
the program we may have to resort to machine-dependent tricks and even to the
use of assembler. The good news is that usually only a tiny portion of the code is time-critical,
so commenting
every line is not really a burden.
If it is
possible to rewrite the code in a less tricky manner, that may be worthwhile.
An example is the conversion of a 32
element long Pascal style set to a packed binary C record. Internally both are
stored as 32-bit integers, each bit corresponding to one element. The standard
conversion uses the "in" operator to test every bit in the Pascal set, and
sets or resets the bits in the C record one by one. It is 64 assembly instructions
long, it does not make any assumption on the way of storage and easily understandable
even without comments. The tricky way is only two assembly instructions long,
moving one doubleword to the other.
Markers
Markers are used as temporary notes to yourself or other programmers on your
team marking debug lines or unfinished code fragments. When the project is completed
these markers, and often the code they refer to, are deleted.
Separators
In the early days of programming files were short, compiled separately and
linked. A good rule of a thumb was to keep the file length under 100 lines.
Memory was small and editors were cumbersome. With the emergence of object-oriented
programming and the growing size of projects,
these rules no longer apply. Editors can handle any length file, compiling
is done in seconds, but programs are much, much bigger. Ten years ago a million-line
program was unthinkable, nowadays-even editors can be that big. Windows.pas
is only a header file but 3124 lines long and it is not overloaded with comments.
Usually a group of similar components and subroutines are kept in one file.
The file length is several thousand lines long. To manage files that big they are separated into sections by separator comment lines. For example the interface
is the first section, global object definition is the next, all the subroutines
of one object are in the following section, and the initialization/finalization
code is the last section. Different separator patterns can be used for even
finer resolution. Typical separator lines are identical-length comment lines full of -, =, #, *,
or other symbols.
Summary of the code
This type of comment summarizes how the code works. It allows someone not familiar
or interested in the details to scan through quickly. This type of comment is usually
placed before a block of instructions, or before a local subroutine. As programs
grow in length this comment can become more and more important.
Description of the code's intent
Description comments tell us how to use a subroutine or a component. The comment is
usually placed before subroutines, before objects, and at the beginning of the
file or section. A well-written description of a subroutine does not bother
us by telling how the subroutine works, it only lists the input and output parameters,
gives a short description of the function and possible side effects. A more detailed
explanation can be given in a help file, as is often the case with components, global objects and global subroutines.
Common questions
When shall I write comments?
While writing the program! It is wrong to wait until the completion
of the code. Comments can help while writing the program. And you may forget
to write them in the end, or worse yet, forget how some tricky part worked.
Even writing summary information and copyright messages after the project is
finished is not a
good practice. You know who the copyright holder is right from the beginning
-- why not start the file with it?
How shall I write comments?
The main rule is to write the comment in a way that does not interfere with the
reading and maintenance of the code. Writing separate comment lines before
each line is unnecessary, and makes the program unwieldy and difficult to follow.
The best place for comments is at the beginning of a subroutine, block
of code, or object definition. If you keep subroutines short, there is little
need for anything else. Endline comments are also useful to explain the intent of the code. I start
endline comments at position 81. This allows me to read the code and the
comments
separately, or read the code only and refer to the comments only for clarification.
Using XGA resolution and 8 point size letters about 120 characters/line is
manageable
and printable. Position 80 is almost always enough for the code, and the 40-character length is not too great
a restriction on endline comments. I prefer longer lines to using abbreviations.
Endline comments should give information that is not obvious from the code. If
you have nothing to add then don't.
Example
A freeware program written for publication
Multi-glyph controls
components are my freeware components, which I have written for publication
with the intention that they might be useful for learning advanced programming
skills. There are plenty of comments in the source explaining everything not
obvious, but most of the information for component users is provided in the
help file. The readme file gives detailed installation instructions, and contains
the usual copyright and licensing information.
I included the source of the help file to encourage programmers to create their
own help files, and tried to make it appear almost identical to Delphi help
pages.
Two HTML pages are based on this component package. One describes the component,
the other gives information about generating help files that integrate seamlessly
into the Delphi Open Help system. The first is mostly repeated in the enclosed
readme file and help file, while the second is maintained separately and references
the component only as an example of creating help files.
Written by Pintir Gabor
Szikesfehirvar, Krivanyi u. 15.
H-8000, HUNGARY
Tel: +36 30 9972445, Fax: +36 22 304326
Email: propix@mail.datatrans.hu
Pinter.Gabor@freemail.hu
Web: http://www.propix.hu
http://www.datatrans.hu/propix
Connect with Us