March 10, 2006
Background: I'm currently merging GDC-0.18.1 and GPhobos64

=== 1: auto ===
Use "auto" when ever reasonable possible,
doing so usually decreases the porting costs.

#
# auto x = someObject.foo();
#

instead of

#
# uint x = someObject.foo();
#

=== 2: size_t / prtdiff_t ===
Unless you require specific bit sizes use
size_t(unsigned) and ptrdiff_t(signed) for temporary
integers - doing so reduces the risk of truncated
array.length and can result in speedups.

Use std.stdint for special needs.

=== 3: length ===
Length is usually an unsigned integer.

#
# size_t len = anotherObject.length();
#

instead of

#
# ptrdiff_t len = anotherObject.length();
#

The difference between unsigned and signed might not be noticeable when using "normal" length, but will be in corner cases.

=== 4: cast and auto/typeof ===
Consider the use of "typeof" or "auto" if you are sure you have
to use a cast.

# auto x = cast(some_type) y;
#
# z = cast(typeof(z)) y;

instead of

# /* valid but likely typos */
# type_a x = cast(type_b) y;
# type_c z;
# z = cast(type_d) y;

=== 5: static if / assert ===
"static if", "pragma(msg, ...)" and  "static assert" are there for
a reason - use them to document and ensure that basic assumptions
of your implementation are valid at compile time.

e.g.:
# static if(real.max < double.max || real.dig < double.dig){
#     double someFloat;
# }else{
#     real someFloat;
# }

=== 6: unittest / invariant / in,out,body ===
Use unittest and invariants to test the sanity of your implementation at
runtime.

=== 7: version - else ===
Safeguard your version expressions.

# version(Windows){
#     import windows_module;
# }else version(linux){
#     import linux_module;
# }else{
#     pragma(msg, "unsupported OS");
#     static assert(0);
# }

instead of

# version(Windows){
#     import windows_module;
# }
# version(linux){
#     import linux_module;
# }

The second sample can lead to hard to track down bugs.

=== 8: version(X86 / AMD64 / ...) ===

You are usually not interested what CPU is used
but what the size of a pointer or "native int" is.

# static if(size_t.sizeof == 4){
#     // 32bit system
# }else static if(size_t.sizeof == 8){
#     // 64bit system
# }else{
#     // something other
# }

or

# static if((void*).sizeof == 4){
#     // 32bit system
# }else static if((void*).sizeof == 8){
#     // 64bit system
# }else{
#     // something other
# }

instead of

# version(X86){
# }else version(AMD64){
# }else{
# }

=== 9: _argptr / va_arg!() ===
Don't access _argptr directly but use std.stdarg.va_arg to
shield your code from the stack layouts of different architectures.

=== 10: trivia ===
This might sound trivial:

1) Use the right tool for your problem, don't try to find a problem
description that fits your tool (except for educational/comparative
purposes).
Yes, D might not be the best tool to solve your problem.

2) Design, documentation and testing(unittests, invariants, test suite)
don't matter - until maintenance kicks in.

Thomas