CS190 Coding Standards

Purpose

Everyone hates having to change their coding standards according to someone else's rules. However, for a large project like TheFORCE, some consistency is necessary so that everyone in a group can understand how others' code works. This document will attempt to be as flexible as possible, while mentioning some of the more obvious coding standards.

Standards mentioned here may be ones you use already, but they are mentioned here because they are more important for a group project of this size. Come talk to me if you dispute any of the standards.

In general, the cs32 coding standards may be considered for anything not mentioned here.

"I don't want to look at your C code..." - Header Files

Header files should be documented enough such that the classes they contain can be used without ever looking at the corresponding C file. This is one of the most important parts of the coding standards. I don't care how you implement your interface, as long as it does what you say it does. Consider this example:
// Get the function node identified by the name passed.
Node* getFuncNode(string name);
Though it gives some indication of what is going on, it leaves some unanswered questions. What happens if you name a function that doesn't exist, or encounter some other error? Who is responsible for managing the memory of the pointer returned? Try to leave no doubt on questions like these.
// Get the named function node, or return NULL if it doesn't exist.
// Do not deallocate the pointer returned; it is managed by this class.
Node* getFuncNode(string name);
Group comments if possible. It's a waste of everyone's time to say the same thing repeatedly:
// Get a function node, or return NULL if it doesn't exist.
// Do not deallocate the pointer returned; it is managed by this class.
Node* getFuncNode(string name);
// Get a variable node or return NULL if it doesn't exist.
// Do not deallocate the pointer returned; it is managed by this class.
Node* getVarNode(string name);
...
Where possible, make a statement about an entire class, or about a set of methods in the class. Avoid redundancy, but also add short clarification where needed.
// These accessors get the type of node that corresponds to the method name.
// if an error occurs, NULL is returned.
// Do not deallocate the pointer returned; it is managed by this class.
Node* getFuncNode(string name);
Node* getVarNode(string name); // variable
Node* getNumNode(int num);
...
Put logical spacing between functions.

Avoid useless comments. They just waste time!

string getName(); // get the name

"...but if I must, it should be readable." - C files

Ideally, there should be no method-level comments in a C file. These should all go in the header. If you use stubgen to produce C files, use a command-line option to produce less gaudy function headers. (e.g. -p)

Put comments every so often (e.g. every few lines) mentioning what your code is trying to do. Such comments should be denser for more complicated code, and less dense for obvious code.

Comment as you go.

Put logical spacing between sections of code.

Use assertions often. It is also helpful to comment assertions, in case they fail for someone else.

// if this fails, it means i was passed a function node without initializing
// it in the function library first.
assert(func_node->getNumArgs() != -1);

Filename Conventions

Use capital C and capital H for extensions.

main.C - for filenames containing a main, use all lowercase, e.g. foo.C is a test program.

FAnimator.H - external headers should be prepended by only the project abbreviation.

FAInterpreter.H - internal headers/C files should have project and module abbreviations, generally with a file for each class. For many small subclasses of one superclass, it is reasonable to put them all in the same H/C file.

libtfanimator.so - shared objects should be named according to the directory that you are working out of, and prefixed with "libtf". So, if you are working out of src/flarp, your shared object should be named libtfflarp.so. This is done to avoid conflicts with any system shared objects.

Variable Naming

These should all be pretty obvious, and are pretty much taken from the cs32 coding standards:
FAnimator - top level module interface
FAInterpreter - class that is part of a module
member_ - I don't care if you put your underscores before or after.
myMethod()
F_GLOBAL_CONSTANT
F_global_var
With one addition: FNodeList - STL typedefs should indicate what they contain, and should end in the name of the STL structure that they use.

Miscellaneous

Use include guards. Emacs generates these for you automatically.

Keep all lines safely under 80 columns. I think 70 is a safe number for line-length.


Keith Dreibelbis
Last modified: Fri Mar 19 08:03:50 EST 1999