Skip to content

Coding Style

Vasilaki Totsili edited this page May 31, 2026 · 4 revisions

sparq coding style

Philosophy

sparq follows the principles defined by the C++ Core Guidelines and applies additional conventions suitable for embedded systems development

The goal is to maximize:

  • Readability
  • Maintainability
  • Testability
  • Predictability
  • Portability

Code should be written for humans first and compilers second

General Rules

Prefer expressive code

Code should communicate intent clearly, should be self-documented

Good

auto motorSpeed = calculateMotorSpeed();

Bad

auto x = calculateMotorSpeed();

Keep functions small

Functions should perform a single logical operation

Good

void initializeMotor();
void configureMotor();
void startMotor();

Avoid

void initializeConfigureAndStartMotor();

Prefer compile-time safety

Prefer compile-time validation over runtime validation whenever possible

Prefer

constexpr std::uint16_t maxMotorAngle = 180;

Over

#define MAX_MOTOR_ANGLE 180

Naming Conventions

Types

Classes, structs, enums and concepts use PascalCase

class MotorController;
struct MotorConfig;
enum class Direction;

Interfaces

Interfaces use an I prefix

class IMotor;
class ISerialPort;
class IHttpClient;

Functions

Functions use camelCase

initialize();
changeMotorAngle();
getPosition();

Variables

Variables use camelCase

motorSpeed
currentPosition
serialPort

Member variables

Member variables use a leading specifier this->

this->motorSpeed
this->serialPort
this->httpClient

Constants

Constants use camelCase

constexpr std::uint32_t maxPacketSize = 1024;

Namespaces

Namespaces use camelCase

namespace sparq::hal
{
}

Classes and Interfaces

Prefer Composition

Prefer composition over inheritance

Good

class MotorService
{
private:
    IMotor& motor;
};

Avoid

class MotorService : public MotorController
{
};

Use interfaces for abstractions

Application code should depend on interfaces

Good

class MotorService
{
public:
    explicit MotorService(IMotor& motor);
};

Avoid

class MotorService
{
public:
    explicit MotorService(Esp32Motor& motor);
};

Use explicit constructors

Single-argument constructors shall be marked explicit

explicit MotorService(IMotor& motor);

Error Handling

Avoid exceptions

Exceptions are disabled in many embedded environments

Use strongly typed error codes

enum class ErrorCode
{
    Ok,
    InvalidParameter,
    InitializationFailed
};

Mark ignored results explicitly

Return values must not be silently ignored

Prefer:

[[nodiscard]]
ErrorCode initialize();

Memory Management

Avoid dynamic allocation

Dynamic allocation should be avoided after system startup

Prefer:

std::array<std::uint8_t, 256> buffer;

Over:

std::vector<std::uint8_t> buffer;

Never use raw ownership

Ownership must be explicit

Prefer:

std::unique_ptr<T>

when dynamic allocation is unavoidable

Modern C++ Usage

Prefer constexpr

constexpr auto timeoutMs = 1000U;

Prefer enum class

enum class Direction
{
    Clockwise,
    CounterClockwise
};

Prefer strong types

Avoid passing unrelated primitive values

Prefer

MotorAngle angle;
MotorSpeed speed;

Over

int angle;
int speed;

Use auto judiciously

Use auto when the type is obvious

Good

auto error = initialize();

Avoid

auto value = someComplexCalculation();

when the type is not clear

Embedded-specific rules

No global mutable state

Avoid global mutable objects

Minimize hardware dependencies

Hardware-specific code belongs in PAL

Application code must not include vendor SDK headers

Allowed

#include <sparq/hal/IMotor.hpp>

Not Allowed

#include <esp_wifi.h>

outside PAL

Prefer static polymorphism when appropriate

Use templates when runtime polymorphism is not required

Use virtual interfaces only where abstraction boundaries exist

Formatting

Indentation

Use four spaces

No tabs

Braces

Opening braces are placed on a new line

if (condition)
{
    doSomething();
}

Line length

Target 150 characters

Hard limit: 200 characters

One declaration per line

int speed;
int angle;

Not:

int speed, angle;

Examples

Good

class MotorService
{
public:
    explicit MotorService(IMotor& motor);

    [[nodiscard]]
    ErrorCode initialize();

private:
    IMotor& motor;
};

Poor

class motorservice
{
public:
    motorservice(Motor* m);

    int Init();

private:
    Motor* _m;
};

References

When guidelines conflict, the sparq coding style takes precedence

sparq-specific coding style

  • Dependency rule: Application → HAL → PAL only; never reverse!
  • Include order rule: sparq → third party libraries → standard library
  • No RTTI rule: dynamic_cast and typeid are prohibited