One part of all assignment marks in OS (and in many other subjects) is
style. We are quite pedantic about good style, and its cousins, readability
and maintainability.
In this document I outline common problems where students commonly lose
style marks. Note that good and consistent style makes it easier for you to
debug, as well as minimise the number of bugs in the first place. Most
style rules have been formed by programmers learning (often the hard way)
what causes problems.
- Repeated Code
-
Never clag (copy-and-paste) code! If the same code appears in
the same place twice it should be in one function called twice.
Even worse is clagged code with minor changes (ie changing one
variable). This is a perfect example of when a function could be
used.
Avoiding repeated code allows easier testing, and bugfixes only
need to applied to one place.
- Functions
-
Many students do not use functions. This often results in the
main function being hundreds of lines in length - this is
unacceptable. C makes it easy to declare and write functions (in
most cases the same as Java, often it is easier!).
Using functions allows you to reduce repeated code, and is a
major aid to debugging. Small functions can easily be tested and
manually be checked for errors.
Side effects in functions should be minimsed (none is ideal,
otherwise well documented).
Additionally each function should have a short comment describing
what it does, and its arguments and return values.
- Magic Numbers
-
Ask yourself: What does 4 mean? Is it 2 squared? Maybe its
1 << 2. Or is it a read permission bit on a UNIX file?
See a problem here?
Never use a number unless it represents that number. Always use
a symbolic representation of some sort. C gives you two choices -
either:
#define S_IRUSR 00400
enum { S_IRUSR = 00400 };
- Undocumented Functions
All functions should have a comment saying what they do. Names
should not be misleading. Also list side effects in the
comments.
- Appropriate use of Comments
Comment any code which is not immediately obvious. Comment
all global variables, comment all functions. Comments should always
document what you are doing, not how you are doing
it.
Do not put in obvious comments -
eg a++ ; /* Increase a
*/
as found in a previous years assignment.
- Long Functions
-
Keep Functions short and simple. Keep all functions as short
as possible. A good rule of thumb is that if you can't describe
what a function does in one sentence it probably should be split.
Additionally if it goes across multiple screens it should be split.
There are two possible exceptions, occasionally initialisation
functions can be long, also code which has a single long switch
statement.
- Shallow Code
-
Avoid deep nesting of control structures (if/while/for) in
functions. Beyond two levels of nesting becomes very hard to follow
(plus a third for error handling).
- Strange Constants
-
Constant values should be intelligent. Do not use 11 for true,
and 10 for false. 0 for true would also be stupid. You also do not
need to make all constants unique if they cannot be confused. For
instance the value of O_WRONLY and TRUE are the same - but they
rarely get confused.
- Macros
-
Don't use macros. There are a few cases when macros are okay,
but 99.9% of the time functions are a better choice. Never use
macros as a substitute for functions.
Note in assignments you can expect to lose marks for a badly
written (eg unsafe) macros.
- Names
-
Keep names short, simple, logical and appropriate. Globals
should be descriptive (and have a comment too). Local variables
should be short. Functions should also be descriptive. For locals
keep idiom in mind:
-
i, j for loop indices,
-
p, q for pointers &
-
s, t for strings.
- Be Liberal, Be Strict
-
Always be liberal in what you code/functions accept. How you
deal with illegal values is up to you, but you should not crash due
to an argument being set to NULL. The best response is to return an
appropriate error code.
On the same basis you should always make sure you follow
documented interfaces, standards and specifications exactly. Don't
rely on undocumented behaviour (no matter how well tested) - it may
change (and often does in autotesting).
- Indentation
Never mix styles in the middle of a file. It makes it hard to
read, as well as confusing. If you really want a hint to get good
marks use 8 space, as the text viewer in the mark system is
pretty poor, so making it really clear helps. Also if you use 8 and
you start running out of space you know you have too much nesting
going on. Additionally keep the width of your code <= 80
characters to make it easier to mark.
A good guide on indentation (and style in general) is the BSD
Kernel
Normal Form.
Also see the indent program.
If you use real tab characters make sure you editor uses 8
spaces.
- Warnings
There is no excuse for submitting code that generates
warnings. For gcc use -Wall to list them all. It is
also suggested to use -Werror to really make sure you
get them all
- The Little Tin God
Don't try to optimise your code by avoiding temporary
variables, or avoiding functions or similar methods. Thats the
compilers job.
However it is your job to use a O(1) algorithm instead of O(n)
algorithm, the compiler can't help you there. This is the only
optimisation you should worry about.