Difference between revisions of "Coding standard"

From OdaWiki
(General)
 
(23 intermediate revisions by 4 users not shown)
Line 1: Line 1:
 
==Overview==
 
==Overview==
Odamex relies on a coding standard to help keep consistency between subprojects, this also helps things like reduce bugs and also provides easy readability of the code.
+
Odamex relies on a coding standard to ensure continuity, this reduces bugs and provides easy readability of the code.
  
Some of the existing doom code in Odamex breaks these guidelines, which is exempt, unless you want to rewrite it!
+
==Requirements==
  
==General Requirements==
+
* Make logical changes in separate patches
 +
* Minimise the number of changes in each patch
 +
* Provide an off switch for every new feature
 +
* Do not submit things you cannot test (e.g. code for alternative platforms)
  
This is a list of general things that must be adhered to when you are:
+
==Code guidelines==
* An Odamex developer.
+
=== General ===
* A patch submitter.
+
Things you should definitely do in your code:
 +
* Include a GPL header at the top of any new files.
 +
* Write code that is clear and avoids being too "tricky".
 +
* Write code that is defensive and secure, don't make assumptions about inputs.
 +
* Write comments that are descriptive and are of reasonable size, without being overly verbose.
 +
* Maintain traditional naming conventions, for consistency.
 +
* Use <code>NULL</code> for null pointers, not <code>0</code>.
 +
* Add a [[test]] for every change (or an explanation of why this is impossible).
  
Rules:
+
Things you should definitely AVOID in your code:
* Do not break code, if it works, leave it, if it doesn't, fix it!
+
* Changing code that already works.
* Do not change formatting of code.  
+
* Precompiler macros.
 +
* Global variables; they can create problems elsewhere in code.
 +
* Variants (tagged unions); they can present a performance problem.
 +
* Passing non-trivial data structures by value; pass them by <code>const</code> reference instead.
 +
* Magic numbers; use <code>#define</code> or <code>const</code> in your code for fixed numbers, at the top of files.
 +
* Hungarian notation such as <code>intVarname</code>; it's just plan evil.
 +
* C-style <code>char*</code> strings; replace them with C++ [http://en.cppreference.com/w/cpp/string/basic_string std::string] where it is safe to do so.
 +
* C-style casts like <code>(int)</code>; use [http://en.cppreference.com/w/cpp/language/static_cast static_cast], [http://en.cppreference.com/w/cpp/language/const_cast const_cast] or [http://en.cppreference.com/w/cpp/language/reinterpret_cast reinterpret_cast] instead.
 +
* <code>goto</code>.
  
===Formatting===
+
=== Style Guidelines ===
 +
* Set your editor to use Unix line-endings (LF), not Windows (CRLF).
 +
* Use tabs for indentation and spaces for alignment [http://www.emacswiki.org/SmartTabs like so].
 +
** If this is done correctly, it does not matter what tab-width you use.
 +
* Use [http://en.wikipedia.org/wiki/Indent_style#Allman_style Allman] brace style: opening and closing braces go on their own line.
 +
* Use of braceless blocks is allowed.
 +
* Try to limit functions to a maximum size (like the amount that would fit on a monitor with a reasonable screen resolution).
 +
* Set your editor to strip trailing whitespace on save.
  
* If creating a new file, include a GPL header at the top of it, as seen in other files.
+
=== File Operations ===
* Code layout. (ANSI is preferable)
+
When using file i/o based functions, such as fopen() etc or filename string functions, there are some that are not provided, ie retrieving the length of a file, checking if a file exists or not.
* Descriptive comments.
+
* Comments of reasonable size. (not too big and not too small)
+
* Comment formatting. (in c/c++, either // for 1 liners or /* */ for multiple lines)
+
* Indentation to be of 4 SPACES, NOT Tab characters. (some editors have a feature which turns tab characters into spaces, like Code::Blocks)
+
* 80 line character limit, for devs with text-based editors.
+
* if you can, limit functions to a maximum size (like the amount that would fit on a monitor with a reasonably screen resolution)
+
  
===Code===
+
Thankfully, Odamex provides some internal functions for doing such. Be sure to check out '''m_fileio.h''' before writing your own, it may have already been implemented! If it isn't, write us a patch and send it in.
  
Things you should definitely AVOID in your code:
+
Some of the useful functions included are:
* GOTO's. (any sane programmer would not use these anyway)
+
* SDWORD M_FileLength(FILE *) - Returns the length of an open file handle
* Macros.
+
* Global variables. (they can create problems elsewhere in code)
+
* Variants. (tagged unions) - they can present a performance problem.
+
* Magic numbers. (use #define or const in your code for fixed numbers, at the top of files)
+
* Hungarian notation. (just plan evil)
+
* C style strings. (replace them with C++ types where it is safe to do so)
+
  
What you should strive for:
+
Filename operations:
* Defensive and secure coding practices.
+
* BOOL M_FileExists(std::string Filename) - Checks if a file exists or not
* Clarity of code.
+
* BOOL M_AppendExtension(std::string &Filename, std::string Extension, bool If_Needed = true) - Add an extension on to the end of a filename, If_Needed detects if Extension is in Filename, if it isn't, it is added
* Maintain traditional naming conventions, for consistency.
+
* void M_ExtractFilePath(std::string Filename, std::string &Destination) - Returns the path of a filename in Destination
 +
* BOOL M_ExtractFileExtension(std::string Filename, std::string &Destination) - Returns the extension of Filename in Destination
 +
* void M_ExtractFileBase(std::string Filename, std::string &Destination) - Returns the base name of Filename in Destination
 +
* void M_ExtractFileName(std::string Filename, std::string &Destination) - Returns the complete filename of Filename in Destination
 +
 
 +
Others include:
 +
* BOOL M_WriteFile(std::string Filename, void *Buffer, QWORD Length) - Creates/overwrites a file and writes a block of data to it.
 +
* QWORD M_ReadFile(std::string Filename, BYTE **Buffer) - Allocates a buffer using Z_Malloc and reads the data into it from a file, lifetime is PU_STATIC.
 +
 
 +
=== Memory Management ===
 +
If you need to use malloc(), calloc(), realloc(), free() functions. Use the '''macros''' located in '''m_alloc.h''', these are provided because they are much better when it comes to debugging code and such:
 +
 
 +
* M_Malloc(size_t Size)
 +
* M_Calloc(size_t Items, size_t Size)
 +
* M_Realloc(void *Pointer, size_t Size)
 +
* M_Free(uintptr_t &Reference)
 +
 
 +
A list of features these functions offer:
  
==See Also==
+
* The Size value can NEVER be 0, this prevents platform-specific behaviour.
 +
* M_Free uses a reference instead of a pointer, it still does the same as normal free(), but will NULL the address on return.
 +
* They will abort the program if their operation fails.
  
* none
+
=== Z_Zone Memory Management ===
 +
* Be aware that the all Z_Zone allocated memory is freed when the WAD changes
  
 
==External Links==
 
==External Links==
  
 
* [http://www.jwz.org/doc/tabs-vs-spaces.html tabs-vs-spaces]
 
* [http://www.jwz.org/doc/tabs-vs-spaces.html tabs-vs-spaces]

Latest revision as of 05:14, 4 July 2012

Overview

Odamex relies on a coding standard to ensure continuity, this reduces bugs and provides easy readability of the code.

Requirements

  • Make logical changes in separate patches
  • Minimise the number of changes in each patch
  • Provide an off switch for every new feature
  • Do not submit things you cannot test (e.g. code for alternative platforms)

Code guidelines

General

Things you should definitely do in your code:

  • Include a GPL header at the top of any new files.
  • Write code that is clear and avoids being too "tricky".
  • Write code that is defensive and secure, don't make assumptions about inputs.
  • Write comments that are descriptive and are of reasonable size, without being overly verbose.
  • Maintain traditional naming conventions, for consistency.
  • Use NULL for null pointers, not 0.
  • Add a test for every change (or an explanation of why this is impossible).

Things you should definitely AVOID in your code:

  • Changing code that already works.
  • Precompiler macros.
  • Global variables; they can create problems elsewhere in code.
  • Variants (tagged unions); they can present a performance problem.
  • Passing non-trivial data structures by value; pass them by const reference instead.
  • Magic numbers; use #define or const in your code for fixed numbers, at the top of files.
  • Hungarian notation such as intVarname; it's just plan evil.
  • C-style char* strings; replace them with C++ std::string where it is safe to do so.
  • C-style casts like (int); use static_cast, const_cast or reinterpret_cast instead.
  • goto.

Style Guidelines

  • Set your editor to use Unix line-endings (LF), not Windows (CRLF).
  • Use tabs for indentation and spaces for alignment like so.
    • If this is done correctly, it does not matter what tab-width you use.
  • Use Allman brace style: opening and closing braces go on their own line.
  • Use of braceless blocks is allowed.
  • Try to limit functions to a maximum size (like the amount that would fit on a monitor with a reasonable screen resolution).
  • Set your editor to strip trailing whitespace on save.

File Operations

When using file i/o based functions, such as fopen() etc or filename string functions, there are some that are not provided, ie retrieving the length of a file, checking if a file exists or not.

Thankfully, Odamex provides some internal functions for doing such. Be sure to check out m_fileio.h before writing your own, it may have already been implemented! If it isn't, write us a patch and send it in.

Some of the useful functions included are:

  • SDWORD M_FileLength(FILE *) - Returns the length of an open file handle

Filename operations:

  • BOOL M_FileExists(std::string Filename) - Checks if a file exists or not
  • BOOL M_AppendExtension(std::string &Filename, std::string Extension, bool If_Needed = true) - Add an extension on to the end of a filename, If_Needed detects if Extension is in Filename, if it isn't, it is added
  • void M_ExtractFilePath(std::string Filename, std::string &Destination) - Returns the path of a filename in Destination
  • BOOL M_ExtractFileExtension(std::string Filename, std::string &Destination) - Returns the extension of Filename in Destination
  • void M_ExtractFileBase(std::string Filename, std::string &Destination) - Returns the base name of Filename in Destination
  • void M_ExtractFileName(std::string Filename, std::string &Destination) - Returns the complete filename of Filename in Destination

Others include:

  • BOOL M_WriteFile(std::string Filename, void *Buffer, QWORD Length) - Creates/overwrites a file and writes a block of data to it.
  • QWORD M_ReadFile(std::string Filename, BYTE **Buffer) - Allocates a buffer using Z_Malloc and reads the data into it from a file, lifetime is PU_STATIC.

Memory Management

If you need to use malloc(), calloc(), realloc(), free() functions. Use the macros located in m_alloc.h, these are provided because they are much better when it comes to debugging code and such:

  • M_Malloc(size_t Size)
  • M_Calloc(size_t Items, size_t Size)
  • M_Realloc(void *Pointer, size_t Size)
  • M_Free(uintptr_t &Reference)

A list of features these functions offer:

  • The Size value can NEVER be 0, this prevents platform-specific behaviour.
  • M_Free uses a reference instead of a pointer, it still does the same as normal free(), but will NULL the address on return.
  • They will abort the program if their operation fails.

Z_Zone Memory Management

  • Be aware that the all Z_Zone allocated memory is freed when the WAD changes

External Links