Style Guide

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, i.e. using the existing style if you are modifying an existing code base. It makes it hard to read, as well as confusing. Generally, using 8 spaces is more readable, and does not rely on the text viewers rendering tabs the same way. Also, if you use 8 spaces 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 view.

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 your editor uses 8 spaces to show tabs.

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.