Log in | Back to darenet.org

Development Team/Coding Standards

In This Guide:

DareNET Development Wiki - Coding Standards

The following are a set of standards that should be adhered to when writing patches for ircd-darenet and services-darenet. Since these programs are based on the works of others (outside of the DareNET development team), it's reasonable to assume not all code will follow them. This, of course, will be rectified with time.

Comments


Comments can add immensely to the readability of a program, but used heavily or poorly placed they can render good code completely incomprehensible.

That being said, good places to put comments are:

  • a broad overview at the beginning of a module
  • data structure definitions
  • global variable definition
  • at the beginning of a function
  • tricky steps within a function

You should also strive to doxify your comments, where suitable.

Multiple Line

Multiple line comments should follow the C-style comment, for example: <source lang="c" line start=1 > /**

* This is a multiple line comment.
* - SecretAgent
*/</source>

Single Line

Single line comments should also be in the C style, for example: <source lang="c" line start=1 > /**< This is a one-line comment. - SecretAgent */</source>

Please avoid using C++-style single line comments (e.g. // Something here).

Additionally, the opening / of all comments should be indented to the same level as the code to which it applies, for example:

<source lang="c" line start=1 >if (fubar()) { /* * Fouled up beyond all recognition. Print a nastygram * and attempt to clean up. If that doesn't work, * die horribly, and try to crash the system while * we're at it. */ ... }</source>

Source/Header Files Organization


Use the following organization for source files:

  • includes of system headers
  • includes of local headers
  • global variables
  • functions

Within each section, order your functions in a 'bottom up' manner - defining functions before their use. The benefit of avoiding redundant (hence error prone) forward declarations outweighs the minor irritation of having to jump to the bottom of the file to find the main functions.

In header files, use the following organization:

  • type and constant definitions
  • external object declarations
  • external function declarations

Avoid having nested includes, ever. If you've ever tried to track a bug through the SunOS /usr/include maze, you'll understand why. Consider using the makedepend tools to help maintain your source file dependencies in your Makefile.

File Naming Conventions


File names are made up of a base name, peiod and suffix. The first character of the name should be a letter and all characters (except the period) should be lower-case letters and numbers. Please try to keep the base name short. These rules apply to both program files and default files used and produced by the program. Browse the current repos for an idea of how things are currently done. Ask if you're unsure!

Suffix Conventions

  • C source files should end in .c
  • Python source files should end in .py

The following conventions are universally followed:

  • Relocatable object files end in .o
  • Include header files end in .h
  • Yacc source files end in .y
  • Lex source files end in .l

In addition, it is conventional to use "Makefile" (not "makefile") for the control file for make (for systems that support it) and "README" for a summary of the contents of the directory or directory tree.

Indentation


Tabs. Tabs. ONLY TABS.

Use a single tab for each level of indentation, for example: <source lang="c" line start=1 > int main() {

 if (condition)
 {
   code
 }

}</source>

Separation


Always put a space in between a keyword like if/while and the condition, for example:

<source lang="c" line start=1 >if (foo == bar)</source>

NOT

<source lang="c" line start=1 >if(foo == bar)</source>

Braces


Always put braces opening and closing blocks on separate lines, see the indentation example.

For example, place braces like this: <source lang="c" line start=1 > if (!(bp = malloc(sizeof (Buffer)))) {

 perror("malloc");
 abort();

} </source>

and NOT: <source lang="c" line start=1 > if (!(bp = malloc(sizeof (Buffer)))) {

 perror("malloc");
 abort();

}</source>

Variable naming


Length is not a virtue in a name; clarity of expression is. A global variable rarely used may deserve a long name, maxphysaddr say. An array index used on every line of a loop needn't be named any more elaborately than i. Saying index or elementnumber is more to type (or calls upon your text editor) and obscures the details of the computation. When the variable names are huge, it's harder to see what's going on.

Struct names should be in camel case with a leading capital letter, for example, "MyBagOfBones". Variable names can be either in camel case with a leading capital letter or alternatively all lower case, so long as the same naming convention is adhered to throughout. Constants and enum values should always be completely in CAPITALS and underscores may be used.

Use of char pointers


Whenever you use char pointers (char*, char**) try to use const equivalents. This is much safer and avoids ugly and dangerous casts.

Functions


Functions should be short and sweet. If a function won't fit on a single screen, it's probably too long. Don't be afraid to break functions down into smaller helper functions. If they are static to the module an optimizing compiler can inline them again, if necessary. Helper functions can also be reused by other functions.

However, we do realize that it is sometimes hard to break things down. Since functions don't nest, variables have to be communicated through function arguments or global variables. Don't create huge interfaces to enable a decomposition that is just not meant to be.

Linefeeds


Unix linefeeds only please. We do not like to see our screens covered in ^M.

Additionally, the maximum line width is 80 characters. If you are writing a longer line, try to break it at a logical point and continue on the next line with the same indenting. Use of backslash is okay; however, multi-line literals might cause less confusion if they are defined before the function start.

Portability


Always make sure your code is portable to all supported operating systems. Don't write code that only works on Linux. Test your code on all platforms or ask for help from other developers who have the platforms you want to test on.

External Dependencies


You must not use any dependencies that are not available as standard on all supported operating systems beyond libc, and whatever else is currently needed to build the ircd/services. If you absolutely must do so, you will need approval from the Development Manager first.

Profiling and Performance


It is one thing to assume that code performs bad, it is another thing to prove that it actually is. A lot of experienced programmers talk about 'premature optimization', and here is what it means: if you have a piece of code called once on start up that takes 10 seconds instead of one second to run, and a piece of code that takes 0.05 seconds to run when it should take 0.01, and it is called once per second, the second piece of code is the priority.

In other words, make sure that what you think is slow, and a performance problem in ircd-*/services-* actually is.

more to come, possibly...