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_pointer
s 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
.