DProgramming Guidelines
Difference (last change) (Author, normal page display)
Changed: 215c215
enum ColorMode? { GRAYSCALE, RGB }; // right |
enum ColorMode? { grayscale, rgb }; // right |
This is an attempt to create a coherent set of programming guidelines for Phobos, and perhaps more projects written using the D programming language. Most of Phobos doesn't conform to those guidelines. Either Phobos should be adapted to fit these, or the guidelines should adapt to Phobos. Probably a little of both.
![]() |
|
Variables
Variable names can be nouns, adjectives, or third-person verbs with an object.
string name; int accountNumber; bool dimmed; bool isCoherent;You may use modal verbs (such as "can" and "should") for boolean values that control behaviour.
bool shouldAnswer;
Types
Types name should contain one noun, which may or may not be qualified by preceding it with an adjective.
alias char[] MutableString; // right class Connection { } // rightTypes name should avoid redundancy.alias bool TrueOrFalse; // wrong (no nouns used) class Connect { } // wrong (no nouns used)
typedef int SerialNumber; // right class Socket : Object { } // rightHowever, it is fine to repeat the base type name in the derived type name if the derived type is only a specialization having the same function, and when it absence might encourage ambiguity or loss of intent:typedef int SerialNumberInt; // wrong ('int' unnecessarily repeated) class SocketObject : Object { } // wrong ('object' unnecessarily repeated)
class RemoteObject : Object { } // right class TcpSocket : Socket { } // right class ConnectAction : Action { } // rightclass RemoteThing : Object { } // not good class TcpConnector : Socket { } // not good class ConnectVerb : Action { } // not good
Derogation
Some standard types in C do not respect the rules enumerated above, but are still acceptable when they do not have their equivalent int D. Types such as `size_t` and `ptrdiff_t` are acceptable, but `wchar_t` should be avoided (use `wchar` or `dchar` instead).
Functions
General Rule
Functions should start with a lowercase letter; each following word should be capitalized. Avoid cryptic or hard-to-pronounce abbreviations in function names.
Action functions
Functions performing a transforming action should start with a verb.
void sort(List subject, Predicate lessThan); // right void moveTo(Rect subject, Point pos); // right void popFront(Range subject); // rightFunctions not changing the state of their arguments should use a past-participle or an adjective describing the returned value. They can also be nouns part of an implicit sentence "[noun] of [arguments]". Avoid making them properties.
List sorted(List subject, Predicate lessThan); // right Rect movedTo(Rect subject, Point pos); // right real sin(real angle); // right, reads "sine of angle"Functions evaluating a boolean characteristic should either start with the prefix "is" or have the property attribute. This makes them distinguishable from the above category.@property List reversed(List subject); // wrong
bool isSorted(List subject, Predicate lessThan); // right @property bool sorted(); // right
Accessor functions
Accessor functions can be nouns, adjectives, or third-person verbs with an object. They should have the @property attribute and return the value for the aspect they give you access to.
@property { string name(); // right bool enabled(); // right bool showsRegion(); // right }Setter and getter should have the same name. This allows the property syntax to be used when accessing the value:
@property { void value(string newValue); // setter string value(); // getter }Boolean properties do not need to start with "is", but may use "has" or a modal verb such as "can" and "should".// Property syntax: value = "hello"; string n = value;
@property { bool enabled(); // right bool empty(); // right bool shouldWait(); // right bool hasFuel(); // right }Avoid the unnecessary prefix "get" or "set" in front of function names. If you can't avoid them, don't use the @property attribute on them:@property { bool isEnabled(); // avoid, "is" is unnecessary bool isEmpty(); // avoid, "is" is unnecessary bool wait(); // wrong bool fuel(); // wrong }
enabled = true; bool e = enabled;
string getTitle(); // avoid void setTitle(string newTitle); // avoidYou should still use "get" for getters that return data through function arguments. Such getter functions should use "out" arguments to make clear which arguments return values. Use "set" for setters taking multiple arguments.@property string getTitle(); // wrong @property void setTitle(string newTitle); // wrong
void getStatistics(out int visitCount, out int[] visitPerDay); // right void setRatio(float widthFactor, float heightFactor); // rightYou should use modal verbs (such as "can" and "should") to clarify a meaning when necessary.
@property { bool canGoBack(); // right void canGoBack(bool flag); // right }When an accessor performs an expensive operation, it is often preferable to make it an action function through the addition of a verb:
uint computeAverage(); // right uint walkLength(); // right @property uint average(); // wrong if getting the average is expensive @property uint length(); // wrong if getting the length is expensive[Note: perhaps we should have a standard verb for this.]
Conversion Functions
Functions that convert from one type to a given target type should begin with "to" and be followed by the target type name. The type name should capitalized according to function capitalization rules:
string toString(Object o);The target type can also be expressed as a template argument. The function is then simply named "to" and the template argument carries the type.
T to(T)(Object o);
Overloading
Functions with the same name but different argument types are overloaded. Functions should be part of the same overload set if they all perform the same basic task using different arguments.
Function names should generally not contain information expressed by the type of their argument, this information is advertised in the function signature:
float truncate(float value); // right float altitude(Plane plane); // right, reads "altitude of plane"float truncateFloat(float value); // wrong float planeAltitude(Plane plane); // wrong float altitudeOfPlane(Plane plane); // wrong
Arguments
Function arguments are variables and should start with a lowercase letter and each successive word should start with a capital letter.
Arguments should have a clear, descriptive name of how they're going to be used. Avoid insignificant names such as one-letter names, or hard-to-decipher abbreviations.
void send(string message, IpAddress? destination); // rightvoid send(string messageString, IpAddress? destinationAddress); // wrong void send(string str, IpAddress? ip); // wrong void send(string m, IpAddress? d); // wrong
Bindings
When writing bindings for code in other languages or system functions, types, variables, constants, functions, and arguments can keep their original names:
extern (C): typedef int pthread_t; // acceptableWrapper classes and functions written around the direct bindings should follow the D conventions however.pthread_t pthread_self(); // acceptable int pthread_equal(pthread_t t1, pthread_t t2); // acceptable
class Thread { private pthread_t threadId; // goodUnless they are private, direct access to non-D functions should be kept in separate modules from the D wrappers. This clean separation avoid mixing programming styles the two equivalent APIs and their different programming styles.static Thread self(); // good bool opEquals(Thread other); // good }
Abbreviations
Common abbreviations (such as ASCII, PDF, RGB, or XML) are allowed, but should be capitalized as regular words:
byte[] toAscii(); // right char[] xmlSerialization(); // right class PdfDocument? { } // right enum ColorMode? { grayscale, rgb }; // rightbyte[] toASCII(); // wrong char[] XMLSerialization(); // wrong class PDFDocument { } // wrong