Browse Source

Add a code style guide

Panagiotis Christopoulos Charitos 5 years ago
parent
commit
0edd903e51
3 changed files with 231 additions and 3 deletions
  1. 3 0
      .gitattributes
  2. 8 3
      README.md
  3. 220 0
      docs/code_style.md

+ 3 - 0
.gitattributes

@@ -12,3 +12,6 @@
 *.ankimtl text eol=lf
 *.ankimdl text eol=lf
 *.ankipart text eol=lf
+*.ankiskel text eol=lf
+*.ankiankim text eol=lf
+*.ankicl text eol=lf

+ 8 - 3
README.md

@@ -10,7 +10,7 @@ AnKi 3D engine is a Linux and Windows opensource game engine that runs on Vulkan
 AnKi's license is `BSD`. This practically means that you can use the source or parts of the source on proprietary and
 non proprietary products as long as you follow the conditions of the license.
 
-See `LICENSE` file for more info.
+See the [LICENSE](LICENSE) file for more info.
 
 2 Building AnKi
 ===============
@@ -80,11 +80,10 @@ Alternatively, recent Visual Studio versions support building CMake projects fro
 - Visual Studio will automatically understand that AnKi is a CMake project and it will populate the CMake cache
 - Press "build all"
 
-
 3 Next steps
 ============
 
-This code repository contains **3 sample projects** that are built by default (`ANKI_BUILD_SAMPLES` CMake option):
+This code repository contains **4 sample projects** that are built by default (`ANKI_BUILD_SAMPLES` CMake option):
 
 - `sponza`: The Crytek's Sponza scene
 - `simple_scene`: A simple scene
@@ -99,3 +98,9 @@ On Linux:
 	$./path/to/build/bin/sponza
 
 On Windows just find the `sponza.exe` and execute it.
+
+4 Contributing
+==============
+
+There are no special rules if you want to contribute. Just create a PR. Read the code [style guide](docs/code_style.md)
+before that though.

+ 220 - 0
docs/code_style.md

@@ -0,0 +1,220 @@
+This document describes the code style of AnKi 3D Engine.
+
+
+Comments
+========
+
+All comments are C++ like:
+
+	// Some comment
+
+And for doxygen comments:
+
+	/// @brief blah blah
+	/// @param blah blah
+
+Naming Conventions
+==================
+
+**Variables, functions and methods** are lower camelCase.
+
+	functionDoSomething(someVariableA, someVariableB);
+
+All **types** are PascalCase and that includes classes, structs, typedefs and enums.
+
+	enum MyEnum {...};
+	class MyClass {...};
+	using MyType = int;
+
+All **constant expressions** are SCREAMING_SNAKE_CASE and that includes enumerants.
+
+	constexpr int MY_CONSTANT = ...;
+
+	enum MyEnum
+	{
+		ENUMERANT_A
+	};
+
+All **macros and defines** should be SCREAMING_SNAKE_CASE and they should have an `ANKI_` prefix.
+
+	ANKI_ASSERT(...);
+
+	#define ANKI_MAX_SOMETHING ...
+
+All **template arguments** should start with `T`.
+
+	template<typename TSomething, typename TOther, U32 T_SOME_CONST>
+
+The **source files** are always PascalCase.
+
+	ThreadHive.h
+	MyShaderProgram.ankiprog
+
+All **function and method names** should form a sentence with at least one verb.
+
+	doSomething(...);
+	getSomething();
+	calculateSomething(...);
+
+**No hungarian notations** with 2 exceptions.
+
+- All member variables have the `m_` prefix.
+- All global variables have the `g_` prefix.
+
+C++ rules
+=========
+
+**Always use strongly typed enums**. If you need to relax the rules use the `ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS` macro.
+
+	enum class MyEnum : uint {...};
+	ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(MyEnum, inline);
+
+**Never use `typedef`** to define types. Use `using` instead.
+
+	using U32 = uint32_t;
+	using Func = void(*)(int, int);
+
+**Never use C-style casting**. Use static_cast, reinterpret_cast or const_cast for most cases and constructor-like cast for fudmental types.
+
+	Derived* d = static_cast<Derived*>(base);
+
+	uint i = uint(1.1f); // uint is fudmental type
+
+**Always use `constexpr`** when applicable. Never use defines for constants.
+
+	constexpr uint SOME_CONST = ...;
+
+**Never use `struct`** and always use `class` instead. Since it's difficult to come up with rules on when to use struct over class always use class and be done with it.
+
+	class MyTrivialType
+	{
+	public:
+		int m_x;
+		int m_y;
+	};
+
+**Avoid using `auto`**. It's only allowed in some templates and in iterators. auto makes reading code difficult.
+
+**Includes should always have the full file path**. This avoids issues with files of similar name. Non-AnKi includes follow AnKi includes.
+
+	#include <anki/util/Thread.h>
+	#include <anki/util/WeakArray.h>
+	#include <anki/util/Allocator.h>
+	#include <cstdio>
+
+**Never use public nested classes**. Only private nested classes are allowed. Nested classes cannot be forward declared.
+
+	class MyClass
+	{
+	public:
+		// NO!!!!!!!!!!!
+		class Nested {...};
+
+	private:
+		// It's fine
+		class Nested {...};
+
+		// Also fine
+		class
+		{
+			...
+		} m_myUnamedThing;
+	};
+
+Try to **use `explicit`** in constructors for extra safety. Don't use explicit on copy constructors.
+
+AnKi uses **const correctness** throughout and that's mandatory. Always use `const`. The only place where you don't have to is for function and method parameters.
+
+	uint doSomething(uint noNeedForConst)
+	{
+		const uint bla = noNeedForConst + 10;
+		return blah;
+	}
+
+**Access types in a class have a specified order**. First `public` then `protected` and last `private`. There are some exceptions where this rule has to break.
+
+	class MyClass
+	{
+	public:
+		...
+	protected:
+		...
+	private:
+		...
+	};
+
+Always **use AnKi's fudmental types** (U32, I32, F32, Bool etc etc). For integers and if you don't care about the size of the integer you can use the type `U` for unsinged or `I` for signed. Both of them are at least 32bit.
+
+	for(U32 i = 0; i < 10; ++i) {...}
+
+If you have to overload the operator Bool always use **`explicit operator Bool` operator** overloading.
+
+	explicit operator Bool() const {...}
+
+The use of **references and pointers** is govern by some rules. Always use references except when you transfer or share ownership where you should use pointers. Pointers are also allowed for optional data that can be nullptr.
+
+	// ptr is a pointer so you CAN NOT destroy it after a call to doSomething is done
+	// ref is a reference so you CAN destroy it after a call to doSomething is done
+	void Foo::doSomething(TypeA* ptr, TypeB& ref)
+	{
+		// Store the ptr somewhere
+		m_someMember = ptr;
+
+		// Won't store the ref
+		ref += ...;
+	}
+
+Always **use `nullptr`**.
+
+	void* ptr = nullptr;
+
+**Never use C style arrays**. Use the `Array<>` template instead.
+
+	Array<MyType, 10> myArray;
+
+**Don't use STL**. AnKi has a replacement for most STL templates. There are some exceptions though.
+
+- Can use `type_traights`.
+- Some from `utility` eg std::move.
+- Some from `algorithm` eg std::sort.
+
+Always try to **comment parts of the source code**. Self documenting code is never enough.
+
+Always use `override` or `final` on virtual methods and try to use `final` on classes when applicable.
+
+	class Foo final
+	{
+	public:
+		void myVirtual(...) override {...}
+	};
+
+Code formatting
+===============
+
+clang-format deals with code formatting. To format the whole source tree type the following in a terminal:
+
+	$ cd /path/to/anki
+	$ ./tools/format_source.sh
+
+If you need to format on Windows do the same from a WSL terminal.
+
+Some cases that are not handled by clang-format follow.
+
+**Always use curly braces** on single line expressions.
+
+	// NO!!!!!!!!!!!
+	if(something) doSomething();
+
+	// YES!!!!!!!!!!!!!!
+	if(something)
+	{
+		doSomething();
+	}
+
+Always place the **condition of a conditional ternary operator** inside parenthesis.
+
+	// NO!!!!!!!!!!!
+	a = b ? 1 : 0;
+
+	// YES!!!!!!!!!!!!!!
+	a = (b) ? 1 : 0;