List of conventions used in the project, plus just plain good practices. Not rules per se, most of the codebase doesn’t meet those standards.
- Are not abbreviated if it could make meaning less obvious -
- Are obvious from context -
int rotaterequires reading the documentation
- Obey same conventions as nearby names -
snake_case is preferred for consistency with most of the project’s code.
- Don’t add methods where a regular function in a namespace would work -
crafting::consume_tools(tool_list,Character &), not
- Don’t add both getters and setters if all they do is read/write a field - those are just disguised
- Getters without (public) setters are OK
protectedonly when there’s a clear reason for it
- Avoid pointers, instead use references,
std::optionalor even a function overload where possible
- Avoid using
std::tuplein headers, instead create a named struct
- Avoid using
enum classwould work
Try to avoid including headers from other headers. This negatively impacts compilation times (both
clean and partial builds), especially when the header in question is already big and widely used
npc.h, etc.), and frequently
pollutes source files with definitions they have no need to know.
Some tips here:
- Compiler doesn’t always need to know the whole definition of a class, a declaration may be enough.
Say, if in
vehicleclass is only ever used for a function argument of type
vehicle &- references are always of the same size regardless of what type they refer to, so compiler only needs to know there exists a type named
vehicle, not its internal details. Adding
class vehicle;declaration in
character.his enough in this case.
- It’s possible to use
pointer-to-implementationidiom for class members to remove the need for the definition, see
src/pimpl.hfor implementation and explanation. There are many usage examples in the codebase (mainly
game.h), but the overall idea is to replace class member with a pointer, and only require definition when accessing the member through pointer. This incurs a tiny performance overhead, but it’s unnoticeable in most cases.
- If you’re adding some functionality to a frequently included header, and that functionality is supposed to be used only in a few source files, consider creating a separate header instead. This way, your code won’t make it into dozens or hundreds of compilation units which don’t ever use it, and the compiler wouldn’t spend time to build it all these dozens or hundreds of unneeded times.
- Including system and std headers is OK, most of them are precompiled anyway.
- Including common “utility” headers (
coordinates.h, etc.) is OK, those are already extensively used in many headers and source files, so not including them makes too little impact to warrant the inconvenience.