This guide lists C++ coding conventions/recommendations for use with WPILib-based robot programming. It is based on GeoSoft's, WPILib's, and conventions previously used in our code.
Conventions are grouped by topic, and each convention has an ID to make it easier to refer to. They are written using this layout:
S#. Short description
Example (if available)
Longer description and reasoning
The terms must, should, and can have special meaning. A must requirement must be followed, a should is a strong recommendation, and a can is a general guideline.
These non-C++ terms will commonly be used throughout the guide:
- camelCase: naming convention where the first letter of each word in a compound word is capitalized, except for the first word
- PascalCase: naming convention where the first letter of each word in a compound word is capitalized, including the first word
The goal of these conventions is to improve readability, which increases the maintanibility and quality of our code. Every specific case will not be listed, so use your own discretion. If you think something should look different as it is easier to read, then make it look different.
This section derermines how things should be named inside of code.
Indexer
, DriveLikeACar
speed
, turnRadius
Makes variables easy to distinguish from types.
kMode
, kTurnSpeed
mSpeed
, mDriveLeft
pDriveTrain
, mpDriveTrain
If a member variable is also a pointer, then it should be labeled as both (mp
)
getSpeed()
, drive()
This excludes Initialize
, Execute
, End
, and IsFinished
.
N4. Variables with a large scope should have long names, variables with a small scope can have short names.
Scratch variables used for temporary storage or indices and are best kept short. (like i
in a loop) A programmer reading it should be able to assume that its value is not used outside of a few lines of code.
This section determines how files should be organized.
F1. A class should be declared in a header file and defined in a source file, where the name of the files match the name of the class.
MyClass.h
declares the class, MyClass.cpp
defines the class, and MyClass
is the name of the class
commands/intake/LowerIntake
, commands/intake/RaiseIntake
, commands/shooter/StopShooter
This keeps related files together and the commands folder unclutered.
This desction determines how code should be formatted.
void Shooter::toggleServo() {
if (mHoodIn) {
extendServo();
} else {
retractServo();
}
mHoodIn = !mHoodIn;
}
Indentation is used to emphasize the logical structure of the code. Tabs are standardized, more efficent, and can be configured to display at any chosen width.
The use of comments about what the code does should be minimized by making the code self-documenting, like appropriate naming and an explicit logical structure.
However, the code can only tell a reader how the code works. You should also include comments that tell the reader what the code is supposed to do.
if (condition) {
// ...
} else {
// ...
}
L4. Conditionals with a single statement should be written on one line and without brackets, if it enhances readability.
if (condition) doSomething();
This makes it clear that the single statement is the only one in the conditional.
L5. Operators should be surrounded by a space character, excluding pointer and member operators. Commas, C++ reserved words, single-line comments, colons, and inline semicolons must be followed by a white space. Opening/closing parenthesis must not have a space after/before.
a = (b + c) * d;
doSomething(a, b, c, d);
if (condition) {}
for (i = 0; i < 10; i++) {}
// Comment
pObject = *object;
object.a = 2;
b = pObject->b;
std::shared_ptr<NetworkTable> table = nt::NetworkTableInstance::GetDefault().GetTable("limelight");
double x = table->GetNumber("tx", 0.0);
double y = table->GetNumber("ty", 0.0);
double v = table->GetNumber("tv", 0.0);
// Aim only if a target is found
if (tv != 0.0) aimTarget(x, y);
A logical unit is a set of lines of code that fit together logically and contextually. Small units of code can make sense by themselves, but combining them with surrounding code can make it confusing to read. This also allows you to clearly have a comment for a specific unit.
L7. Include statements must be at the top of the file. Library includes should use angled brackets and project file includes should use quotes. Include statements within groups should be sorted alphabetically. Inlude statements should be placed in the below order:
// Related header file
#include "subsystems/Shooter.h"
// Libraries
#include <cmath.h>
#include <ctre/Phoenix.h>
#include <frc/Encoder.h>
// Additional project files
#include "Constants.h"
#include "subsystems/Indexer.h"