Browse Source

doc: Adding coding style guide

Closes #279

Co-authored-by: Sam Edwards <[email protected]>

[skip ci]
rdb 2 years ago
parent
commit
e3f73f37f6
1 changed files with 200 additions and 0 deletions
  1. 200 0
      doc/CODING_STYLE.md

+ 200 - 0
doc/CODING_STYLE.md

@@ -0,0 +1,200 @@
+Panda3D C++ Style Guide
+=======================
+
+Rather than try to justify every decision made, this document attempts to be as
+at-a-glance as possible.  Examples provided where necessary to illustrate best
+practices.
+
+Note that this style guide is, for the most part, not very strict, and there
+are exceptions to every rule.  However, this guide does serve to illustrate the
+preferred style for the entire codebase.
+
+Naming conventions
+------------------
+
+- **Classes**: `CamelCaseFirstUpper`
+- **Filenames**: `lowerCamelCase.h`, `lowerCamelCase.cxx`
+  - Note, every header file must have a unique filename.  They are all
+    installed into the same path.
+- **Functions**: `lower_snake_case_without_prefix`
+- **Local variables**: `lower_snake_case_without_prefix`
+- **Member variables**: `_lower_snake_case_with_initial_score`
+- **Enum constants**: `SE_enum_value` (for an enum type named SomeEnum)
+- **Enum class constants**: `ENUM_VALUE`
+
+Indentation
+-----------
+
+Always use two spaces to indent.  Tabs should never appear in a C++ file.
+
+Access modifiers (`public`/`private`/`protected`/`PUBLISHED`) are never
+indented relative to the class they are in, and do not affect the indentation
+of the surrounding lines.
+
+Spaces
+------
+
+Always put one space after a control keyword, before the condition's
+parentheses.  Don't pad the inside of parentheses with spaces unless there are
+several nested parenthetical expressions and the extra spaces contribute
+substantially to readability.
+
+    if (x == y) {
+
+Don't place a space after a function name (declarations, definitions, or calls).
+
+    void function_name();
+    ...
+    function_name();
+
+Always place a space after each comma in an arguments list.
+
+    function_call(x, y, z);
+
+Always pad binary operators with a space on either side.
+
+    a || b
+
+Never end a line with trailing whitespace.
+
+Function definitions
+--------------------
+
+The recipe for a function definition is:
+
+1. JavaDoc comment describing the purpose of the function
+2. Function return value and class
+3. **At the beginning of its own line,** the function's name, followed by the
+   parameter list and anything else necessary for the function's signature.
+4. Opening brace on the same line, not its own line.
+5. Single empty line before next definition.
+
+For example:
+
+    /**
+     * String documenting the function, in JavaDoc style.
+     */
+    void ClassName::
+    function_name(int x, int y) const {
+      ...
+    }
+
+    /**
+     * ...
+     */
+    ...
+
+If the function is a constructor with an initializer list, the `:` goes on the
+same line as the constructor name, and the initializers are listed *one per
+line*, indented by two spaces.
+
+    ClassName::
+    ClassName() :
+      _a("a"),
+      _b("b"),
+      _c("c")
+    {
+    }
+
+Empty function bodies in a .cxx/.I file still contain a single line break (i.e.
+to put `}` on its own line).  In a .h file, an empty function can be given as
+`{}`
+
+Braces
+------
+
+Always put an opening `{` on the same line as the statement that calls for the
+brace.  There is exactly one exception to this: constructors with initializer
+lists.
+
+    SomeClass::
+    SomeClass() :
+      _one(1),
+      _two(2)
+    {
+      if (_one < _two) {
+        ...
+      }
+    }
+
+Comments
+--------
+
+Comments should be properly-formatted English, with proper capitalization and
+punctuation rules.  There are two spaces between sentences.
+
+Note that `//` is preferred over `/*` except in some special circumstances.
+
+Except for commented-out lines of code, there should be a space between the
+first word and the `//`.
+
+    // The following line is commented out.
+    //if (value == 0) {
+
+Line limits and continuations
+-----------------------------
+
+Lines should be limited to 80 columns.  This is not a hard limit, and lines
+should not be wrapped if doing so hurts readability, except comments, which
+should always be wrapped.
+
+Continuation lines shall be aligned to the same column as appropriate, or
+indented two spaces otherwise:
+
+    if ((a &&
+         b) ||
+        c) {
+      ...
+    }
+
+When choosing where to break a line, these are the preferred places, from best
+to worst:
+
+1. If inside a comment, break the comment to as many lines as appropriate, but
+   only after moving the comment to its own line.
+2. After a comma in an argument/parameter list.
+3. After a binary operator (leaving the binary operator at the end of the line)
+4. In a function declaration, after the function's return type but before the
+   function's name. (Indented by two spaces.)
+5. In a log statement with `<<`, before a `<<`. (Avoid ending a line with `<<`)
+6. Around a string literal, at a natural word boundary, with a space left on
+   the previous line (e.g. `"This is a "` / `"continued string literal."`)
+7. After the `=` in an assignment operator.
+8. As a last resort, after the opening `(` in a function call.
+
+If none of these rules can apply cleanly, it is okay to have lines extend past
+the 80-column boundary.
+
+Alignment
+---------
+
+Avoid the temptation to align multiple assignments in consecutive lines of code.
+While it may look neater, it decreases the maintainability of the code.
+
+Asterisks and ampersands indicating a pointer or reference type should always
+be aligned against the name, and not the type:
+
+    Type *x, &y;
+
+Grouping
+--------
+
+Try to group logically-similar lines, separating them with a single blank line.
+
+Modern language features
+------------------------
+
+Panda3D is a C++11 project.  The use of the following modern language features
+is greatly encouraged:
+
+1. `nullptr` over `NULL`
+2. `std::move` and move semantics
+3. Range-based for loops
+
+Using `auto` can be okay, such as when storing an iterator, but consider
+creating a typedef for the container type instead.
+
+Avoid using `std::function` in cases where a lambda can be accepted directly
+(using a template function), since it has extra overhead over lambdas.
+
+C++14 and C++17 features should be avoided for now.