ZestCode Styleguide
[!TIP] ZestCode is in the process of migrating to this new style; some older code may not yet be using this new style.
Maintaining a consistent coding style is important. It helps make the code more readable. ZestCode’s style guide is largely inspired by rustfmt.
General Rules
[!TIP] The clangd VSCode extension can be used to automatically format your code using the ZestCode styleguide
Some basic rules are as follows:
use fixed width integer types instead of
intorunsigned intdon’t use
int_fast_torint_smallest_tunless you document why its necessary
indent using 4 spaces, not tabs
no more than 100 columns per line
write tests for your code
always use
enum classoverenuma
structshould have only public member variables and no methodsdon’t use
typedef, useusinginsteaduse C++11 attributes instead of the older GCC attribute syntax:
__attribute__((...))only use macros as a last resort
For more details, see .clang-format.
File extensions
[!IMPORTANT] ZestCode is being rewritten in C++. No C files or headers may be added, but existing ones can be modified.
C source files will have the extension
.cC++ source files will have the extension
.cppC header files will have the extension
.hC++ header files will have the extension
.hppAssembly source files will have the extension
.sLinkerscripts will have the extension
.ldMarkdown documents will have the extension
.mdPython files will have the extension
.py
Naming Conventions
files, folders - snake_case
classes, structs, enums, unions, concepts, etc - PascalCase
enum members - PascalCase
edge case - names like
HTTPRequestshould beHttpRequst
functions - snake_case
variables - snake_case
member variables - m_snakecase (The `m` is intentional)
macros - SCREAMING_SNAKE_CASE
constexpr constants - SCREAMING_SNAKE_CASE
Documentation
Use Doxygen-style comments as shown in the sections below.
Enum-Level Comments
These should be placed immediately before the declaration of the enum.
/*
* @brief Short description of the enum
*
* Extended description of the enum goes here. This should explain general usage
* patterns for the enum.
*/
enum class MyEnum {
member_0, ///< short description of member 0 goes here.
member_1, ///< these can be omitted if it's painfully obvious
member_2, ///< what each is for, or if there are just so many of
member_3, ///< them it doesn't make practical sense to
member_4, ///< document them all.
}
[!TIP] In the above example, the comments describing each member of the
enumrun together and form complete sentences for effect. Please do not do this in your code!
Function-Level Comments
These should be placed immediately before the function prototype they are describing in a header file.
/**
* @brief Brief description of the function.
*
* An extended description of the function (if applicable).
*
* This function uses the following values of errno when an error state is
* reached:
* ERRNO_VALUE - Description of what causes this error
*
* @tparam T the type of the parameters
*
* @param parameter_name The parameter description
* @param other_parameter_name The parameter description
*
* @return The description of the return value, if this is longer than one line
* then it will wrap around under the return statement
*
* @code
* // example code here
* @endcode
*
* @see src/referenced_file.cpp
*/
Implementation Comments
Sometimes it is necessary to explain statement or series of statements. In this case, comment it! Prefer adding comments before the offending code, rather than next to it. Add as much documentation as you think is necessary, rather too much than too little.
For example:
// Program entrypoint. This is the first function that is run.
// It sets up memory, initializes libc, and then calls main
extern "C" [[gnu::section(".boot")]]
void _start() {
// Symbols provided by the linker script
extern uint32_t __bss_start;
extern uint32_t __bss_end;
extern uint32_t __sbss_start;
extern uint32_t __sbss_end;
// Don't try refactoring this code with stuff like std::fill or std::span.
// It's been tried before, and it causes UB.
// It's suspected that this is due to libc not being initialized yet.
for (uint32_t* bss = &__bss_start; bss < &__bss_end; bss++)
*bss = 0;
for (uint32_t* sbss = &__sbss_start; sbss < &__sbss_end; sbss++)
*sbss = 0;
// Initialize libc
__libc_init_array();
// call the main function, which sets up the scheduler
main();
}
[!TIP] commenting out lines is fine during testing, but should be removed when you mark your PR as ready for review!
Notes to Other Developers (Or Yourself)
When writing code, it can sometimes be useful to leave notes to other developers or to yourself in the future. Examples of these include:
// TODO: something that should be done// HACK: used to describe a particularly nasty way of solving a problem-- could be improved, but it works for now
While it is not strictly necessary to use these keywords in comments, they can be helpful - modern editors either highlight some of these keywords by default or have extensions that do. This can make certain comments stand out even more when developers are “grepping” the codebase (visually or otherwise).