DProgramming Guidelines
Difference (previous author) (Change, Edit, normal page display)
Changed: 1c1
This is an attempt to create a coherent set of programming guidelines for Phobos, and perhaps more projects written using the D programming language. <n>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 both.</n> |
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. |
Changed: 56c56,57
Functions should start with a lowercase letter; each following word should be capitalized. |
Functions should start with a lowercase letter; each following word should be capitalized. Avoid cryptic or hard-to-pronounce abbreviations in function names. |
Changed: 62,63c63,71
void capture(); // right void popFront(); // right |
void sort(List subject, Predicate lessThan); // right void moveTo(Rect subject, Point pos); // right void popFront(Range subject); // right Functions 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" |
Changed: 65c73
Function names shouldn't start with adverbs or adjectives: |
@property List reversed(List subject); // wrong |
Changed: 67,68c75
void mergeStructure(T other); // right void structuralMerge(T other); // wrong |
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. |
Changed: 70c77,78
Avoid using "do" or other verbs with little meaning. |
bool isSorted(List subject, Predicate lessThan); // right @property bool sorted(); // right |
Deleted: 72,73d79
void paint(); // right void doPaint(); // wrong |
Changed: 77c83
Accessor functions can be nouns, adjectives, or third-person verbs with an object. |
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. |
Changed: 79,81c85,89
string name(); // right bool enabled(); // right bool showsRegion(); // right |
@property { string name(); // right bool enabled(); // right bool showsRegion(); // right } |
Changed: 83c91
Setter and getter should have the same name. This allows the property syntax to be used: |
Setter and getter should have the same name. This allows the property syntax to be used when accessing the value: |
Changed: 85,86c93,96
void value(string newValue); // setter string value(); // getter |
@property { void value(string newValue); // setter string value(); // getter } |
Changed: 92c102
Avoid unnecessary "get", "set" in front of function names, as they get in the way of the property syntax: |
Boolean properties do not need to start with "is", but may use "has" or a modal verb such as "can" and "should". |
Changed: 94,98c104,109
string name(); // right void name(string newName); // right string getName(); // wrong void setName(string newName); // wrong |
@property { bool enabled(); // right bool empty(); // right bool shouldWait(); // right bool hasFuel(); // right } |
Changed: 100c111,116
Boolean properties should start with "is", "has", or a modal verb such as "can" and "should". This makes clearer the meaning of the flag. It is especially important when the name is also a verb (such as with "empty") in order to distinguish it from the action. |
@property { bool isEnabled(); // avoid, "is" is unnecessary bool isEmpty(); // avoid, "is" is unnecessary bool wait(); // wrong bool fuel(); // wrong } |
Changed: 102,104c118,119
bool isEnabled(); // right bool shouldEmpty(); // right bool hasFuel(); // right |
enabled = true; bool e = enabled; |
Changed: 106,109c121
bool enabled(); // wrong bool empty(); // wrong bool fuel(); // wrong bool fuelled(); // wrong |
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: |
Changed: 111,112c123,127
isEnabled = true; bool e = isEnabled; |
string getTitle(); // avoid void setTitle(string newTitle); // avoid @property string getTitle(); // wrong @property void setTitle(string newTitle); // wrong |
Changed: 114c129,130
You should still use "get" for getters that return data using function arguments (by reference or pointer), and "set" for setters taking multiple arguments: |
You 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. |
Changed: 116c132
void getStatistics(ref int visitCount, ref int[] visitPerDay); // right |
void getStatistics(out int visitCount, out int[] visitPerDay); // right |
Changed: 121,122c137,142
bool canGoBack(); // right void canGoBack(bool flag); // right |
@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: |
Changed: 124c144,147
When an accessor performs an expensive operation, it is preferable to prefix it with "calc" (abbreviation for calculate) to make the user aware of this: |
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 |
Changed: 126,127c149
uint calcAverage(); // right uint average(); // wrong if getting the average is expensive |
[Note: perhaps we should have a standard verb for this.] |
Changed: 135,144c157
If converting from one type to another is an expensive operation, it is preferable to use "convertTo" instead to make the user aware of this: string convertToString(Object o); The target type can also be expressed as a template argument. The function is then simply named "to", or "convertTo", and the template argument carries the type. string to(T : string)(Object o); string convertTo(T : string)(Object o); == Math Functions == |
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. |
Changed: 146c159
[should we allow some exceptions here? sin(x) comes to mind] |
T to(T)(Object o); |
Changed: 155c168
int altitude(Plane plane); // right |
float altitude(Plane plane); // right, reads "altitude of plane" |
Changed: 157,159c170,172
float truncateFloat(float value); // wrong int planeAltitude(Plane plane); // wrong int altitudeOfPlane(Plane plane); // wrong |
float truncateFloat(float value); // wrong float planeAltitude(Plane plane); // wrong float altitudeOfPlane(Plane plane); // wrong |
Changed: 165c178
Use names with clear, descriptive meaning of how they're going to be used, and avoid insignificant names such as one-letter names, or hard-to-decifer abbreviations. |
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. |
Added: 168a182
void send(string messageString, IpAddress? destinationAddress); // wrong |
Changed: 192c206
Unless they are private, direct access to non-D functions should be kept in modules separate from the D wrappers. This is to avoid mixing programming styles from other languages within D-style APIs. |
Unless 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. |
Deleted: 196,211d209
In general, abbreviations and acronyms should be avoided as their meaning may not be clear in all contexts and cultures. There is a narrow range of abbreviations which have a well-established legacy however you may use: [[table] Abbreviation, Meaning alloc , allocate alt , alternate avg , average calc , calculate deleg , delegate (note: `delegate` is a keyword in D) func , function (note: `function` is a keyword in D) info , information max , maximum min , minimum temp , temporary] |
Changed: 217c215
enum ColorMode? { GRAYSCALE, RGB }; // right |
enum ColorMode? { grayscale, rgb }; // right |
Deleted: 222d219
|
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