The goal of this document is to establish a common understanding among software contributors to D-Wave's Ocean software projects based on the code conventions and best practices used at D-Wave.
This document is intended to be a living document, and is not complete. Feedback is welcome.
A feature or bugfix is complete only when the code has been unit-tested. Part of the pull-request process is to test your branch against master, and so the more tests you provide, the easier the pull-request process.
When contributing to a D-Wave project, fork the repository using the Github fork button and work in a feature branch in your own repository. In your feature branch, commit and push often, you can always rebase locally to edit your commit history and make it readable. To start a discussion, initiate a pull request. The sooner you start the pull request, the better. This allows early discussion on your feature and saves time and effort when you are ready to merge. When you are ready to merge, notify the repository owner and they will merge your code in.
Follow the commit conventions described here:
- https://chris.beams.io/posts/git-commit/
- http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
TL;DR:
- Separate subject from body with a blank line
- Limit the subject line to 50 characters
- Capitalize the subject line
- Do not end the subject line with a period
- Use the imperative mood in the subject line
- Wrap the body at 72 characters
- Use the body to explain what and why vs. how
If your branch is long-lived, rebase off of master periodically.
If you're already familiar with Git, but rebasing is still scary, try this think like a Git guide.
The master branch in a dwavesystems repository reflects the bleeding-edge developments of the project. Significant old versions forked from master are kept in version branches. For example, we might keep version branches 2.x and 3.x while master tracks the latest 4.x version. We try to minimize the number of version branches kept alive/maintained.
Stable releases are tracked using tags. These tagged snapshots are deployed to PyPI after successfully passing the test cases during continuous integration.
- Variable naming should follow the well-known conventions of a language. Avoid uninformative or needlessly terse variable names.
- Code is read more often than written.
- Functions should do one thing.
- Early pull requests and code reviews.
- Early architecting/design. Code reviews can happen before any code has been written.
- Use a consistent character width of 120.
- Use 4 spaces instead of tabs.
- End all files with a newline.
Do a good job of commenting. Read this Coding Horror article.
Comments should add, not repeat: avoid repeating in English or pseudo-code what the code does. Rather, discuss what the block is trying to achieve.
Side effects should be visible on screen; if not in code, then in comments.
Remember, the best documentation is clean, simple code with good variable names. When this is not possible, you must use a comment to explain the purpose of a functional block.
Example:
The following code
# z must not be greater than 255. if z > 255: raise RuntimeError('z must be <= 255!')
would be much more informative as
# if z is greater than 255, this universe will collapse. See https://url.to.issue.tracker/IS-42 if z > 255: raise RuntimeError('z must be <= 255!')
or even better:
# See https://url.to.issue.tracker/IS-42 if z > 255: raise RuntimeError('z cannot be greater than 255, or this universe will collapse.')
As a baseline, follow the pep8 style guide for python.
All code should be both Python 2 and 3 compatible.
- Google docstrings convention (definition, example) on all public-facing functions. The
following are exceptions:
- For D-Wave extensions of third-party projects, we match the existing convention (e.g. the D-Wave NetworkX project follows NumPy conventions).
- Argument defaults are written "default=x" rather than "default x".
- Private functions should include some sort of docstring.
- If your module has more than one public unit, it should have a module docstring with a table of contents.
- The docstring for the
__init__
method goes on the class. - All docstrings should be parsable by the Sphinx documentation generation tool (i.e. reStructuredText) The sphinx theme should be readthedocs.
When starting a new C++ project, copy the .clang-format file included here.
Our style is based on Google (as opposed to LLVM, Chromium, Mozilla, or Webkit) with minor differences.
ColumnLimit
is set to120
, as specified in Coding Conventions.NamespaceIndentation
is set toInner
as a middle ground betweenNone
(Google) andAll
, such that every line in a file defining a namespace isn't indented, but nested namespaces are easily spotted.Various indent-width specifiers are scaled by a factor of 2 such that the base indent is
4
, as specified in Coding Conventions, instead of2
(Google). This is especially helpful for readibility in cases likeif (condition) { foo(); } else { bar(); }
as opposed to
if (condition) { foo(); } else { bar(); }
Favor the use of the optional braces for single-line control statements, which enhance consistency and extensibility.
Example:
Use the following format
if (a) {
return;
}
as opposed to
if (a) return;
This could potentially be enforced by clang-tidy
.
Our code follows Semantic Versioning conventions: major.minor.patch.
A change that breaks backwards compatibility must increment the major version. Anything below version 1.0.0 can break backwards compatibility.
If you are creating a repository, don't forget to include a README.rst
containing
a reasonable description of your project.