The official Kapendev style guide for D. This guide should be used as a reference, not as a hard rule.
- Prefer using
//instead of/* */ - Prefer ending comments with a
. - Prefer using
///for documentation comments - Comments are always above attributes and functions
- Use
// --- Title Casefor splitting code into sections - Use
// +-- Title Casefor creating a section with an end. The section should end with// +-- - Use
// @-- Optional Titlefor attribute groups that use:
- Structs, classes and enums use PascalCase:
List,Arena,Rgba,GVec2 - Generic types are prefixed with "G" when the name without the prefix is reserved for a specific type:
Vec2->GVec2!float - Aliases use PascalCase or camelCase based on what they are pointing to
- Aliases to
typeof(this)are calledThis - Custom attributes use camelCase:
hiddenMember,requiredMember - Enum variants use camelCase:
none,some,topLeft - Templates use PascalCase or camelCase based on what they are pointing to
- Mixin templates use camelCase:
typed,runGame - Functions use camelCase:
findListCapacity,toForeignSlice - Variables use camelCase:
position,tileSize - Constants use camelCase:
pi,epsilon,white - Constants are prefixed with "default" + group when the name without the prefix is too generic:
defaultEngineTitle,defaultAsciiFmtArgStr - Internal names use underscore prefix:
_engineState,_swizzleN,_swizzleC - Prefer using one underscore in most cases
- Common temporary loop variable names:
i,j,k,x,y,z,n,c,e,index,item
- CSV, JSON, EOL, etc. are treated as regular names
- In PascalCase contexts:
Csv,Json,Eol - In camelCase contexts:
csv,json,eol
Organize members in this order:
- Variables
- Aliases
- Enums
- Structs and classes (implementation)
- Constructors (implementation)
- Methods (implementation)
With alias this being part of the variables,
and with @disable this(); being the first constructor (if it exists).
More information about the order of some of the above members is available in the next section.
Each module should:
- Start with header comment (copyright, license, etc.)
- Define the module name
- Import dependencies
- Define versions/configurations
- Define the module body
With the body following this order:
- Variables
- Aliases
- Enums
- Structs and classes (implementation)
- Functions (implementation)
Only excpetion to the above points are types that follow this pattern:
// NOTE: Writting `Attached!Camera(camera)` would look bad, so a function is used.
struct _Attached(T) {
T* _attachedObject;
@trusted nothrow @nogc:
@disable this();
this(ref T object) {
this._attachedObject = &object;
attach(*this._attachedObject);
}
~this() {
detach(*this._attachedObject);
}
}
/// Attaches the camera for the scope and detaches automatically.
/// Designed to be used with the `with` keyword.
@trusted nothrow @nogc
_Attached!T Attached(T)(ref T object) {
return _Attached!T(object);
}In this specific case it's fine to have functions after the struct definition and then continue with other structs or classes.
- About the variables section: the order of them should be mutable varibles -> immutable variables.
- About the enum section: the order of them should be single enums -> enum groups.
- Avoid cross-module dependencies
- Try to keep the module dependency count low
- Prefer big modules that include eveything instead of smaller modules that split things into specific groups
- Attributes and pragmas should always be on a different line than a function or type definition
- Prefer groupping attributes with
{} - Prefer using only one
:at the start of an implementation section (see structs, classes and modules) - Add a
// @--comment above every use of:inside the module scope - The
// @--comment can be skipped inside structs and classes - Function aliases should be inside attribute groups, even if it's only one function
- Preferred order of attributes and pragmas:
pragma(xyz) @safe nothrow @nogc @customAttribute - Never use the
pureattribute - Avoid writting code in an "attribute-oriented" style: don't always add
@nogcto a nogc function when it accepts a callback - Attributes should mainly be used for library code and not application code
- Avoid runtime asserts
- Be explicit about functions that assert:
getOrAssert - Use
assert(0, ...)and notassert(false, ...)