Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
Styles and Guidelines
This page defines a set of coding styles and guidelines that are recommended to be followed when contributing to code changes in this repository.
File Names and Paths
- File names should be succinct, yet descriptive and should be able to reflect the meaning of the file. File names should be composed of alphanumerical character all in lower cases(in most cases), with words joined by underscores.
- Header files should end with the suffix
.h, while source files should end with the suffix
- All header files should be included in the
include/directory, and all source files should be included in the
Coding Styles and Practices
- Include guards should begin with
SNEAKER_, followed by the name of the file or class in capital letters, and followed by
_H_. For example, the header file that defines the
standard_alloc_policyclass has the include guard name of
- In most cases, include guards must start at the beginning of the file before any other macros, include directives and definitions. Also, they must be in the standard
Include directives must be listed in the following order, with each section separated by a blank line:
- corresponding header
- necessary project headers
- 3rd party libraries headers
- standard libraries headers
- system headers
Namespaces and Declarations
- Namespaces must begin with the most outer namespace of
sneaker, followed by an inner namespace for one of the main areas in the project, such as
io, etc. No third level namespaces are allowed.
- Class, struct and function declarations must be included in header files, under the proper namespaces. All definitions must be placed in source files.
- Use the keyword
explicitfor constructors that take one argument.
- Only do work related to initialization/destruction of resources inside constructors and destructors respectively. Do not throw exceptions in constructors and destructors.
- Implement copy constructor and assignment operator only if needed.
- Make a class support move semantics if it is expected that instances of that class are often passed as rvalues.
- Avoid multi-inheritance if possible, as it often introduces unnecessary code complexities and maintenance overheads.
- Nested classes should be avoided if possible, as they force tight coupling between components and introduce overhead over management of classes.
- Have the proper access modifier over class members.
- Only inline functions that are short and have constant time runtimes.
- Use the
constmodifier on member types, parameters, and function signatures where appropriate.
- Mark function declarations with the
throwkeyword to specify the types of exceptions that are expected be thrown from a function.
- Use structs only for passive data wrapper, otherwise use classes instead.
- Follow the RAII (Resource Allocation Is Initialization) idiom where possible, this helps reduce a lot of complexity associated with resource managements.
- Use smart pointers where there's complex delegation, sharing and relinquishment on ownership of resources. However, it's advised to use smart pointers from the standard template library or
- Have good comments and documentations at places where the ownership of resources are not obvious, or the ways resources are passed around are not clear. Specially, the places where a particular resource is initialized and destroyed should be mentioned.
- Every component introduced should have the associated tests implemented. Tests live in the top level directory
- Test files should be named with the name of the associated file, followed by either the suffix
- It's a good practice to include a line of comment at the top of the test file to specify which definition that this test is written for.
- Each test should have a test class defined, which inherits either directly or indirectly from
libgtest.a. A test class should define any test fixtures needed as members, and may have the
void TearDown()members implemented to do the appropriate setup and teardown work.
- Each test class may have one or more test cases associated. Each test case should be named with the prefix
Test, followed by a combination of words that form a sensical definition that can reflect the meaning of that particular test case. For example, a particular test case that tests the allocation of an allocator on empty memory should be named to something similar to
- Each test should have sufficient test cases to cover all cases of a definition implementation. It's advised to follow the 3-times rule of thumb of testing, which essentially means that the amount of code in the test should be at least 3 times of the amount of code in the actual implementation being tested.
- Commits that can only be considered to be pulled in into the master branch if all associated tests of a particular definition pass.
- Commit messages should be properly written. The first line of the message should be a short line of text that can succinctly describes the changes made. An additional commit body message can be included if needed. Commits with non-sensical or incomplete commit messages may be rejected.
- The first lines of commit messages must begin with a legitimate ticket/issue identifier in square brackets, followed by a short sentence. For example:
[SNEAKER-45] Implement Tarjan's Strongly Connected Graph Algorithm.
- Commits must have the correct author name and e-mail.
- Commits must be as atomic as possible, meaning they should only include the changes for a particular implementation or bug fix, and should not include anything unrelated.
- Commits should not include merged changes from other branches that are not already in
- If a commit is already being pulled into
master, do not amend that commit. Push a separate commit.