Dgame Styleguide
Dgame follows mostly the D style, but differs in a few things.
Braces
In contrast to the D style, Dgame is using the 1TBS / K & R indentation style, also known as the Java / Sun variation.
int example(int x, int y, int z) { if (x < foo(y, z)) { qux = bar[4] + 5; } else { while (z) { qux += foo(z, z); z--; } return ++x + bar(); } }
Naming conventions
- filenames: PascalCases
- packages & modules:
- public: PascalCase.
Example:module Dgame.Package.Example;
- internal: if abbreviation lowercase, otherwise PascalCase
- public: PascalCase.
- enum, struct, class, union: PascalCase
- function /method: camelCase
- member variable:
- public: camelCase
- private, protected, package: _camelCase
- template parameter: PascalCase (single letters are prefered)
- enum member: PascalCase
- constants: PascalCase
Example:enum MaxFrameRate = 30;
All names should only contain the characters [a..z][0..9]
.
Imports
The following order should be granted:
- std.* e.g. std.stdio
- others, e.g. derelict or other third party libs
- Dgame modules (except Dgame.Internal.* or Dgame.Window.Internal.*)
- Dgame internals
In a few cases they could be also declared as package but there are only few exceptions to make them public.
public, private, protected, package
If more than one function is affected these should be declared as labels (e.g. public:) on their own line.
If only one function is affected, they appear on the left side.
properties (@property
)
properties should only be used, if the method sets or gets a (few) variable(s). But never, if the method calls another method or did a (more) complex operation.
Indentation
Dgame uses spaces invariably, never tabs. A tabulator is equal to 4 spaces.
Declarations
const / immutable is used weherever possible, especially for temporary variables.
A common practise is to use const for (temporary) structs and immutable for (temporary) primitive types as e.g. int or bool.
pointer / ref / auto ref Parameter
- pointers should be used if your parameter is optional (so null is a valid value) of if your dealing with self allocated memory.
- ref should be used for lvalues
- ref const should be used for performance reasons *
- auto ref should be avoided, since it leads to template bloat.
* Since Dgame does not use auto ref, it is a common practise to pass structs up to 16 Bytes by value and all other by ref const.
Example #1
void test(ref SomeStruct abc) { // change abc or store the pointer }
Example #2
void test(ref const SomeBigStruct abc) { // use abc }
Example #3
void test()(auto ref const SomeStruct abc) { // abc can be both, lvalue or rvalue }Note: only templates accept auto ref
casts
Try to avoid casts if possible. If not, the new functional-style cast is prefered (if possible):
-
int(3.14) // good
-
cast(int)(3.14) // long, but ok
-
cast(int) 3.14 // bad
alias / typedef
The new alias style is always prefered:
-
alias Vector2f = Vector2!(float); // good
-
alias Vector2!(float) Vector2f; // bad
structs & classes
Dgame uses structs whenever possible. classes are only used if polymorphism is need.
classes and final
Since D is virtual-by-default, Dgame uses regulary final:
at the top of each class.
If that is not possible, take care that every method which is not meant to be virtual is declared with final
Attributes
Dgame takes care that as many attributes as possible are used. Therefore Dgame uses pure
, nothrow
and const
wherever possible.
Especially @nogc
should be used in almost all cases, since Dgame tries to avoid the GC wherever possible.
Instead of the GC, the internal modules
Dgame.Internal.d2c
and
Dgame.Internal.m3
are used. There are only a few places where the GC is involved internally.
Place attributes
Attributes appear as follows:
- Attributes with an @ like @nogc, @property, @safe etc. appear on the top of the method on their own line.
- pure, nothrow, const, immutable and return (DIP25) appear on the right side.
- final, override together with public, private, protected and package appear on the left side.
Example #1
@nogc @property void test() const pure nothrow { // do something useful }
Example #2
@nogc @property final void test2() const pure nothrow { // do something useful }
Example #3
@nogc @property override void test2() const pure nothrow { // do something useful }
Every Pull Request (PR) should follow these rules. If not, it will not be accepted.