Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

Coding conventions

As Tango grows, we want the code to share common ground in coding style to make it easier to read. The conventions should also ensure that the code is written in the safest possible way, where it will not cause unneccessary performance problems.

General Considerations

  • All D source files must be saved with the .d extension, whereas D header files must be saved with the .di extension. Anything intended to reside in a library should be represented by a .di file, not .d
  • Make sure all D source files are saved in ASCII or UTF-8
  • Since much of the code will be used over several platforms, the type of newlines the files are saved with might cause problems. We're using svn:eol-style in an attempt to resolve this, see [SvnGuide].
  • Use CamelCase for all D Module names. This permits more flexibility in descriptive naming, which is an important aspect of good documentation. Traditional C module names are in lowercase as this seems to be more comfortable, and has the bonus of clearly identifying C from D modules.
  • Capitalize, or use CamelCase for all aggregate-types and for enum member-names.
  • Use the override keyword appropriately. This will help make the code more robust in the face of long-term changes.
  • The default visibility of methods, attributes, members, enums, structs etc, should be private. Expose only what's necessary.
  • Make all imports private by default. Consider exposing those which would be required to invoke the primary function of the given module; such as the arguments to public class constructors. This makes pedestrian usage simple, yet helps to reduce namespace collisions and actually makes the compiler run faster.
  • When using default argument values, try to order them such that common usage has the least knowledge required.
  • Avoid large numbers of parameters (6 and above?) where at all possible. If things start to get crazy, consider using a struct to gather related arguments instead; or try to partition the functionality.
  • Consider returning a value from all methods/functions. It's almost free! Call-chaining is one reasonable application of this idiom. If there's an overall idiom to Tango, it would probably be call-chaining.
  • Use of tabs within source-code is considered wholly inappropriate. Just say no.
  • Writing style is important, but we do not enforce one particular indentation style over another. If the code is deemed to be maintainable (by the review group), that will be the overriding factor. However, and with few exceptions, code that is unclear, obtuse, inscrutable etc. will likely not be as attractive in terms of library adoption.
  • The original contributor will be expected to maintain their code, as required, over a period of time.
  • License is BSD-style only at this time. We require adoption of the Tango license header, along with author names, copyright text, revision list: see Documenting the Code
  • Along with functions and methods, each struct, class, interface, or other aggregate should have some descriptive annotation. Each of these represent a good place to add short usage examples, using the ddoc "---" mechanism.
  • Ensure that only the expected interface is exposed by the API documentation.

  • Document each non-private enum-member, such that it will be included in the API documentation.
  • Never comment out code without duly noting in the source why, who and when.

GC Considerations

  • The Tango libraries are intended to be lean and efficient when it comes to resource usage. Thus, indisicriminate heap-activity is frowned upon. Try to avoid such activity by, for example, exposing a delegate-oriented interface as an alternative to serial array-concatenation.
  • Rationale: heap-activity incurs non-deterministic up-front costs, increases the overall GC load, and exposes mutex-contention in a multi-threaded environment. Please treat it with respect.

Multi Threading

  • Where appropriate, construct classes such that there is both a mutable and immutable variation. For example, a Uri or String class could expose an Immutable baseclass or Interface, which should be applied to relevant argument declarations. Immutable objects can notably increase both the robustness and simplicity of multi-threaded systems.
  • Document thread-specifics carefully. Where it makes sense, note whether a class is considered thread-safe or not.

Unittests

  • Wrap all unittests and unittest specific imports and/or code in debug (UnitTest) {} blocks. To compile these in, use the switch -debug=UnitTest in addition to -unittest. Rationale: library code is compiled alongside user-code, and if the user is trying to unittest their own stuff we don't want library tests getting in the way.