Written by: | Rick Caudill |
Last Updated: | Dec 19, 2004 |
Overview
This document explains the coding style that is to be used in Syllable. This document should be followed when you submit any new code to the core components of the OS, including the kernel, appserver, and the various API libraries that are part of the core distribution.
NoteNote
Naming
All variable names and struct/class members should be constructed from one or more type prefixes, followed by a mixed-case descriptive name. The only exception to this rule is counter variables and other iterators typically used in loops.
Rationale: The prefixes are a great help when reading others' code (and your own a few moments after it is written). It also makes it easier to search for members and variables since they tend to be more unique.
Counter variables and other iterators don't have to follow the coding standards. It is legal to write:
Example2 {
3 DoStuff();
4 }
Type prefixes:
-
n
- Any integer type (char, short int, long, long long) -
v
- Floating-point types (float, double, long double) -
s
- Structures -
c
- Classes -
e
- Enums -
u
- Unions -
h
- Handles (variables that are never de-referenced, like file descriptors and message ports) -
f
- Functions (only used in conjunction with thep
prefix to build function pointers)
Qualifier prefixes:
-
p
- Pointer to -
a
- Array of
And, no rule without exceptions:
-
z
- Zero-terminated string
All variables should be prefixed with one of the type prefixesl. Examples:
2 float vScale;
3 struct stat sStat;
4 Rect cBoundary;
If the variable is a pointer or an array, the type prefix should be preixed with a qualifier:
2 float* pvScale;
3 struct stat* psStat;
4 Rect acRectangles[16];
In addition to the type prefix(es), all
class members should be prefixed with m_
to distinguish them from local variables in member functions. Structure
members should normally be prefixed with an abbreviation of the
structure name. This is not required, but since many structures have
matching member names, and structure members often match other variable
names, it is much easier to search for a structure member if it has a
prefix.
Global variables and module variables should have a g_
prefix. Global variables should (for obvious reasons) be very rare,
especially in C++ where there often are better solutions (like
singleton classes).
Member functions should have mixed-case names, while global function names should be all lower-case with words separated by underscores. Example:
Defines, macros, and enum items should have uppercase-only names with words separated by underscores. Example:
Indentation and Tab Size
We have come up with a good solution for indentation and tab size. Indentation of anything is one tab in size, and the tab size is whatever you want to make it.
Example Using Tabs2 {
3 printf( "a is 2\n" ); //one tab over
4 }
5
6 if ( a != 2 )
7 {
8 printf( "a is not 2\n" ); //one tab over
9 printf( "it might be 3\n" ); // one tab over
10
11 if ( a != 3 )
12 printf( "No, not 3 either\n" ); // two tabs over
13 }
Brackets
Code blocks start on a new line, and align with the beginning of the statement above. The only exception to this rule is a single statement when a code block is not required. See the above code listing for examples.
Switch/Case
Brackets should be at the
same indentation level as the switch
statement. Each case
label should be one
indentation level deeper than the switch
statement. The code for each case should be one indentation level
deeper than the case
label. Example:
2 {
3 case CRASH_AND_BURN:
4 SetFire();
5 Crash();
6 break;
7 default:
8 printf( "Unknown command: %d\n", nAction );
9 break;
10 }
Parentheses
There should NOT be any spaces between a function name and the opening parenthesis for the function parameter. For other constructs like for/while, switch/case, if, etc., you may include a space if desired.
Comments
Just keep in mind that the API documentation is generated with Doxygen. Write comments so that as much documentation can be automatically extracted.
Code Cleanliness
There is no standard for code cleanliness yet, but we suggest you use either GNU Indent or Artistic Style to clean up your code.
Header Files
The standard format for inclusion safeuards is: __F_(DIRECTORY FILE IS LOCATED IN)_(FILENAME)_H__
Examples:
-
__F_GUI_WINDOW_H__
would be the inclusion guard for /include/gui/window.h -
__F_STORAGE_FSNODE_H__
would be the inclusion guard for /include/storage/fsnode.h -
__F_CODEVIEW_CODEVIEW_H__
would be the inclusion guard for /include/codeview/codeview.h
Classes
As Syllable gets bigger and includes more and more classes, changes to those classes will inevitably break binary compatibility. Here are a couple of guidelines that we have come up with in our Sysiphean fight against this inevitability. Hey, every little bit helps.
All classes should have a separate class for private members, like so:
Example class using Private Member Class2 {
3 public:
4 Window( const std::string& cTitle );
5 ~Window();
6 private:
7 class Private;
8 Private* m;
9 };
10
11 class Window::Private
12 {
13 public:
14 Private()
15 {
16 m_cTitle = "";
17 }
18
19 std::string m_cTitle; // Holds the title name of the window
20 };
21
22 Window::Window( const std::string& cTitle ) : os::Looper()
23 {
24 m = new Private;
25 m->m_cTitle = cTitle;
26 }
27
28 Window::~Window()
29 {
30 // Do not forget to delete the private class.
31 delete m;
32 }
Note
Window
class.All classes should have five to ten extra virtual functions, even if they are all empty, so that adding a virtual function won't break compatibility. When you want to add another virtual method, start with the highest reserved method, and rename it to whatever you want. This way, you and everyone else will know that you added a new virtual method.
Empty virtual functions should be named using the form: __(class
abbreviation)_reserved(number)__
Example:
2 {
3 public:
4 Window( const std::string& );
5 virtual void __WI_reserved1__();
6 virtual void __WI_reserved2__();
7 virtual void __WI_reserved3__();
8 virtual void __WI_reserved4__();
9 virtual void __WI_reserved5__();
10 virtual void __WI_reserved6__();
11 virtual void __WI_reserved7__();
12 virtual void __WI_reserved8__();
13 virtual void __WI_reserved9__();
14 virtual void __WI_reserved10__();
15 };
Other/Miscellaneous Stuff
Using the keyword const
is taught early on in C++ programming classes. It is important because
it tells the programmer that the const
data cannot change. Declaring something constant is usually up to the
programmer, but the rule of thumb is that if the data shouldn't be
changed, then it should be declared constant. Examples:
2 void SetTitle( const std::string& cTitle );
3 bool GetSelected() const;
GCC 3.0 came with a more strict and more standard-like standard namespace, so here are a couple of rules that you have to follow.
You can declare the standard namespace completely:
You can declare the parts of the namespace you need:
2 using std::cout;
3 using std::string;
4 using std::endl;
You can put std::
in front of anything you need:
2 std::string cString = "Hello World";
3 std::vector < std::string > tList;
Questions/Comments/Problems
All questions, comments, or problems with this document can be e-mailed to the Syllable Development List.