Coding Style

From ATIRE

Jump to: navigation, search

Contents

About Coding Styles

One of the most hotly debated topics of discussion in any project is the coding style. Many weeks are lost to debates about CamelCase, Hungarian Notation, and the placement of brackets. Luckily the core of ATIRE was developed by one person following one style.

The ATIRE coding style rule is simple, follow what is already there and break rules only when necessary. That said, below are the guidelines.

Files

  • The C and C++ file extension is .c
    • There is no common agreement in the correct file extension for C++ with some compilers preferring .cxx while others prefer .C or .c++. Consequently most compilers have a command line switch to say "this is a C++ file". For consistency an arbitrary decision has been made to use the .c file extension
  • The header file extension is .h
    • Again, this is an arbitrary decision.

Classes

  • Every class starts ANT_
    • This had been chosen over namespaces because it makes all declarations explicit.
  • Every class goes in its own source code file named after the class but without the ANT_
    • Putting each class in its own file Meeks it easy to find the sourcing code of any class. There is no point in including the ANT_ in the file name as all classes start with the same prefix.
  • Clases should be used rather than structs
    • In C++ there isn't much difference between a class and a struct, except that it is necessary to explicitly declare the scope. Doing so makes the code clearer and so classes are preferred over structs
  • Embeded classes are allowed but discouraged.
    • That is, you are permitted to declare a class within a class, butif you are doing this there should be some good reason it isn't a public class. That said, it it is a public class that only the outer class uses then the declaration in the class header file can be made faster using a class forward declaration and only including the second classes declaration in the .c file.

Templates

  • Templates use is discouraged unless necessary.
  • Template meta-programming is stringly discouraged unless there is no other way to solve the problem (which is unlikely).
    • There are two reasons for this. The first is portability, the second is readability.
    • The C++ standard does not allow for many levels of recursion even if your compiler does, this leads to problems porting the code to alternative compilers, which leads to compiler lock-in, which reduces the number of platforms that can be supported, which is bad.
    • The ATIRE source code is written so that it can be read and understood by someone familiar with C++, not someone who is fluent in C++. Template meta-programs, although standard, are not in common use except by the fluent. As such they decrease the readability if the code by many potential contributors (university students and hobbiests).
  • The C++ standard template library should not be used unless necessary
    • The C++ STL is not as standard and portable as you might think. New versions superseded old versions which results in old classes being deprecated. An example is the ostrstream class being replaced with ostringstream. In an effort to future-proof the code base use of the STL is strongly discouraged.
  • Use of boost is currently not permitted.

Naming Convention

  • Use long descriptive identifier names
    • The use of long descriptive identifier names makes the code easier to read and to search with standard command line tools such as grep. In order to increase the uptake of the code base and to increase readability, the code should be as self documenting as possible. Long variable names help with this goal.
  • Use of i, l,and o are forbidden as identifiers
    • Quite simply, these are indistinguishable from 1 and 0.
  • Names are lowercase separated with underscores (unless formal acronyms)
    • There were several options here including camel case and Hungarian notation. In my opinion camel case looks lucky. Hungarian notation makes it hard to abstract a variable's type from its name and difficult to change the name of a variable.
  • Class names start ANT_ and are not in a namespace
    • This is historic and a hangover from the days before namespaces. It also labels the classes as coming from the ATIRE codebase.

Comments

  • Every method has a block comment above it identifying the full name of the routine.
    • These comments have two functions: first they are navigational; and second they provide a location to comment the purpose of the method (which should be obvious from the method name, thus making the comment navigational only).
/*
   ANT_EXAMPLE::HELLO()
   --------------------
*/
void ANT_example::hello(void)


  • Inline comments are block comments
    • The usual reason for not using block comment is that you cannot block comment a code block containing a block comment. The solution to this problem is to wrap such blocks in an #ifdef NEVER block.
/*
   This is a block comment.  Block comments are indented at the same level as the code
   And the text withing the comment is tabbed in one more layer.  They are blocks
   And they look liked blocks. There is no column of stars at the left or right.
*/
  • // comments are permitted
    • End of line comments should be used to comment the end of a line of code (where necessary). If the comment is a block comment then use the block comment style.

Dead Code

  • Remove all dead code when no longer needed
    • Dead code decreases the readability of the main code base. It can have bugs in it. And it is usually in the. Versions control repository. If it is not in the repositories and you think you will need it later the put it in the repository then remove it from the main code base.
  • Remove Diagnostics after use
    • Diagnostic code is of no value once the code is reliably working. It should be removed in order to decrease the complexity of the remaining code base. Always remember that diagnostic code can have bugs in it.
  • ANT_class::text_render()
    • It is legitimate to have a member function in a class that print out the state of the class. This might be used for diagnostic (or other) purposes. For convenience sake, that method is called text_render(). It can optionally take parameters.
  • Use #ifdef NEVER to temporarily kill code
    • Notwithstanding the removal of dead code, temporarily dead code should be removed using #ifdev NEVER because that way you don't need to worry about nested comments. You do need to worry about nested #if statements, but they are easy to spot.

Lines of code

  • One line of code takes one line
    • The convention to currently have drawn the most debate is that a line of code should take only one line. This really only applies to if, for, and while statements, but they do not get wrapped in the source code. This is for several reasons, but the strongest of these is that if your editor allows long lines then the code is easier to read. That is, the overall structure of the code is easier to read even though the individual line is not. It's a trade off between block level comprehension and statement level comprehension.
  • enums may be split over multiple lines
    • aAn exception to ithe rule above. If you do this then put each constant on a separate line
  • allow ? yes : no;
    • this syntax is permitted.

Blocks of Code

  • Whitesmiths style
    • The Wikipedia article on indent style http://en.wikipedia.org/wiki/Indent_style describes the advantages and disadvantages of many different C/C++ styles. The Whitesmiths style is used for several reasons, including a Pascal heritage.
  • Don't indent the method block
/*
   ANT_EXAMPLE::HELLO()
   --------------------
*/
void ANT_example::hello()
{
puts("Hello World");
}
    • Less of a problem today than in the past, but screen realty is a premium, especially horizontal realty. There is no point on indenting every line of code. Consequently, the first block of a routine should be flush left.
  • else if is allowed
    • The wikipedia article discusses breaking else if into an else and an embedded if. This should only be done when it adds clarity to the code as otherwise it results in high indent levels.
/*
   ANT_EXAMPLE::HELLO()
   --------------------
*/
void ANT_example::hello()
{
if (three_state < 0)
   puts("-ve");
else if (three_state == 0)
   puts("0");
else
   puts("+ve");
}
  • Don't use unnecessary {} pairs
    • That is, if you have a one line if or a one line for then do not put in unnecessary curly braces. They just clutter the code and take screen realty.
  • Explicitly mark empty blocks with comments
    • Avoid empty blocks of you can. Re-write the for as a while. Re-write the if in the negative. Sometimes this cannot be done due to compiler warnings. In this case explicitly comment the block as empty because it makes it so much easier for any future reader of the code
  • Avoid inline variable declarations (declarations should be at the top of a method)
    • This is so that a variable's declaration can easily be found (it's at the start of the method) and so that the stack use of a method can easily be seen simply by looking at the method declaration. It is accepted that in C++ some objects can only be declared inline.

Class Declarations

  • Types then constants then variables then methods
    • Again from a Pascal heritage. Grouping these categories together makes it easier to read a class declaration and to find stuff. If, for example, you know it's a method then it'll be with all the other methods and not mixed in with Constants and types.
  • Private then protected then public
    • This decision is arbitrary, some argue for public stuff first because that is what you see when you open a source code file, but to others it just makes more since to declare the class and then list the public interfaces. The source code uses the latter.
  • Public constants before public methods
    • To reiterate, declare all constants before any methods. So, private constants then protected constants then public constants then private methods then protected methods then public methods. Yes, this does mean the public interface is not all in one place, but there should really only by methods and constant exposed, all access to variables should be via set() and get() methods.

Eclipse Users

Media:Andrew_Style.xml