arul's views on
programming style
A.
The user
should be able to use the program easily, without needing the programmer
standing there next to the user:
An initial
message should be displayed to tell the user what the program does.
When any
input is expected, a message should be displayed before the input is
expected, informing the user clearly as to what input is expected and in
what format.
When any
input is given by the user, the input should be checked to see that it is
valid (for example, if the input is someone's age, it cannot be a negative
number). If the input is invalid, a clear error message should be
given that will help the user give the correct input. The user should be
given another chance to resubmit the input.
If command line arguments are expected in the program, the number of command line arguments actually given by the user should be checked. Each argument value given by the user should be checked to see if it is valid. If erroneous arguments or wrong number of arguments are given by the user, a usage message should be displayed, clearly informing the user what and how many arguments are expected.
Especially in the Unix environment, messages and errors should be displayed only on stderr/cerr. Only actual data should be displayed on stdout/cout. This is useful in piping the data output of one program to the input of another program.
B.
Another programmer should be able to
easily read, understand, and modify your program, without having to interact
with you:
Use meaningful names everywhere (variables, defines, procedures, files, directories, etc). Use names like i,j, k etc. for local counters only, and p etc. for local pointers within loops only. Use standard extensions for the file names (for example, always use .c for the C program files).
Use a standard naming syntax uniformly (e.g. use Upper case letters at the beginning of each part of the name (e.g. ReadInp). Use the same abbreviation everywhere (e.g. Fil for file).
Use indentation. (The statements within {} are shifted right by a certain fixed number of spaces.) Use a uniform indentation style. (The most common style is to have the { on a new line and at the same horizontal level as the previous statement ('for', 'if', 'while', etc.), all subsequent statements are shifted right, and then the } is at the same horizontal level as the {. Another style is to have the { at the end of the line that has the 'for', 'if', 'while', etc.. ) Use a uniform indentation amount (2,4, or 8 spaces). Use indentation amount of 2 spaces only if the programs have very deep nesting of indentation (for within for within for within for etc.). Either 4 or 8 spaces can be used for indentation usually.
Use horizontal and vertical white spaces appropriately. For example, leave an empty line between functions. Use blanks carefully in large expressions, so that the major sub-expressions are immediately clear visually.
Always use parantheses to make the precedence of operators clear in arithmetic expressions. Never depend on that particular language's definition of precedence of operators.
Use #defines (or 'const' in C++) for any numbers that you use in the program. Avoid numerals in the program. This is needed for two reasons. Firstly it tells the reader what that 29 actually is (for example, maximum size of that buffer). More importantly, the same value is usually used in different parts of the program (for example, in the definition of the array, and to check that the index has not overflowed the last element of the array), and a change in one place (the 'define') will automatically make the change in all the other places.
Prologue comments for functions.
Functions should be small ( say 5 to 15
lines of program lines, other
than declarations, etc ).
Parameters should be described through comments.
Never use global variables,
except in your very first few programs.
(If it can be justified that global variables are absolutely
necessary, try to hide them and access them only through a set of
functions. In C, this can be done by justify and use static in a
separate file accessed
through functions).
Use meaningful typedefs, instead of raw
data types, as far as possible.
Use multiple source files and multiple
header files, with appropriate breakup of modules.
No program lines in header files. Only #defines, externs, typedefs and function prototypes / class declarations.
Use make or .prj files.
Learn
to use the debugger meaningfully. Do not 'single step' except as a
last resort. Set breakpoints at the entry to each new function, and check
that the behaviour is okay till then. Usually one can identify the
function where there is a problem. Then, within that problem function,
set breakpoints at the entry to each new sub-function, and check where the
problem is.