Start now, that way you won't have to unlearn bad habits.
Modularity means each part of the program is simple, not complicated. Each function does one thing well. If there are two things to do, write two functions. There are two main reasons for this rule. The first reason is that simple functions are easier; easier to write, easier to understand, and easier to debug. Once you define the single purpose of a function, you can code it, check it, and be done with it. A complicated function has many more ways to go wrong.
The second reason is that simple functions are more useful. You may later want to reuse a function that finds the date of Thanksgiving for a given year. It would be a nuisance if that same function also baked a pumpkin pie.
main() Must be Short: Do not put much code in main(). The main() function should be the top-level abstraction for your program. It should call a few functions that show the main structure of your program. Those functions should do the work or call their own helper functions to do the work. To repeat: do not put much code in main().
30-Line Rule: Your functions should be short: 30 lines at most. If a function exceeds 30 lines, it is doing too much. Break it into smaller functions.
80-Column Rule: Your code should fit on a compact window: 80 columns at most. We grade your assignment with one terminal window and one browser window side by side. We want your code to fit in a terminal window 80 columns wide.
Indentation Rules: Indent all functions, all loops, conditional blocks, and cases. It is acceptable to indent with tabs. Indenting by eight spaces makes the structure very clear, but four is acceptable. Two is not acceptable.
Good documentation should permeate your code. In particular:
File headers | Each file must have a header that describes the purpose of that set of functions, lists the public functions in the file, and offers any hints or warnings about using the set of functions in the file. |
Function headers | Each function must have a header comment
that describes the purpose of the function,
the meaning of each of its arguments,
the meaning of the return value,
the possible error conditions, and a brief
outline of the method the function uses to
do its work. You do not need to be wordy
here; clear, simple statements do the
trick.
For example: /* is_logname_valid(const char *s) * purpose: determine if string represents * a valid logname on system * args: string * rets: 1 if true, 0 if not * note: this function ignores case */ int is_logname_valid( const char *s ) |
Local Variables | The local variables must have names that describe their purpose. Each variable should also get a descriptive comment. |
Code Paragraphs | Each chunk of code in the function needs a brief description to explain where it fits in the flow of the function. Its role may make perfect sense to you at 4:30 am, but might not seem so clear to you a week later. Furthermore, explaining a piece of code helps clarify your logic. It is nicer to catch logic errors at the time you write the code than after several days of debugging illogical code. |
Sneaky Lines | C invites you to write clever, efficient
code. As you get used to the language,
you will find yourself writing code that
looks a little weird. When you feel that
twinge of cleverness, put a comment like:
/* yes, I mean =, it should not be == */ |