Last update February 21, 2010

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.

Table of contents of this page
Variables   
Types   
Derogation   
Functions   
General Rule   
Action functions   
Accessor functions   
Conversion Functions   
Overloading   
Arguments   
Bindings   
Abbreviations   

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 { }        // right

alias bool TrueOrFalse; // wrong (no nouns used) class Connect { } // wrong (no nouns used)

Types name should avoid redundancy.

	typedef int SerialNumber;        // right
	class Socket : Object { }        // right

typedef int SerialNumberInt; // wrong ('int' unnecessarily repeated) class SocketObject : Object { } // wrong ('object' unnecessarily repeated)

However, 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:

	class RemoteObject : Object { }  // right
	class TcpSocket : Socket { }     // right
	class ConnectAction : Action { } // right

class 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);                // 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"

@property List reversed(List subject); // 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.

	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
	}

// Property syntax: value = "hello"; string n = value;

Boolean properties do not need to start with "is", but may use "has" or a modal verb such as "can" and "should".

	@property {
		bool enabled();     // right
		bool empty();       // right
		bool shouldWait();  // right
		bool hasFuel();     // right
	}

@property { bool isEnabled(); // avoid, "is" is unnecessary bool isEmpty(); // avoid, "is" is unnecessary bool wait(); // wrong bool fuel(); // wrong }

enabled = true; bool e = enabled;

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:

	string getTitle();              // avoid
	void setTitle(string newTitle); // avoid

@property string getTitle(); // wrong @property void setTitle(string newTitle); // wrong

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.

	void getStatistics(out int visitCount, out int[] visitPerDay); // right
	void setRatio(float widthFactor, float heightFactor); // right

You 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); // right

void 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;                         // acceptable

pthread_t pthread_self(); // acceptable int pthread_equal(pthread_t t1, pthread_t t2); // acceptable

Wrapper classes and functions written around the direct bindings should follow the D conventions however.

	class Thread
	{
		private pthread_t threadId;   // good

static Thread self(); // good bool opEquals(Thread other); // good }

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.

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 };  // right

byte[] toASCII(); // wrong char[] XMLSerialization(); // wrong class PDFDocument { } // wrong


FrontPage | News | TestPage | MessageBoard | Search | Contributors | Folders | Index | Help | Preferences | Edit

Edit text of this page (date of last change: February 21, 2010 15:25 (diff))