Skip to content

Coding Style

Thanks for considering contributing to this project. Before you jump into the code, there are a few things we should discuss. This is a democracy, everything is open for discussion, but this is how everything has been done so far, and how things should continue to be done unless there's a good argument and a refactor.

Bazel

Bazel is our chosen build tool. There are several reasons for this this, including that bazel is the worst build tool, except for all the others. All code and dependencies should be managed through bazel, except for one-off scripts, that may be placed in the scripts file.

Docker

"It works on my machine" is not a valid excuse when working on larger products. As such everything should build, compile and test correctly on the provided docker container.

Testing Coverage

We use codecov.io as our testing platform. Acceptable coverage is defined at 80%+, although more would be encouraged. Contributions should not significantly lower this coverage.

Global Values as Constants

Perhaps one of the most contentious issues of this project is compiling constant values into the binary. This is done to ensure complete reproducibility for a given study. A given binary has the needed parameters which cannot be edited and thus are guaranteed to produce the same results. Large studies should ideally not change these values much, and making these values non-editable ensure that there is some reproducibility reliability in running experiments. For more on this see Protobuf as a configuration file.

Protobuf as wire format

When communicating information between nodes, consider changing your data to protobuf format before sending. They are not a perfect format, nor the fastest but are cross compatible with many systems, implicitly versioned, easily serialized to disk, work well with Bazel, and perform well enough at their intended job. A move to CaptnProto or FlatBuffers may be considered.

Protobuf as configuration file

Since the global values should be constants, it follows that there should be some reliable, easy to try method of holding on to different system types. As mentioned earlier, protobuf is cross platform, implicitly versioned- and typed which means they are a good form to record configuration files. Note that as we desire constants in our builds, we use the initial proto configuration to generate a header that can then be compiled into the rest of the program.

C++

new considered harmful

Refrain from using the new keyword unless coupled with absl::WrapUnique. For all other heap allocations, use absl::make_unique. Both of these can be used to create shared_pointers in addition to unique pointers.

Raw pointers considered harmful

Please refrain from using raw pointers e.g. int* variable unless absolutely necessary. In these cases, consider explicitly prefixing the variable as unsafe e.g. int* unsafe_variable. Note, that raw pointers can be used properly but, more times than not, lead to crashes. Use safe pointers wherever possible. Use references (prefer const int& variable) for other cases. If very low overhead, consider a clone. Finally consider using a raw pointer.

Private namespaces

All code should reside under the pd3 namespace.

Internal library namespaces as _namespace. These will not be added to the documentation and should be used for general helper functions. Helper functions to a particular library component should be placed in an anonymous namespace.

Python

C++ Binding

We use pybind11 for binding to C++. Basic utilities and helper functions may be written in python, but system level changes or calculations should be performed in C++. Wrapper classes are suggested for th generated pybind11 classes for a more user friendly interface to the C++.

Typing

Please attempt to follow typing guidelines for python3 and ensure that your code passes mypy tests.

Private attributes

Private attributes should be prepended with _. For instance _config suggests that config should not be directly accessible to the consuming user. Instead, write a property function that helps handle this interface.

Misc Naming Conventions

Miller Indices and Burgers Vectors

Refer to constant miller indices by mABC where ABC refers to the index for [A B C]. If an index must be distinguished with a negative, add a leading _ to denote this. For instance, given miller index [-A B -C] one would name their variable m_AB_C. For constant burgers vectors, take the same approach with the b prefix e.g b110. All burgers vectors should be assumed to preserve k(A + B + C) = 1. In the case that the magnitude of a burgers vector deviates from this, explicitly type this with bKmABC where k is the inverse scale. For instance, for a super [1 1 0] dislocation, we may denote as b1m110, while the regular full dislocation may be denoted as b2m110.

Shared pointers

For convenience, please retype std::shared_pointer<MyClass> as MyClass_, std::shared_pointer<const MyClass> as cMyClass_

Protobuf

Protobuf mirrors should be retyped as pMyClass and the respective pointers or shared pointers should be _pMyClass.