aboutsummaryrefslogtreecommitdiff
path: root/contributing.md
diff options
context:
space:
mode:
authorLoek Le Blansch <loek@pipeframe.xyz>2024-11-05 13:07:16 +0100
committerLoek Le Blansch <loek@pipeframe.xyz>2024-11-05 13:07:16 +0100
commit8839d428b76bb1bf4a5318751a78867d6ef7c4a2 (patch)
tree5815360a7cb88ea10fb0945a8e8549d5d61b8fb8 /contributing.md
parent777556306a5ab23d97d955701c93ae764673ddfe (diff)
parentb082e63fe81a3650599aef79e4d56d5afb2a731a (diff)
Merge branch 'max/code-style' of github.com:lonkaars/crepe
Diffstat (limited to 'contributing.md')
-rw-r--r--contributing.md349
1 files changed, 308 insertions, 41 deletions
diff --git a/contributing.md b/contributing.md
index 775119a..4c347bb 100644
--- a/contributing.md
+++ b/contributing.md
@@ -18,66 +18,333 @@
# Code style
- ASCII only
+
+ ```cpp
+ // Good
+ std::string message = "Hello, world!";
+
+ // Bad
+ std::string message = "こんにちは世界";
+ ```
+
- Class names are always singular
+
+ ```cpp
+ // Good
+ class Car {};
+
+ // Bad
+ class Cars {};
+ ```
+
- Explanatory comments are placed above the line(s) they are explaining
-- Source files should only contain comments that plainly state what the code is
- supposed to do
-- Explanatory comments in headers may be used to clarify implementation design
- decisions
-- Formatting nitty-gritty is handled by clang-format/clang-tidy (run `make
- format` in the root folder of this repository to format all sources files)
-- Header includes are split into paragraphs separated by a blank line. The
- order is:
+
+ ```cpp
+ // Good
+ // This function adds two numbers
+ int add(int a, int b) {
+ return a + b;
+ }
+
+ // Bad
+ int add(int a, int b) {
+ return a + b; // This function adds two numbers
+ }
+ ```
+
+- Source files should only contain comments that plainly state what the code is supposed to do
+
+ ```cpp
+ // Good
+ // Initialize the engine
+ engine.init();
+
+ // Bad
+ // Initialize the engine with default settings and prepare it for running
+ engine.init();
+ ```
+
+- Explanatory comments in headers may be used to clarify implementation design decisions
+
+ ```cpp
+ // Good
+ // This class handles the rendering process
+ class Renderer {
+ // This method initializes the rendering context
+ void init_context();
+ };
+
+ // Bad
+ class Renderer {
+ void init_context(); // This method initializes the rendering context
+ };
+ ```
+
+- Formatting nitty-gritty is handled by clang-format/clang-tidy (run `make format` in the root folder of this repository to format all sources files)
+
+
+- Header includes are split into paragraphs separated by a blank line. The order is:
1. system headers (using `<`brackets`>`)
2. relative headers NOT in the same folder as the current file
3. relative headers in the same folder as the current file
-- When using libraries of which the header include order is important, make
- sure to separate the include statements using a blank line (clang-format may
- sort include statements, but does not sort across empty lines).
-- All engine-related code is implemented under the `crepe` namespace,
- user-facing APIs under `crepe::api` (the folder structure should also reflect
- this).
+
+ ```cpp
+ // Good
+ #include <iostream>
+
+ #include "utils/helper.h"
+
+ #include "main.h"
+
+ // Bad
+ #include "main.h"
+ #include <iostream>
+ #include "utils/helper.h"
+ ```
+
+- When using libraries of which the header include order is important, make sure to separate the include statements using a blank line (clang-format may sort include statements, but does not sort across empty lines).
+
+ ```cpp
+ // Good
+ #include <iostream>
+
+ #include <boost/algorithm/string.hpp>
+
+ // Bad
+ #include <iostream>
+ #include <boost/algorithm/string.hpp>
+ ```
+
+- All engine-related code is implemented under the `crepe` namespace, user-facing APIs under `crepe::api` (the folder structure should also reflect this).
+
+
- `using namespace` may not be used in header files, only in source files.
-- Do not (indirectly) include private *dependency* headers in API header files,
- as these are no longer accessible when the engine is installed
-- Getter and setter functions are appropriately prefixed with `get_` and
- `set_`.
-- Doxygen commands are used with a backslash instead of an at-sign (i.e.
- `\brief` instead of `@brief`)
-- A singleton's instance is always accessed using a getter function that
- instantiates its own class as a static variable within the getter function
- scope, instead of storing the instance as a member variable directly:
+
+ ```cpp
+ // Good
+ // header.h
+ namespace crepe {
+ void init();
+ }
+
+ // source.cpp
+ #include "header.h"
+ using namespace crepe;
+ void init() {}
+
+ // Bad
+ // header.h
+ using namespace crepe;
+ void init();
+ ```
+
+- Do not (indirectly) include private *dependency* headers in API header files, as these are no longer accessible when the engine is installed
+
+ ```cpp
+ // Good
+ // api.h
+ namespace crepe::api {
+ void start();
+ }
+
+ // Bad
+ // api.h
+ #include "private_dependency.h"
+ namespace crepe::api {
+ void start();
+ }
+ ```
+
+- Getter and setter functions are appropriately prefixed with `get_` and `set_`.
+
+ ```cpp
+ // Good
+ class Car {
+ public:
+ int get_speed() const;
+ void set_speed(int speed);
+ private:
+ int speed;
+ };
+
+ // Bad
+ class Car {
+ public:
+ int speed() const;
+ void speed(int speed);
+ private:
+ int speed;
+ };
+ ```
+
+- Doxygen commands are used with a backslash instead of an at-sign (i.e. `\brief` instead of `@brief`)
+
+ ```cpp
+ // Good
+ /// \brief This function adds two numbers
+ int add(int a, int b);
+
+ // Bad
+ /// @brief This function adds two numbers
+ int add(int a, int b);
+ ```
+
+- A singleton's instance is always accessed using a getter function that instantiates its own class as a static variable within the getter function scope, instead of storing the instance as a member variable directly:
```cpp
class Bad {
- static Bad instance;
- Bad & get_instance() { return instance; }
+ static Bad instance;
+ Bad & get_instance() { return instance; }
};
class Good {
- Good & get_instance() {
- static Good instance;
- return instance;
- }
+ Good & get_instance() {
+ static Good instance;
+ return instance;
+ }
+ };
+ ```
+
+- Member variable default values should be directly defined in the class declaration instead of using the constructor.
+
+ ```cpp
+ // Good
+ class Car {
+ private:
+ int speed = 0;
+ };
+
+ // Bad
+ class Car {
+ private:
+ int speed;
+ Car() : speed(0) {}
};
```
-- Member variable default values should be directly defined in the class
- declaration instead of using the constructor.
-- Header files declare either a single class or symbols within a single
- namespace.
+
+- Header files declare either a single class or symbols within a single namespace.
+
+ ```cpp
+ // Good
+ // car.h
+ namespace crepe {
+ class Car {};
+ }
+
+ // Bad
+ // car.h
+ namespace crepe {
+ class Car {};
+ class Engine {};
+ }
+ ```
+
- Use of the `auto` type is not allowed, with the following exceptions:
- When naming the item type in a range-based for loop
- - When calling template factory methods that explicitly name the return type
- in the function call signature
+ - When calling template factory methods that explicitly name the return type in the function call signature
- When fetching a singleton instance
+
+ ```cpp
+ // Good
+ for (auto item : items) {}
+
+ auto instance = Singleton::get_instance();
+
+ // Bad
+ auto speed = car.get_speed();
+ ```
+
- Only use member initializer lists for non-trivial types.
+
+ ```cpp
+ // Good
+ class Car {
+ public:
+ Car() : engine("V8") {}
+ private:
+ std::string engine;
+ };
+
+ // Bad
+ class Car {
+ public:
+ Car() : speed(0) {}
+ private:
+ int speed;
+ };
+ ```
+
- C++-style structs should define default values for all non-trivial fields.
-- Declare incomplete classes instead of including the relevant header where
- possible (i.e. if you only need a reference or pointer type).
-- Template functions are only declared in a `.h` header, and defined in a
- matching `.hpp` header.
-- Where possible, end (initializer) lists with a trailing comma (e.g. with
- structs, enums)
+
+ ```cpp
+ // Good
+ struct Car {
+ std::string model = "Unknown";
+ };
+
+ // Bad
+ struct Car {
+ std::string model;
+ Car() : model("Unknown") {}
+ };
+ ```
+
+- Declare incomplete classes instead of including the relevant header where possible (i.e. if you only need a reference or pointer type).
+
+ ```cpp
+ // Good
+ class Engine;
+ class Car {
+ Engine* engine;
+ };
+
+ // Bad
+ #include "engine.h"
+ class Car {
+ Engine* engine;
+ };
+ ```
+
+- Template functions are only declared in a `.h` header, and defined in a matching `.hpp` header.
+
+ ```cpp
+ // Good
+ // add.h
+ template <typename T>
+ T add(T a, T b);
+
+ // add.hpp
+ #include "add.h"
+ template <typename T>
+ T add(T a, T b) {
+ return a + b;
+ }
+
+ // Bad
+ // add.h
+ template <typename T>
+ T add(T a, T b) {
+ return a + b;
+ }
+ ```
+
+- Where possible, end (initializer) lists with a trailing comma (e.g. with structs, enums)
+
+ ```cpp
+ // Good
+ enum Color {
+ Red,
+ Green,
+ Blue,
+ };
+
+ // Bad
+ enum Color {
+ Red,
+ Green,
+ Blue
+ };
+ ```
## CMakeLists specific